diff --git a/go.mod b/go.mod index 3a468ae..64979a3 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,8 @@ require ( github.com/corona10/goimagehash v1.1.0 github.com/fumiama/go-base16384 v1.7.0 github.com/fumiama/terasu v0.0.0-20241027183601-987ab91031ce + github.com/google/uuid v1.6.0 + github.com/jinzhu/gorm v1.9.16 github.com/pkg/errors v0.9.1 github.com/pkumza/numcn v1.0.0 github.com/sirupsen/logrus v1.9.3 @@ -28,7 +30,8 @@ require ( github.com/fumiama/go-simple-protobuf v0.2.0 // indirect github.com/fumiama/gofastTEA v0.0.10 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/google/uuid v1.6.0 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect @@ -40,7 +43,7 @@ require ( github.com/wdvxdr1123/ZeroBot v1.8.0 // indirect golang.org/x/net v0.24.0 // indirect golang.org/x/sys v0.26.0 // indirect - golang.org/x/text v0.19.0 // indirect + golang.org/x/text v0.20.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect modernc.org/libc v1.61.0 // indirect modernc.org/mathutil v1.6.0 // indirect diff --git a/go.sum b/go.sum index 50b4bec..63fa392 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,10 @@ github.com/FloatTech/sqlite v1.7.1 h1:XKUY0+MNaRmvEIgRv7QLbl7PFVpUfQ72+XQg+no2Vq github.com/FloatTech/sqlite v1.7.1/go.mod h1:/4tzfCGhrZnnjC1U8vcfwGQeF6eR649fhOsS3+Le0+s= github.com/FloatTech/ttl v0.0.0-20240716161252-965925764562 h1:snfw7FNFym1eNnLrQ/VCf80LiQo9C7jHgrunZDwiRcY= github.com/FloatTech/ttl v0.0.0-20240716161252-965925764562/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs= +github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7 h1:S/ferNiehVjNaBMNNBxUjLtVmP/YWD6Yh79RfPv4ehU= github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7/go.mod h1:vD7Ra3Q9onRtojoY5sMCLQ7JBgjUsrXDnDKyFxqpf9w= +github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/antchfx/htmlquery v1.3.3 h1:x6tVzrRhVNfECDaVxnZi1mEGrQg3mjE/rxbH2Pe6dNE= github.com/antchfx/htmlquery v1.3.3/go.mod h1:WeU3N7/rL6mb6dCwtE30dURBnBieKDC/fR8t6X+cKjU= github.com/antchfx/xpath v1.3.2 h1:LNjzlsSjinu3bQpw9hWMY9ocB80oLOWuQqFvO6xt51U= @@ -15,8 +17,12 @@ github.com/corona10/goimagehash v1.1.0/go.mod h1:VkvE0mLn84L4aF8vCb6mafVajEb6QYM github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM= +github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= +github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= github.com/fumiama/cron v1.3.0 h1:ZWlwuexF+HQHl3cYytEE5HNwD99q+3vNZF1GrEiXCFo= github.com/fumiama/cron v1.3.0/go.mod h1:bz5Izvgi/xEUI8tlBN8BI2jr9Moo8N4or0KV8xXuPDY= github.com/fumiama/go-base16384 v1.7.0 h1:6fep7XPQWxRlh4Hu+KsdH+6+YdUp+w6CwRXtMWSsXCA= @@ -33,12 +39,32 @@ github.com/fumiama/sqlite3 v1.29.10-simp h1:c5y3uKyU0q9t0/SyfynzYyuslQ5zP+5CD8e0 github.com/fumiama/sqlite3 v1.29.10-simp/go.mod h1:ItX2a1OVGgNsFh6Dv60JQvGfJfTPHPVpV6DF59akYOA= github.com/fumiama/terasu v0.0.0-20241027183601-987ab91031ce h1:T6iDDU16rFyxV/FwfJJR6qcgkIlXJEIFlUTSmTD1h6s= github.com/fumiama/terasu v0.0.0-20241027183601-987ab91031ce/go.mod h1:UVx8YP1jKKL1Cj+uy+OnQRM2Ih6U36Mqy9GSf7jabsI= +github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo= +github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k= +github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw= +github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ= +github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o= +github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4= +github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA= +github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= @@ -70,12 +96,19 @@ github.com/wdvxdr1123/ZeroBot v1.8.0 h1:v7m+0kGtL6XQlUH9O/LzmOntDJs2clzVj93YsAWW github.com/wdvxdr1123/ZeroBot v1.8.0/go.mod h1:C86nQ0gIdAri4K2vg8IIQIslt08zzrKMcqYt8zhkx1M= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s= golang.org/x/image v0.21.0/go.mod h1:vUbsLavqK/W303ZroQQVKQ+Af3Yl6Uz1Ppu5J/cLz78= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= @@ -83,8 +116,10 @@ golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -101,8 +136,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= -golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= @@ -113,6 +148,8 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs= +gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE= modernc.org/cc/v4 v4.21.2 h1:dycHFB/jDc3IyacKipCNSDrjIC0Lm1hyoWOZTRR20Lk= modernc.org/ccgo/v4 v4.17.8 h1:yyWBf2ipA0Y9GGz/MmCmi3EFpKgeS7ICrAFes+suEbs= modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= diff --git a/niu/db.go b/niu/db.go new file mode 100644 index 0000000..0bd1138 --- /dev/null +++ b/niu/db.go @@ -0,0 +1,61 @@ +package niu + +import ( + "fmt" + "github.com/RomiChan/syncx" + "github.com/jinzhu/gorm" +) + +var ( + migratedGroups = syncx.Map[string, bool]{} // key: string, value: bool +) + +func ensureUserInfoTable[T userInfo | AuctionInfo](gid int64, prefix string) error { + table := fmt.Sprintf("group_%d_%s_info", gid, prefix) + if _, ok := migratedGroups.Load(table); ok { + return nil + } + err := db.Table(table).AutoMigrate(new(T)).Error + if err != nil { + return err + } + + // 设置为已迁移 + migratedGroups.Store(table, true) + return nil +} + +// TableFor 大写是为了防止数据操作哪里有问题留个保底可以在zbp的项目里直接改 +func TableFor(gid int64, prefix string) *gorm.DB { + return db.Table(fmt.Sprintf("group_%d_%s_info", gid, prefix)) +} + +func listUsers(gid int64) (users, error) { + var us users + err := TableFor(gid, ur).Find(&us).Error + return us, err +} + +func listAuction(gid int64) ([]AuctionInfo, error) { + var as []AuctionInfo + err := TableFor(gid, ac).Order("money DESC").Find(&as).Error + return as, err +} + +func createUser(gid int64, user *userInfo, fix string) error { + return TableFor(gid, fix).Create(user).Error +} + +func getUserByID(gid int64, uid int64) (*userInfo, error) { + var user userInfo + err := TableFor(gid, ur).Where("user_id = ?", uid).First(&user).Error + return &user, err +} + +func updatesUserByID(gid int64, id int64, fields map[string]interface{}) error { + return TableFor(gid, ur).Where("user_id = ?", id).Updates(fields).Error +} + +func deleteUserByID(gid int64, id int64) error { + return TableFor(gid, ur).Where("user_id = ?", id).Delete(&userInfo{}).Error +} diff --git a/niu/main.go b/niu/main.go index 6388b0e..83d65ec 100644 --- a/niu/main.go +++ b/niu/main.go @@ -4,21 +4,28 @@ package niu import ( "errors" "fmt" + "github.com/google/uuid" + "github.com/jinzhu/gorm" "os" "strconv" "strings" "sync" - "time" "github.com/FloatTech/floatbox/file" - sql "github.com/FloatTech/sqlite" "github.com/FloatTech/AnimeAPI/wallet" ) +const ( + ur = "user" + ac = "auction" +) + var ( - db = &model{} + db *gorm.DB globalLock sync.Mutex + + errCancelFail = errors.New("遇到不可抗力因素,注销失败!") // ErrNoBoys 表示当前没有男孩子可用的错误。 ErrNoBoys = errors.New("暂时没有男孩子哦") @@ -63,30 +70,41 @@ func init() { panic(err) } } - db.sql = sql.New("data/niuniu/niuniu.db") - err := db.sql.Open(time.Hour * 24) + + sdb, err := gorm.Open("sqlite3", "data/niuniu/niuniu.db") if err != nil { panic(err) } + + if err = sdb.AutoMigrate(&niuNiuManager{}).Error; err != nil { + panic(err) + } + + db = sdb.LogMode(false) + } // DeleteWordNiuNiu ... func DeleteWordNiuNiu(gid, uid int64) error { globalLock.Lock() defer globalLock.Unlock() - return db.deleteWordNiuNiu(gid, uid) + if err := ensureUserInfoTable[userInfo](gid, ur); err != nil { + return err + } + return deleteUserByID(gid, uid) } // SetWordNiuNiu length > 0 就增加 , length < 0 就减小 func SetWordNiuNiu(gid, uid int64, length float64) error { globalLock.Lock() defer globalLock.Unlock() - niu, err := db.getWordNiuNiu(gid, uid) - if err != nil { + if err := ensureUserInfoTable[userInfo](gid, ur); err != nil { return err } - niu.Length += length - return db.setWordNiuNiu(gid, niu) + m := map[string]interface{}{ + "length": length, + } + return updatesUserByID(gid, uid, m) } // GetWordNiuNiu ... @@ -94,8 +112,18 @@ func GetWordNiuNiu(gid, uid int64) (float64, error) { globalLock.Lock() defer globalLock.Unlock() - niu, err := db.getWordNiuNiu(gid, uid) - return niu.Length, err + if err := ensureUserInfoTable[userInfo](gid, ur); err != nil { + return 0, err + } + + info, err := getUserByID(gid, uid) + if errors.Is(err, gorm.ErrRecordNotFound) { + return 0, ErrNoNiuNiu + } else if err != nil { + return 0, err + } + + return info.Length, err } // GetRankingInfo 获取排行信息 @@ -104,15 +132,18 @@ func GetRankingInfo(gid int64, t bool) (BaseInfos, error) { defer globalLock.Unlock() var ( list users - err error ) - niuOfGroup, err := db.getAllNiuNiuOfGroup(gid) + if err := ensureUserInfoTable[userInfo](gid, ur); err != nil { + return nil, err + } + + us, err := listUsers(gid) if err != nil { return nil, err } - list = niuOfGroup.filter(t) + list = us.filter(t) list.sort(t) if len(list) == 0 { if t { @@ -123,7 +154,7 @@ func GetRankingInfo(gid int64, t bool) (BaseInfos, error) { f := make(BaseInfos, len(list)) for i, info := range list { f[i] = BaseInfo{ - UID: info.UID, + UID: info.UserID, Length: info.Length, } } @@ -134,20 +165,29 @@ func GetRankingInfo(gid int64, t bool) (BaseInfos, error) { func GetGroupUserRank(gid, uid int64) (int, error) { globalLock.Lock() defer globalLock.Unlock() - niu, err := db.getWordNiuNiu(gid, uid) + + if err := ensureUserInfoTable[userInfo](gid, ur); err != nil { + return 0, err + } + niu, err := getUserByID(gid, uid) if err != nil { return -1, err } - group, err := db.getAllNiuNiuOfGroup(gid) + + group, err := listUsers(gid) if err != nil { return -1, err } + return group.ranking(niu.Length, uid), nil } // View 查看牛牛 func View(gid, uid int64, name string) (string, error) { - i, err := db.getWordNiuNiu(gid, uid) + if err := ensureUserInfoTable[userInfo](gid, ur); err != nil { + return "", err + } + i, err := getUserByID(gid, uid) if err != nil { return "", ErrNoNiuNiu } @@ -159,7 +199,7 @@ func View(gid, uid int64, name string) (string, error) { sexLong = "深" sex = "♀️" } - niuniuList, err := db.getAllNiuNiuOfGroup(gid) + niuniuList, err := listUsers(gid) if err != nil { return "", err } @@ -171,7 +211,10 @@ func View(gid, uid int64, name string) (string, error) { // HitGlue 打胶 func HitGlue(gid, uid int64, prop string) (string, error) { - niuniu, err := db.getWordNiuNiu(gid, uid) + if err := ensureUserInfoTable[userInfo](gid, ur); err != nil { + return "", err + } + niuniu, err := getUserByID(gid, uid) if err != nil { return "", ErrNoNiuNiuTwo } @@ -180,37 +223,62 @@ func HitGlue(gid, uid int64, prop string) (string, error) { if err != nil { return "", err } - if err = db.setWordNiuNiu(gid, niuniu); err != nil { + + if err = TableFor(gid, ur).Where("user_id = ?", uid).Save(niuniu).Error; err != nil { return "", err } + return messages, nil } // Register 注册牛牛 func Register(gid, uid int64) (string, error) { - if _, err := db.getWordNiuNiu(gid, uid); err == nil { + globalLock.Lock() + defer globalLock.Unlock() + + if err := ensureUserInfoTable[userInfo](gid, ur); err != nil { + return "", err + } + + if _, err := getUserByID(gid, uid); err == nil { return "", ErrAlreadyRegistered } // 获取初始长度 - length := db.newLength() + length := newLength() u := userInfo{ - UID: uid, + UserID: uid, + NiuID: uuid.New(), Length: length, } - if err := db.setWordNiuNiu(gid, &u); err != nil { + + if err := createUser(gid, &u, ur); err != nil { return "", err } + + if err := db.Model(&niuNiuManager{}).Create(&niuNiuManager{ + NiuID: u.NiuID, + }).Error; err != nil { + return "", err + } + return fmt.Sprintf("注册成功,你的牛牛现在有%.2fcm", u.Length), nil } // JJ ... func JJ(gid, uid, adduser int64, prop string) (message string, adduserLength float64, err error) { - myniuniu, err := db.getWordNiuNiu(gid, uid) + globalLock.Lock() + defer globalLock.Unlock() + + if err = ensureUserInfoTable[userInfo](gid, ur); err != nil { + return "", 0, ErrNoNiuNiu + } + + myniuniu, err := getUserByID(gid, uid) if err != nil { return "", 0, ErrNoNiuNiu } - adduserniuniu, err := db.getWordNiuNiu(gid, adduser) + adduserniuniu, err := getUserByID(gid, adduser) if err != nil { return "", 0, ErrAdduserNoNiuNiu } @@ -224,39 +292,65 @@ func JJ(gid, uid, adduser int64, prop string) (message string, adduserLength flo return "", 0, err } - if err = db.setWordNiuNiu(gid, myniuniu); err != nil { + if err = TableFor(gid, ur).Where("user_id =?", uid).Update("length", myniuniu.Length).Error; err != nil { return "", 0, err } - if err = db.setWordNiuNiu(gid, adduserniuniu); err != nil { + if err = TableFor(gid, ur).Where("user_id =?", adduser).Update("length", adduserniuniu.Length).Error; err != nil { return "", 0, err } adduserLength = adduserniuniu.Length - if err = db.setWordNiuNiu(gid, adduserniuniu); err != nil { - return "", 0, err - } - return } // Cancel 注销牛牛 func Cancel(gid, uid int64) (string, error) { - _, err := db.getWordNiuNiu(gid, uid) + globalLock.Lock() + defer globalLock.Unlock() + if err := ensureUserInfoTable[userInfo](gid, ur); err != nil { + return "", err + } + _, err := getUserByID(gid, uid) if err != nil { return "", ErrNoNiuNiuTwo } - err = db.deleteWordNiuNiu(gid, uid) + err = deleteUserByID(gid, uid) if err != nil { - err = errors.New("遇到不可抗力因素,注销失败!") + return "", errCancelFail } + err = db.Model(&niuNiuManager{}).Where("niu_id = ?", uid).Update("status", 2).Error return "注销成功,你已经没有牛牛了", err } // Redeem 赎牛牛 func Redeem(gid, uid int64, lastLength float64) error { + globalLock.Lock() + defer globalLock.Unlock() + if err := ensureUserInfoTable[userInfo](gid, ur); err != nil { + return err + } + + _, err := getUserByID(gid, uid) + if err != nil { + return ErrNoNiuNiu + } + + /* var n niuNiuManager + if err = db.Where("niu_id = ?", niuID).First(&n).Error; err != nil { + return err + } + + switch n.Status { + case 1: + return errors.New("你的牛牛已经被拍卖无法赎回") + case 2: + return errors.New("你的牛牛已经被注销无法赎回") + }*/ + money := wallet.GetWalletOf(uid) + if money < 150 { var builder strings.Builder walletName := wallet.GetWalletName() @@ -269,23 +363,22 @@ func Redeem(gid, uid int64, lastLength float64) error { return errors.New(builder.String()) } - if err := wallet.InsertWalletOf(uid, -150); err != nil { + if err = wallet.InsertWalletOf(uid, -150); err != nil { return err } - niu, err := db.getWordNiuNiu(gid, uid) - if err != nil { - return ErrNoNiuNiu - } - - niu.Length = lastLength - - return db.setWordNiuNiu(gid, niu) + return TableFor(gid, ur).Where("user_id = ?", uid).Update("length", lastLength).Error } // Store 牛牛商店 func Store(gid, uid int64, n int) error { - info, err := db.getWordNiuNiu(gid, uid) + globalLock.Lock() + defer globalLock.Unlock() + if err := ensureUserInfoTable[userInfo](gid, ur); err != nil { + return err + } + + info, err := getUserByID(gid, uid) if err != nil { return err } @@ -303,12 +396,20 @@ func Store(gid, uid int64, n int) error { return err } - return db.setWordNiuNiu(uid, info) + return TableFor(gid, ur).Save(info).Error } // Sell 出售牛牛 func Sell(gid, uid int64) (string, error) { - niu, err := db.getWordNiuNiu(gid, uid) + globalLock.Lock() + defer globalLock.Unlock() + if err := ensureUserInfoTable[userInfo](gid, ur); err != nil { + return "", err + } + if err := ensureUserInfoTable[AuctionInfo](gid, ac); err != nil { + return "", err + } + niu, err := getUserByID(gid, uid) if err != nil { return "", ErrNoNiuNiu } @@ -317,7 +418,7 @@ func Sell(gid, uid int64) (string, error) { return "", errors.New(message) } - if err := db.deleteWordNiuNiu(gid, uid); err != nil { + if err = deleteUserByID(gid, uid); err != nil { return "", err } @@ -326,16 +427,23 @@ func Sell(gid, uid int64) (string, error) { return message, err } - infos, _ := db.getAllNiuNiuAuction(gid) + if err = db.Model(&niu).Where("niu_id = ?", niu.NiuID).Update("status", 1).Error; err != nil { + return message, err + } u := AuctionInfo{ - ID: len(infos), - UserID: niu.UID, + UserID: uid, + NiuID: niu.NiuID, Length: niu.Length, Money: money * 2, } - err = db.setNiuNiuAuction(gid, &u) + if err = TableFor(gid, ac).Create(&u).Error; err != nil { + return "", err + } + + db.Model(&niuNiuManager{}).Where("niu_id = ?", niu.NiuID).Update("status", 1) + return message, err } @@ -343,41 +451,61 @@ func Sell(gid, uid int64) (string, error) { func ShowAuction(gid int64) ([]AuctionInfo, error) { globalLock.Lock() defer globalLock.Unlock() - return db.getAllNiuNiuAuction(gid) + if err := ensureUserInfoTable[AuctionInfo](gid, ac); err != nil { + return nil, err + } + return listAuction(gid) } // Auction 购买牛牛 func Auction(gid, uid int64, index int) (string, error) { - infos, err := db.getAllNiuNiuAuction(gid) - if err != nil { + globalLock.Lock() + defer globalLock.Unlock() + if err := ensureUserInfoTable[AuctionInfo](gid, ac); err != nil { + return "", err + } + + infos, err := listAuction(gid) + if len(infos) == 0 || err != nil { return "", ErrNoNiuNiuINAuction } - if err := wallet.InsertWalletOf(uid, -infos[index].Money); err != nil { + + var info AuctionInfo + if err = TableFor(gid, ac).Where("id = ?", index).First(&info).Error; err != nil { + return "", err + } + + if err = wallet.InsertWalletOf(uid, -info.Money); err != nil { return "", ErrNoMoney } - niu, err := db.getWordNiuNiu(gid, uid) + niu, err := getUserByID(gid, uid) if err != nil { - niu.UID = uid + niu.UserID = uid } - niu.Length = infos[index].Length + niu.Length = info.Length + niu.NiuID = info.NiuID - if infos[index].Money >= 500 { + if info.Money >= 500 { niu.WeiGe += 2 - niu.Philter += 2 + niu.MeiYao += 2 } - if err = db.deleteNiuNiuAuction(gid, uint(index)); err != nil { + if err = TableFor(gid, ac).Delete(&info).Error; err != nil { return "", err } - if err = db.setWordNiuNiu(gid, niu); err != nil { + if err = TableFor(gid, ur).Save(&niu).Error; err != nil { return "", err } - if infos[index].Money >= 500 { + if err = db.Model(&niuNiuManager{}).Where("niu_id = ?", niu.NiuID).Update("status", 0).Error; err != nil { + return "", err + } + + if info.Money >= 500 { return fmt.Sprintf("恭喜你购买成功,当前长度为%.2fcm,此次购买将赠送你2个伟哥,2个媚药", niu.Length), nil } @@ -386,7 +514,12 @@ func Auction(gid, uid int64, index int) (string, error) { // Bag 牛牛背包 func Bag(gid, uid int64) (string, error) { - niu, err := db.getWordNiuNiu(gid, uid) + globalLock.Lock() + defer globalLock.Unlock() + if err := ensureUserInfoTable[userInfo](gid, ur); err != nil { + return "", err + } + niu, err := getUserByID(gid, uid) if err != nil { return "", ErrNoNiuNiu } @@ -396,7 +529,7 @@ func Bag(gid, uid int64) (string, error) { result.WriteString("当前牛牛背包如下\n") result.WriteString(fmt.Sprintf("伟哥: %v\n", niu.WeiGe)) - result.WriteString(fmt.Sprintf("媚药: %v\n", niu.Philter)) + result.WriteString(fmt.Sprintf("媚药: %v\n", niu.MeiYao)) result.WriteString(fmt.Sprintf("击剑神器: %v\n", niu.Artifact)) result.WriteString(fmt.Sprintf("击剑神稽: %v\n", niu.ShenJi)) diff --git a/niu/models.go b/niu/models.go index 1acdc27..6324416 100644 --- a/niu/models.go +++ b/niu/models.go @@ -4,49 +4,52 @@ package niu import ( "errors" "fmt" + "github.com/google/uuid" + "github.com/jinzhu/gorm" "math" "math/rand" "sort" - "strconv" - "sync" - - sql "github.com/FloatTech/sqlite" + "time" ) var ( daJiaoProps = []string{"伟哥", "媚药"} jjPorps = []string{"击剑神器", "击剑神稽"} - query = "WHERE UID = ?" ) type users []*userInfo -type model struct { - sql sql.Sqlite - sync.RWMutex +type niuNiuManager struct { + ID uint `gorm:"primary_key"` + CreatedAt time.Time + NiuID uuid.UUID `gorm:"type:varchar(36);unique_index"` + Status int `gorm:"default:0"` // 0正常 1拍卖 2注销 } +// UserInfo 结构体 type userInfo struct { - UID int64 - Length float64 - UserCount int - WeiGe int // 伟哥 - Philter int // 媚药 - Artifact int // 击剑神器 - ShenJi int // 击剑神稽 - Buff1 int // 暂定 - Buff2 int // 暂定 - Buff3 int // 暂定 - Buff4 int // 暂定 - Buff5 int // 暂定 + gorm.Model + UserID int64 `gorm:"column:user_id;index"` + NiuID uuid.UUID `gorm:"type:char(36);index"` + Length float64 `gorm:"default:1"` + WeiGe int `gorm:"default:0"` + MeiYao int `gorm:"default:0"` + Artifact int `gorm:"default:0"` + ShenJi int `gorm:"default:0"` + Buff2 int `gorm:"default:0"` + Buff3 int `gorm:"default:0"` + Buff4 int `gorm:"default:0"` + Buff5 int `gorm:"default:0"` } -// AuctionInfo 拍卖信息 +// AuctionInfo 结构体 type AuctionInfo struct { - ID int `db:"id"` - UserID int64 `db:"user_id"` - Length float64 `db:"length"` - Money int `db:"money"` + ID uint `gorm:"primary_key"` + CreatedAt time.Time + UserID int64 `gorm:"column:user_id;index"` + NiuID uuid.UUID `gorm:"type:varchar(36);unique_index"` + Length float64 `gorm:"default:0.01"` + Money int } // BaseInfo ... @@ -100,7 +103,7 @@ func (m users) sort(isDesc bool) { func (m users) ranking(niuniu float64, uid int64) int { m.sort(niuniu > 0) for i, user := range m { - if user.UID == uid { + if user.UserID == uid { return i + 1 } } @@ -118,12 +121,12 @@ func (u *userInfo) useWeiGe() (string, float64) { }), niuniu } -func (u *userInfo) usePhilter() (string, float64) { +func (u *userInfo) useMeiYao() (string, float64) { niuniu := u.Length reduce := math.Abs(hitGlue(niuniu)) niuniu -= reduce return randomChoice([]string{ - fmt.Sprintf("你使用媚药,咿呀咿呀一下使当前长度发生了一些变化,当前长度%.2f", niuniu), + fmt.Sprintf("你使用媚药,咿呀咿呀一下使当前长度发生了一些变化,当前长度%.2fcm", niuniu), fmt.Sprintf("看来你追求的是‘微观之美’,故意使用道具让牛牛凹进去了%.2fcm!", reduce), fmt.Sprintf("缩小奇迹’在你身上发生了,牛牛凹进去了%.2fcm,你的选择真是独特!", reduce), }), niuniu @@ -187,15 +190,17 @@ func (u *userInfo) applyProp(props string) error { errMsg string }{ "伟哥": {&u.WeiGe, "你还没有伟哥呢,不能使用"}, - "媚药": {&u.Philter, "你还没有媚药呢,不能使用"}, + "媚药": {&u.MeiYao, "你还没有媚药呢,不能使用"}, "击剑神器": {&u.Artifact, "你还没有击剑神器呢,不能使用"}, "击剑神稽": {&u.ShenJi, "你还没有击剑神稽呢,不能使用"}, } - if propInfo, ok := propsMap[props]; ok { - return u.useItem(propInfo.itemCount, propInfo.errMsg) + propInfo, ok := propsMap[props] + if !ok { + return ErrPropNotFound } - return ErrPropNotFound + + return u.useItem(propInfo.itemCount, propInfo.errMsg) } func (u *userInfo) useItem(itemCount *int, errMsg string) error { @@ -203,6 +208,7 @@ func (u *userInfo) useItem(itemCount *int, errMsg string) error { *itemCount-- return nil } + fmt.Println(*u) return errors.New(errMsg) } @@ -255,7 +261,7 @@ func (u *userInfo) purchaseItem(n int) (int, error) { u.WeiGe += 5 case 2: money = 300 - u.Philter += 5 + u.MeiYao += 5 case 3: money = 500 u.Artifact += 2 @@ -268,20 +274,16 @@ func (u *userInfo) purchaseItem(n int) (int, error) { return money, err } -func (u *userInfo) processDaJiao(props string) (string, error) { - var ( - messages string - info userInfo - err error - f float64 - ) - info = *u +func (u *userInfo) processDaJiao(props string) (messages string, err error) { + var f float64 + + info := *u if props != "" { - err := u.checkProps(props, "dajiao") + err = u.checkProps(props, "dajiao") if err != nil { return "", err } - if err := u.applyProp(props); err != nil { + if err = u.applyProp(props); err != nil { return "", err } } @@ -289,16 +291,14 @@ func (u *userInfo) processDaJiao(props string) (string, error) { case u.WeiGe-info.WeiGe != 0: messages, f = u.useWeiGe() u.Length = f - - case u.Philter-info.Philter != 0: - messages, f = u.usePhilter() + case u.MeiYao-info.MeiYao != 0: + messages, f = u.useMeiYao() u.Length = f - default: messages, f = hitGlueNiuNiu(u.Length) u.Length = f } - return messages, err + return } func (u *userInfo) processJJ(adduserniuniu *userInfo, props string) (string, error) { @@ -311,11 +311,11 @@ func (u *userInfo) processJJ(adduserniuniu *userInfo, props string) (string, err ) info = *u if props != "" { - err := u.checkProps(props, "jj") + err = u.checkProps(props, "jj") if err != nil { return "", err } - if err := u.applyProp(props); err != nil { + if err = u.applyProp(props); err != nil { return "", err } } @@ -338,83 +338,6 @@ func (u *userInfo) processJJ(adduserniuniu *userInfo, props string) (string, err return fencingResult, err } -func (db *model) newLength() float64 { +func newLength() float64 { return float64(rand.Intn(9)+1) + (float64(rand.Intn(100)) / 100) } - -func (db *model) getWordNiuNiu(gid, uid int64) (*userInfo, error) { - db.RLock() - defer db.RUnlock() - - var u userInfo - err := db.sql.Find(strconv.FormatInt(gid, 10), &u, query, uid) - return &u, err -} - -func (db *model) setWordNiuNiu(gid int64, u *userInfo) error { - db.Lock() - defer db.Unlock() - err := db.sql.Insert(strconv.FormatInt(gid, 10), u) - if err != nil { - err = db.sql.Create(strconv.FormatInt(gid, 10), &userInfo{}) - if err != nil { - return err - } - err = db.sql.Insert(strconv.FormatInt(gid, 10), u) - } - return err -} - -func (db *model) deleteWordNiuNiu(gid, uid int64) error { - db.Lock() - defer db.Unlock() - return db.sql.Del(strconv.FormatInt(gid, 10), query, uid) -} - -func (db *model) getAllNiuNiuOfGroup(gid int64) (users, error) { - db.Lock() - defer db.Unlock() - var user userInfo - var useras users - err := db.sql.FindFor(fmt.Sprintf("%d", gid), &user, "", - func() error { - newUser := user - useras = append(useras, &newUser) - return nil - }) - return useras, err -} - -func (db *model) setNiuNiuAuction(gid int64, u *AuctionInfo) error { - db.Lock() - defer db.Unlock() - err := db.sql.Insert(fmt.Sprintf("auction_%d", gid), u) - if err != nil { - err = db.sql.Create(fmt.Sprintf("auction_%d", gid), &AuctionInfo{}) - if err != nil { - return err - } - err = db.sql.Insert(fmt.Sprintf("auction_%d", gid), u) - } - return err -} - -func (db *model) deleteNiuNiuAuction(gid int64, id uint) error { - db.Lock() - defer db.Unlock() - return db.sql.Del(fmt.Sprintf("auction_%d", gid), "WHERE id = ?", id) -} - -func (db *model) getAllNiuNiuAuction(gid int64) ([]AuctionInfo, error) { - db.RLock() - defer db.RUnlock() - var user AuctionInfo - var useras []AuctionInfo - err := db.sql.FindFor(fmt.Sprintf("auction_%d", gid), &user, "", - func() error { - useras = append(useras, user) - return nil - }) - - return useras, err -} diff --git a/niu/test_test.go b/niu/test_test.go index 4cfae11..913a332 100644 --- a/niu/test_test.go +++ b/niu/test_test.go @@ -4,7 +4,7 @@ import "testing" func TestCreateUserInfoByProps(t *testing.T) { user := &userInfo{ - UID: 123, + UserID: 123, Length: 12, WeiGe: 2, } @@ -17,7 +17,7 @@ func TestCreateUserInfoByProps(t *testing.T) { func TestCheckProp(t *testing.T) { user := &userInfo{ - UID: 123, + UserID: 123, Length: 12, WeiGe: 2, } diff --git a/niu/utils.go b/niu/utils.go index 2322990..9bb8894 100644 --- a/niu/utils.go +++ b/niu/utils.go @@ -222,20 +222,24 @@ func fence(rd float64) float64 { } func hitGlue(l float64) float64 { - if l == 0 { + l = math.Abs(l) + if l < 0.1 { l = 0.1 } - l = math.Abs(l) + + var logValue float64 switch { - case l > 1 && l <= 10: - return rand.Float64() * math.Log2(l*2) - case 10 < l && l <= 100: - return rand.Float64() * math.Log2(l*1.5) - case 100 < l && l <= 1000: - return rand.Float64() * (math.Log10(l*1.5) * 2) case l > 1000: - return rand.Float64() * (math.Log10(l) * 2) - default: - return rand.Float64() + logValue = math.Log10(l) * 2 + case l > 100: + logValue = math.Log10(l*1.5) * 2 + case l > 10: + logValue = math.Log2(l * 1.5) + case l > 1: + logValue = math.Log2(l * 2) + default: // 0.1 <= l <= 1 + logValue = 1 } + + return rand.Float64() * logValue }