diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..eda6242 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,22 @@ +{ + // 使用 IntelliSense 了解相关属性。 + // 悬停以查看现有属性的描述。 + // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Attach to Process", + "type": "go", + "request": "attach", + "mode": "local", + "processId": "${command:pickGoProcess}" + }, + { + "name": "Launch Package", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index eb77020..4a8e14e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,12 @@ FROM git.vaala.cloud/vaalacat/golang:1.20 AS builder -WORKDIR $GOPATH/src/mcbot -COPY . . -RUN mkdir /app && \ - CGO_ENABLED=0 GOPROXY=https://goproxy.cn,direct go build -o mcbot main.go && \ - cp mcbot /app/ +# WORKDIR $GOPATH/src/mcbot +# COPY . . +# RUN mkdir /app && \ +# CGO_ENABLED=0 GOPROXY=https://goproxy.cn,direct go build -o mcbot main.go && \ +# cp mcbot /app/ FROM git.vaala.cloud/vaalacat/alpine -COPY --from=builder /app/mcbot /app/mcbot +# COPY --from=builder /app/mcbot /app/mcbot +COPY mcbot /app/mcbot ENTRYPOINT [ "/app/mcbot" ] \ No newline at end of file diff --git a/conf/env.go b/conf/env.go index cab31e3..d07878a 100644 --- a/conf/env.go +++ b/conf/env.go @@ -1,51 +1,28 @@ package conf import ( - "os" - "strconv" - + "github.com/ilyakaznacheev/cleanenv" "github.com/joho/godotenv" - "github.com/sirupsen/logrus" ) type botSettings struct { - HTTPProxy string - BotToken string - MCServer string - MCBotName string - GroupID int64 + HTTPProxy string `env:"HTTP_PROXY"` + BotToken string `env:"BOT_TOKEN"` + MCServer string `env:"MC_SERVER"` + MCBotName string `env:"MC_BOT_NAME"` + GroupID int64 `env:"GROUP_ID"` + DBPath string `env:"DB_PATH"` } var ( - botSettingsInstance *botSettings + botSettingsInstance botSettings ) func init() { godotenv.Load() - http_proxy := os.Getenv("HTTP_PROXY") - bot_token := os.Getenv("BOT_TOKEN") - mc_server := os.Getenv("MC_SERVER") - mc_bot_name := os.Getenv("MC_BOT_NAME") - group_id_str := os.Getenv("GROUP_ID") - - if http_proxy == "" || bot_token == "" || mc_server == "" || mc_bot_name == "" || group_id_str == "" { - logrus.Panic("请检查环境变量是否设置正确") - } - - group_id, err := strconv.ParseInt(group_id_str, 10, 64) - if err != nil { - logrus.Panic("请检查环境变量是否设置正确") - } - - botSettingsInstance = &botSettings{ - HTTPProxy: http_proxy, - BotToken: bot_token, - MCServer: mc_server, - MCBotName: mc_bot_name, - GroupID: group_id, - } + cleanenv.ReadEnv(&botSettingsInstance) } func GetBotSettings() *botSettings { - return botSettingsInstance + return &botSettingsInstance } diff --git a/db.sqlite b/db.sqlite new file mode 100644 index 0000000..8e31b19 Binary files /dev/null and b/db.sqlite differ diff --git a/go.mod b/go.mod index 5a978ed..4451248 100644 --- a/go.mod +++ b/go.mod @@ -4,13 +4,34 @@ go 1.20 require ( github.com/Tnze/go-mc v1.19.4-pre1 + github.com/glebarez/sqlite v1.8.0 github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 github.com/joho/godotenv v1.5.1 github.com/sirupsen/logrus v1.9.1 + gorm.io/gorm v1.25.1 ) require ( + github.com/BurntSushi/toml v1.3.2 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/glebarez/go-sqlite v1.21.1 // indirect + github.com/go-co-op/gocron v1.28.3 // indirect github.com/google/uuid v1.3.0 // indirect github.com/iancoleman/strcase v0.2.0 // indirect - golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect + github.com/ilyakaznacheev/cleanenv v1.4.2 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + github.com/robfig/cron/v3 v3.0.1 // indirect + go.uber.org/atomic v1.9.0 // indirect + golang.org/x/sys v0.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + modernc.org/libc v1.22.3 // indirect + modernc.org/mathutil v1.5.0 // indirect + modernc.org/memory v1.5.0 // indirect + modernc.org/sqlite v1.21.1 // indirect + olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect ) + +replace github.com/Tnze/go-mc => /Users/vaala/Workdir/Code/go-mc diff --git a/go.sum b/go.sum index 3a68176..b9514d6 100644 --- a/go.sum +++ b/go.sum @@ -1,25 +1,86 @@ -github.com/Tnze/go-mc v1.19.4-pre1 h1:0yBCeK9EGICdIzxSPbvD88HqcNRho8PRgKtpAC02W0E= -github.com/Tnze/go-mc v1.19.4-pre1/go.mod h1:c1znJQglgqa1Jjs3Dr29woN/msguiJrlNtWXhKedh2U= +github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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/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/glebarez/go-sqlite v1.21.1 h1:7MZyUPh2XTrHS7xNEHQbrhfMZuPSzhkm2A1qgg0y5NY= +github.com/glebarez/go-sqlite v1.21.1/go.mod h1:ISs8MF6yk5cL4n/43rSOmVMGJJjHYr7L2MbZZ5Q4E2E= +github.com/glebarez/sqlite v1.8.0 h1:02X12E2I/4C1n+v90yTqrjRa8yuo7c3KeHI3FRznCvc= +github.com/glebarez/sqlite v1.8.0/go.mod h1:bpET16h1za2KOOMb8+jCp6UBP/iahDpfPQqSaYLTLx8= +github.com/go-co-op/gocron v1.28.3 h1:swTsge6u/1Ei51b9VLMz/YTzEzWpbsk5SiR7m5fklTI= +github.com/go-co-op/gocron v1.28.3/go.mod h1:39f6KNSGVOU1LO/ZOoZfcSxwlsJDQOKSu8erN0SH48Y= github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 h1:wG8n/XJQ07TmjbITcGiUaOtXxdrINDz1b0J1w0SzqDc= github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1/go.mod h1:A2S0CWkNylc2phvKXWBBdD3K0iGnDBGbzRpISP2zBl8= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/ilyakaznacheev/cleanenv v1.4.2 h1:nRqiriLMAC7tz7GzjzUTBHfzdzw6SQ7XvTagkFqe/zU= +github.com/ilyakaznacheev/cleanenv v1.4.2/go.mod h1:i0owW+HDxeGKE0/JPREJOdSCPIyOnmh6C0xhWAkF/xA= +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.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/sirupsen/logrus v1.9.1 h1:Ou41VVR3nMWWmTiEUnj0OlsgOSCUFgsPAOl6jRIcVtQ= github.com/sirupsen/logrus v1.9.1/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 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.25.1 h1:nsSALe5Pr+cM3V1qwwQ7rOkw+6UeLrX5O4v3llhHa64= +gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +modernc.org/libc v1.22.3 h1:D/g6O5ftAfavceqlLOFwaZuA5KYafKwmr30A6iSqoyY= +modernc.org/libc v1.22.3/go.mod h1:MQrloYP209xa2zHome2a8HLiLm6k0UT8CoHpV74tOFw= +modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds= +modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/sqlite v1.21.1 h1:GyDFqNnESLOhwwDRaHGdp2jKLDzpyT/rNLglX3ZkMSU= +modernc.org/sqlite v1.21.1/go.mod h1:XwQ0wZPIh1iKb5mkvCJ3szzbhk+tykC8ZWqTRTgYRwI= +olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 h1:slmdOY3vp8a7KQbHkL+FLbvbkgMqmXojpFUO/jENuqQ= +olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3/go.mod h1:oVgVk4OWVDi43qWBEyGhXgYxt7+ED4iYNpTngSLX2Iw= diff --git a/mcbot b/mcbot new file mode 100755 index 0000000..8d2fb57 Binary files /dev/null and b/mcbot differ diff --git a/models/user.go b/models/user.go new file mode 100644 index 0000000..b61e8d3 --- /dev/null +++ b/models/user.go @@ -0,0 +1,52 @@ +package models + +import ( + "tg-mc/utils/database" + + "github.com/sirupsen/logrus" + "gorm.io/gorm" +) + +type User struct { + gorm.Model + TGID int64 + MCName string + Status int // 0: pending, 1: normal, 2: banned +} + +func init() { + if err := database.GetDB().AutoMigrate(&User{}); err != nil { + logrus.Panic(err) + } +} + +func (u *User) TableName() string { + return "users" +} + +func GetUserByTGID(tgID int64) (user User, err error) { + err = database.GetDB().Where( + &User{TGID: tgID}, + ).First(&user).Error + return +} + +func GetUserByMCName(mcName string) (user User, err error) { + err = database.GetDB().Where( + &User{MCName: mcName}, + ).First(&user).Error + return +} + +func CreateUserIfNotExist(tgID int64, u *User) (err error) { + err = database.GetDB().Where( + &User{TGID: tgID}, + ).FirstOrCreate(&u).Error + return +} + +func (u *User) Delete(tgID int64) error { + return database.GetDB().Where( + &User{TGID: tgID}, + ).Delete(&u).Error +} diff --git a/services/mc/defs.go b/services/mc/defs.go new file mode 100644 index 0000000..8aa2d22 --- /dev/null +++ b/services/mc/defs.go @@ -0,0 +1,16 @@ +package mc + +const ( + ErrNotJoined = "not joined" +) + +const ( + EventPlayerJoined = "multiplayer.player.joined" + EventPlayerLeft = "multiplayer.player.left" +) + +const ( + StatusPending = iota + StatusNormal + StatusBanned +) diff --git a/services/mc/helper.go b/services/mc/helper.go new file mode 100644 index 0000000..973dae7 --- /dev/null +++ b/services/mc/helper.go @@ -0,0 +1,89 @@ +package mc + +import ( + "crypto/rand" + "encoding/binary" + "errors" + "tg-mc/conf" + "tg-mc/models" + su "tg-mc/services/utils" + "tg-mc/utils" + "time" + + "github.com/Tnze/go-mc/chat" + "github.com/Tnze/go-mc/data/packetid" + "github.com/Tnze/go-mc/net/packet" + "github.com/sirupsen/logrus" +) + +func GetJoinedPlayer(m chat.Message) (userName string, err error) { + if m.Translate != "multiplayer.player.joined" && len(m.With) == 0 { + return "", errors.New(ErrNotJoined) + } + userName = m.With[0].Text + return +} + +func GetLeftPlayer(m chat.Message) (userName string, err error) { + if m.Translate != "multiplayer.player.left" && len(m.With) == 0 { + return "", errors.New(ErrNotJoined) + } + userName = m.With[0].Text + return +} + +func HandleJoinGame(userName string) { + + u, err := models.GetUserByMCName(userName) + if err != nil { + logrus.Error("get user name error: ", err) + } + time.Sleep(3 * time.Second) + + switch u.Status { + case StatusNormal: + SendMsgToPlayer("欢迎回来!", userName) + case StatusPending: + SendMsgToPlayer("你还没有绑定 Telegram 哦, 5秒后你将会被踢出。请在群组中发送 /bind <你的 MC 用户名> 进行绑定。", userName) + time.Sleep(5 * time.Second) + kickPlayer(userName) + case StatusBanned: + SendMsgToPlayer("你已被封禁,如有疑问请联系管理员。", userName) + default: + SendMsgToPlayer("未知错误,请联系管理员,你将被踢出", userName) + time.Sleep(3 * time.Second) + kickPlayer(userName) + } +} + +func sendCommand(cmd string) error { + var salt int64 + if err := binary.Read(rand.Reader, binary.BigEndian, &salt); err != nil { + return err + } + + err := conf.Client.Conn.WritePacket(packet.Marshal( + packetid.ServerboundChatCommand, + packet.String(cmd), + packet.Long(time.Now().UnixMilli()), + packet.Long(salt), + packet.VarInt(0), // signature + packet.VarInt(0), + packet.NewFixedBitSet(20), + )) + return err +} + +func kickPlayer(userName string) error { + err := sendCommand("kick " + userName) + return err +} + +func CronKick() { + utils.CronStart(func() { + users := su.GetAlivePlayerList() + for _, u := range users { + kickPlayer(u) + } + }) +} diff --git a/services/mc/mc.go b/services/mc/mc.go index 2c3f7d6..7003076 100644 --- a/services/mc/mc.go +++ b/services/mc/mc.go @@ -13,7 +13,6 @@ import ( "github.com/Tnze/go-mc/bot/playerlist" "github.com/Tnze/go-mc/bot/screen" "github.com/Tnze/go-mc/chat" - "github.com/Tnze/go-mc/data/item" tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" "github.com/sirupsen/logrus" ) @@ -36,9 +35,8 @@ func Run() error { DisguisedChat: onDisguisedMsg, }) conf.ScreenManager = screen.NewManager(client, screen.EventsListener{ - Open: nil, - SetSlot: onScreenSlotChange, - Close: nil, + Open: nil, + Close: nil, }) err := client.JoinServer( @@ -54,16 +52,38 @@ func Run() error { return client.HandleGame() } -func SendMsg(msg string) error { - if err := conf.ChatHandler.SendMessage(msg); err != nil { - return err - } - return nil +func SendMsg(msg string) { + go func() { + err := conf.ChatHandler.SendMessage(msg) + if err != nil { + logrus.Error("send msg error: ", err) + } + }() +} + +func SendMsgToPlayer(msg string, playerName string) { + go func() { + err := sendCommand(fmt.Sprintf("tell %s %s", playerName, msg)) + if err != nil { + logrus.Error("send msg to player error: ", err) + } + }() } func onSystemMsg(msg chat.Message, overlay bool) error { go func() { - log.Printf("System: %v", msg) + log.Printf("System: %v", msg.String()) + switch msg.Translate { + case EventPlayerJoined: + userName, err := GetJoinedPlayer(msg) + if err != nil { + logrus.Error("user join error ", err) + break + } + go HandleJoinGame(userName) + default: + break + } m := tgbotapi.NewMessage(conf.GetBotSettings().GroupID, fmt.Sprintf("%v", msg)) conf.Bot.Send(m) }() @@ -110,30 +130,14 @@ func onDeath() error { } func onGameStart() error { - log.Println("Game start") + go func() { + log.Println("Game start") + // SendMsgToPlayer("Hello", "test") + go CronKick() + }() return nil // if err isn't nil, HandleGame() will return it. } -func onScreenSlotChange(id, index int) error { - if id == -2 { - log.Printf("Slot: inventory: %v", conf.ScreenManager.Inventory.Slots[index]) - } else if id == -1 && index == -1 { - log.Printf("Slot: cursor: %v", conf.ScreenManager.Cursor) - } else { - container, ok := conf.ScreenManager.Screens[id] - if ok { - // Currently, only inventory container is supported - switch container.(type) { - case *screen.Inventory: - slot := container.(*screen.Inventory).Slots[index] - itemInfo := item.ByID[item.ID(slot.ID)] - log.Printf("Slot: Screen[%d].Slot[%d]: [%v] * %d | NBT: %v", id, index, itemInfo, slot.Count, slot.NBT) - } - } - } - return nil -} - func onHealthChange(health float32, foodLevel int32, foodSaturation float32) error { log.Printf("Health: %.2f, FoodLevel: %d, FoodSaturation: %.2f", health, foodLevel, foodSaturation) return nil diff --git a/services/tgbot/bot.go b/services/tgbot/bot.go index f134f60..0642506 100644 --- a/services/tgbot/bot.go +++ b/services/tgbot/bot.go @@ -6,13 +6,14 @@ import ( "net/http" "net/url" "tg-mc/conf" + "tg-mc/models" "tg-mc/services/utils" tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" "github.com/sirupsen/logrus" ) -func Run(sendFunc func(string) error) { +func Run(sendFunc func(string)) { var err error HttpProxy := conf.GetBotSettings().HTTPProxy @@ -41,18 +42,52 @@ func Run(sendFunc func(string) error) { for update := range updates { if update.Message != nil { - logrus.Infof("[%s] %s", update.Message.From.UserName, update.Message.Text) - if update.Message.Command() == "talk" { - logrus.Infof("id is %d", update.Message.Chat.ID) - m := fmt.Sprintf("%v: %v", update.Message.From.UserName, update.Message.CommandArguments()) - err := sendFunc(m) - logrus.WithError(err).Error("send message error") - } - if update.Message.Command() == "list" { - logrus.Infof("id is %d", update.Message.Chat.ID) - m := tgbotapi.NewMessage(update.Message.Chat.ID, utils.GetAlivePlayer()) - conf.Bot.Send(m) - } + go func(m *tgbotapi.Message) { + logrus.Infof("[%s] %s", m.From.UserName, m.Text) + if m.Command() == "talk" { + logrus.Infof("id is %d", m.Chat.ID) + m := fmt.Sprintf("%v: %v", m.From.UserName, m.CommandArguments()) + sendFunc(m) + logrus.WithError(err).Error("send message error") + return + } + if m.Command() == "list" { + logrus.Infof("id is %d", m.Chat.ID) + m := tgbotapi.NewMessage(m.Chat.ID, utils.GetAlivePlayer()) + conf.Bot.Send(m) + return + } + if m.Command() == "bind" { + logrus.Infof("id is %d", m.Chat.ID) + models.CreateUserIfNotExist(m.From.ID, &models.User{ + TGID: m.From.ID, + MCName: m.CommandArguments(), + Status: 1, + }) + m := tgbotapi.NewMessage(m.Chat.ID, + fmt.Sprintf("绑定成功,你的MCID是%v", m.CommandArguments())) + conf.Bot.Send(m) + return + } + if m.Command() == "unbind" { + logrus.Infof("id is %d", m.Chat.ID) + u, err := models.GetUserByTGID(m.From.ID) + if err != nil { + m := tgbotapi.NewMessage(m.Chat.ID, "你还没有绑定") + conf.Bot.Send(m) + return + } + err = u.Delete(m.From.ID) + if err != nil { + m := tgbotapi.NewMessage(m.Chat.ID, "解绑失败") + conf.Bot.Send(m) + return + } + m := tgbotapi.NewMessage(m.Chat.ID, "解绑成功") + conf.Bot.Send(m) + return + } + }(update.Message) } } } diff --git a/services/utils/mc.go b/services/utils/mc.go index 757c172..5b6f1b3 100644 --- a/services/utils/mc.go +++ b/services/utils/mc.go @@ -9,3 +9,14 @@ func GetAlivePlayer() string { } return ans } + +func GetAlivePlayerList() []string { + ans := []string{} + for _, v := range conf.PlayerList.PlayerInfos { + if v.Name == conf.GetBotSettings().MCBotName { + continue + } + ans = append(ans, v.Name) + } + return ans +} diff --git a/utils/cron.go b/utils/cron.go new file mode 100644 index 0000000..8822858 --- /dev/null +++ b/utils/cron.go @@ -0,0 +1,16 @@ +package utils + +import ( + "time" + + "github.com/go-co-op/gocron" +) + +var ( + s = gocron.NewScheduler(time.UTC) +) + +func CronStart(f func()) { + s.Every("1m").Do(f) + s.StartAsync() +} diff --git a/utils/database/db.go b/utils/database/db.go new file mode 100644 index 0000000..bea388a --- /dev/null +++ b/utils/database/db.go @@ -0,0 +1,24 @@ +package database + +import ( + "github.com/joho/godotenv" + "github.com/sirupsen/logrus" + "gorm.io/gorm" +) + +func init() { + godotenv.Load() + initSqlite() +} + +func GetDB() *gorm.DB { + return GetSqlite() +} + +func CloseDB(db *gorm.DB) { + tdb, err := db.DB() + if err != nil { + logrus.WithError(err).Errorf("Close DB error") + } + tdb.Close() +} diff --git a/utils/database/sqlite.go b/utils/database/sqlite.go new file mode 100644 index 0000000..af50dfb --- /dev/null +++ b/utils/database/sqlite.go @@ -0,0 +1,31 @@ +package database + +import ( + "tg-mc/conf" + + "github.com/glebarez/sqlite" + "github.com/joho/godotenv" + "github.com/sirupsen/logrus" + "gorm.io/gorm" +) + +func initSqlite() { + var err error + godotenv.Load() + + dbPath := conf.GetBotSettings().DBPath + db, err := gorm.Open(sqlite.Open(dbPath), &gorm.Config{}) + if err != nil { + logrus.Panic(err, "Initializing DB Error") + } + CloseDB(db) +} + +func GetSqlite() *gorm.DB { + dbPath := conf.GetBotSettings().DBPath + db, err := gorm.Open(sqlite.Open(dbPath), &gorm.Config{}) + if err != nil { + return nil + } + return db +}