From df67445aaab7bfe8772d3f51256f66b787480993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E8=B6=85=E8=B6=8A?= <993921@qq.com> Date: Sat, 16 Mar 2024 09:19:51 +0800 Subject: [PATCH 01/11] WIP: turn to local --- telegram/root.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/telegram/root.go b/telegram/root.go index 7a5b376..9cf2b0f 100644 --- a/telegram/root.go +++ b/telegram/root.go @@ -13,7 +13,9 @@ var Bot *tb.Bot // BotStart 机器人启动 func BotStart() { setting := tb.Settings{ - Token: config.TelegramC.BotToken, + Token: func() string { + config.TelegramC.BotToken, + }(), Updates: 100, Poller: &tb.LongPoller{Timeout: 10 * time.Second, AllowedUpdates: []string{ "message", From 99eeb678857e3eb52c6e2030cc521ac51f3e637d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E8=B6=85=E8=B6=8A?= <993921@qq.com> Date: Sat, 16 Mar 2024 09:40:12 +0800 Subject: [PATCH 02/11] from env --- Dockerfile | 4 ++-- telegram/root.go | 16 +++++++++++----- util/config/config.go | 20 +++++++++++++++++++- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/Dockerfile b/Dockerfile index 582a883..165f0b8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,8 +10,8 @@ ENV CGO_ENABLED=1 \ GOOS=linux \ GOARCH=amd64 \ CC=x86_64-linux-musl-gcc \ - CXX=x86_64-linux-musl-g++ \ - GOPROXY=https://goproxy.cn,direct + CXX=x86_64-linux-musl-g++ + # GOPROXY=https://goproxy.cn,direct RUN go mod download RUN go mod verify diff --git a/telegram/root.go b/telegram/root.go index 9cf2b0f..4a7e594 100644 --- a/telegram/root.go +++ b/telegram/root.go @@ -1,11 +1,13 @@ package telegram import ( + "log" + "os" + "time" + "github.com/assimon/captcha-bot/util/config" ulog "github.com/assimon/captcha-bot/util/log" tb "gopkg.in/telebot.v3" - "log" - "time" ) var Bot *tb.Bot @@ -13,8 +15,12 @@ var Bot *tb.Bot // BotStart 机器人启动 func BotStart() { setting := tb.Settings{ - Token: func() string { - config.TelegramC.BotToken, + Token: func() string { + if token := os.Getenv("bot_token"); len(token) > 0 { + return token + } else { + return config.TelegramC.BotToken + } }(), Updates: 100, Poller: &tb.LongPoller{Timeout: 10 * time.Second, AllowedUpdates: []string{ @@ -94,7 +100,7 @@ func isManage(chat *tb.Chat, userId int64) bool { // isRoot 判断是否为超管 func isRoot(userid int64) bool { - for _, id := range config.TelegramC.ManageUsers { + for _, id := range config.TelegramC.GetManageUsers() { if userid == id { return true } diff --git a/util/config/config.go b/util/config/config.go index 00dd733..e6c6e8d 100644 --- a/util/config/config.go +++ b/util/config/config.go @@ -1,9 +1,12 @@ package config import ( - "github.com/spf13/viper" "log" "os" + "strconv" + "strings" + + "github.com/spf13/viper" ) var AppPath string @@ -22,6 +25,21 @@ type Telegram struct { ManageUsers []int64 `mapstructure:"manage_users"` } +func (tel *Telegram) GetManageUsers() []int64 { + if len(tel.ManageUsers) == 0 { + if users := os.Getenv("managers"); len(users) > 0 { + if userArr := strings.Split(users, ","); len(userArr) > 0 { + tel.ManageUsers = make([]int64, len(userArr)) + for i, uid := range userArr { + uid64, _ := strconv.Atoi(uid) + tel.ManageUsers[i] = int64(uid64) + } + } + } + } + return tel.ManageUsers +} + var TelegramC Telegram type Log struct { From f51bfabf9bc28457d1c76441ae17a578aeb3c763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E8=B6=85=E8=B6=8A?= <993921@qq.com> Date: Sat, 16 Mar 2024 10:56:09 +0800 Subject: [PATCH 03/11] wip: dockerfile --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 373dd06..33c29c8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,6 +20,7 @@ RUN go build -ldflags '-linkmode external -extldflags "-static"' -o captcha-bot FROM alpine:latest COPY --from=builder /app/captcha-bot /work/captcha-bot +COPY --from=builder /app/captcha-bot/config /work/captcha-bot/config WORKDIR /work From 51284cfee4fa9330c4e6cd332334988065d98ee2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E8=B6=85=E8=B6=8A?= <993921@qq.com> Date: Sat, 16 Mar 2024 10:58:58 +0800 Subject: [PATCH 04/11] wip --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 33c29c8..cd468b4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,7 +20,7 @@ RUN go build -ldflags '-linkmode external -extldflags "-static"' -o captcha-bot FROM alpine:latest COPY --from=builder /app/captcha-bot /work/captcha-bot -COPY --from=builder /app/captcha-bot/config /work/captcha-bot/config +COPY --from=builder /app/captcha-bot/config/* /work/captcha-bot/config/ WORKDIR /work From f1d81e7a777710f11547c332afebc2dd3e078db7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E8=B6=85=E8=B6=8A?= <993921@qq.com> Date: Sat, 16 Mar 2024 11:04:18 +0800 Subject: [PATCH 05/11] wip2 --- Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index cd468b4..488885f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,8 +19,7 @@ RUN go build -ldflags '-linkmode external -extldflags "-static"' -o captcha-bot FROM alpine:latest -COPY --from=builder /app/captcha-bot /work/captcha-bot -COPY --from=builder /app/captcha-bot/config/* /work/captcha-bot/config/ +COPY --from=builder /app /work WORKDIR /work From b392da23633bdb255eed94d4dfd1272f2d132632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E8=B6=85=E8=B6=8A?= <993921@qq.com> Date: Sun, 17 Mar 2024 11:51:43 +0800 Subject: [PATCH 06/11] chore: allow Access-Control-Allow-Origin when health check --- .gitignore | 4 +++- main.go | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 4cfda1d..e538900 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,9 @@ runtime/ .env dist/ config.*.toml +config.toml db/geecaptcha.db captcha-bot dict/dec_* -.vscode \ No newline at end of file +.vscode +vendor \ No newline at end of file diff --git a/main.go b/main.go index 00f85bd..79fbaab 100644 --- a/main.go +++ b/main.go @@ -2,14 +2,14 @@ package main import ( "fmt" - "net/http" - "github.com/assimon/captcha-bot/bootstrap" + "net/http" ) func main() { go func() { http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Access-Control-Allow-Origin", "*") fmt.Fprintf(w, "OK") }) http.ListenAndServe(":80", nil) From b17d720f2dfdae38eae66d1c54e79c0dbd8392ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E8=B6=85=E8=B6=8A?= <993921@qq.com> Date: Sun, 17 Mar 2024 13:32:33 +0800 Subject: [PATCH 07/11] chore: prevent to sleep --- main.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/main.go b/main.go index 79fbaab..180fa79 100644 --- a/main.go +++ b/main.go @@ -3,7 +3,9 @@ package main import ( "fmt" "github.com/assimon/captcha-bot/bootstrap" + "io" "net/http" + "time" ) func main() { @@ -15,5 +17,19 @@ func main() { http.ListenAndServe(":80", nil) }() + go func() { + t := time.NewTimer(time.Second * 10) + for { + if resp, err := http.Get("https://captcha-bot-zg9p.onrender.com/healthz"); err != nil { + fmt.Println(fmt.Sprintf("err:%v", err)) + } else { + if b, err := io.ReadAll(resp.Body); err == nil { + fmt.Println("health: " + string(b)) + } + } + <-t.C + } + }() + bootstrap.Start() } From 388fd538bf56075db5b272ef76d3b663ec3aa10d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E8=B6=85=E8=B6=8A?= <993921@qq.com> Date: Sun, 17 Mar 2024 14:12:20 +0800 Subject: [PATCH 08/11] chore: prevent to sleep --- main.go | 17 +++++++++++------ telegram/root.go | 12 +++++++++++- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/main.go b/main.go index 180fa79..8a5b9e8 100644 --- a/main.go +++ b/main.go @@ -4,30 +4,35 @@ import ( "fmt" "github.com/assimon/captcha-bot/bootstrap" "io" + "log" "net/http" + "strconv" "time" ) +var counter = 0 + func main() { go func() { http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { + counter++ w.Header().Set("Access-Control-Allow-Origin", "*") - fmt.Fprintf(w, "OK") + _, _ = fmt.Fprintf(w, "OK, checker: "+strconv.Itoa(counter)) }) - http.ListenAndServe(":80", nil) + _ = http.ListenAndServe(":80", nil) }() go func() { - t := time.NewTimer(time.Second * 10) + t := time.Tick(time.Second * 10) for { if resp, err := http.Get("https://captcha-bot-zg9p.onrender.com/healthz"); err != nil { - fmt.Println(fmt.Sprintf("err:%v", err)) + log.Default().Printf("error: " + err.Error()) } else { if b, err := io.ReadAll(resp.Body); err == nil { - fmt.Println("health: " + string(b)) + log.Default().Printf("health: " + string(b)) } } - <-t.C + <-t } }() diff --git a/telegram/root.go b/telegram/root.go index 4a7e594..a4264e6 100644 --- a/telegram/root.go +++ b/telegram/root.go @@ -2,6 +2,8 @@ package telegram import ( "log" + "net/http" + "net/url" "os" "time" @@ -35,7 +37,15 @@ func BotStart() { } // 反向代理 if config.TelegramC.ApiProxy != "" { - setting.URL = config.TelegramC.ApiProxy + trans := &http.Transport{ + Proxy: func(_ *http.Request) (*url.URL, error) { + return url.Parse(config.TelegramC.ApiProxy) + }, + } + setting.Client = &http.Client{ + Timeout: time.Minute, + Transport: trans, + } } var err error Bot, err = tb.NewBot(setting) From cfa2befc1c6ed96e072d4bd8a41741458a72455d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E8=B6=85=E8=B6=8A?= <993921@qq.com> Date: Sun, 17 Mar 2024 14:42:50 +0800 Subject: [PATCH 09/11] chore: prevent to sleep --- main.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main.go b/main.go index 8a5b9e8..3659361 100644 --- a/main.go +++ b/main.go @@ -17,7 +17,8 @@ func main() { http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { counter++ w.Header().Set("Access-Control-Allow-Origin", "*") - _, _ = fmt.Fprintf(w, "OK, checker: "+strconv.Itoa(counter)) + w.Header().Set("counter", strconv.Itoa(counter)) + fmt.Fprintf(w, "OK") }) _ = http.ListenAndServe(":80", nil) }() From c6fcc4229c4d73dde217f32e77b55ac216e1f2cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E8=B6=85=E8=B6=8A?= <993921@qq.com> Date: Sun, 17 Mar 2024 17:02:35 +0800 Subject: [PATCH 10/11] config from env --- .gitignore | 1 - telegram/root.go | 2 +- util/config/config.go | 17 +++++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index e538900..625331e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ runtime/ .env dist/ config.*.toml -config.toml db/geecaptcha.db captcha-bot dict/dec_* diff --git a/telegram/root.go b/telegram/root.go index a4264e6..86f4570 100644 --- a/telegram/root.go +++ b/telegram/root.go @@ -35,7 +35,7 @@ func BotStart() { ulog.Sugar.Error(err) }, } - // 反向代理 + // 代理 if config.TelegramC.ApiProxy != "" { trans := &http.Transport{ Proxy: func(_ *http.Request) (*url.URL, error) { diff --git a/util/config/config.go b/util/config/config.go index 002d7af..367e549 100644 --- a/util/config/config.go +++ b/util/config/config.go @@ -59,6 +59,21 @@ type Message struct { var MessageC Message +func (msg *Message) FromEnv() { + if joinHint := os.Getenv("msg__join_hint"); len(joinHint) > 0 { + msg.JoinHint = joinHint + } + if captchaImage := os.Getenv("msg__captcha_image"); len(captchaImage) > 0 { + msg.CaptchaImage = captchaImage + } + if verificationComplete := os.Getenv("msg__verification_complete"); len(verificationComplete) > 0 { + msg.VerificationComplete = verificationComplete + } + if blockHint := os.Getenv("msg__block_hint"); len(blockHint) > 0 { + msg.BlockHint = blockHint + } +} + type AdBlock struct { NumberOfForbiddenWords int `mapstructure:"number_of_forbidden_words"` BlockTime int64 `mapstructure:"block_time"` @@ -97,6 +112,8 @@ func InitConfig() { err = viper.UnmarshalKey("message", &MessageC) if err != nil { log.Fatal("load config message err:", err) + } else { + MessageC.FromEnv() } err = viper.UnmarshalKey("adblock", &AdBlockC) if err != nil { From ec94732984cde284bdefba24dc9b8ba6d1e7aebf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E8=B6=85=E8=B6=8A?= <993921@qq.com> Date: Sun, 17 Mar 2024 22:18:43 +0800 Subject: [PATCH 11/11] translation --- config/config.toml | 6 +++--- telegram/handle.go | 22 ++++++++++++---------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/config/config.toml b/config/config.toml index 57af796..b6831f4 100644 --- a/config/config.toml +++ b/config/config.toml @@ -19,9 +19,9 @@ max_backups=3 #消息模板 [message] -join_hint="欢迎 [%s](%s) 加入 %s\n ⚠️本群已开启新成员验证功能,未通过验证的用户无法发言 \n超时未完成验证会被移除本群! \n⏱本条消息 %d 秒后自动删除\n👇点击下方按钮自助解除禁言" -captcha_image="欢迎您加入[%s]!\n⚠本群已开启新成员验证功能。\n👆为了证明您不是机器人,请发送以上图片验证码内容\n🤖机器人将自动验证您发送的验证码内容是否正确\n⏱本条验证消息有效期[%d]秒" -verification_complete="恭喜您成功通过[🤖人机验证],系统已为您解除禁言限制。\n如若还是无法发言,请重启telegram客户端\n请同时注意群内发言规范,以防永久禁止" +join_hint="Welcom [%s](%s) to join %s\\!\n ⚠️ This group has enabled new member verification\\.\n User who failed to complete verification in time will be removed from this group\\!\n ⏱ This message will be deleted after %d seconds automatically\\.\n 👇 Click the button below to self\\-unmute\\." +captcha_image="Welcome to join[%s]!\n⚠This group has enabled new member verification.\n👆Please send the captcha above\n🤖I'll check if it is correct\n⏱This message is vaild in [%d]seconds" +verification_complete="Welcome to join us!\nYou can restart telegram if you still can't speak.\nPlease also pay attention to the norms of communication to avoid permanent bans." block_hint="\\#封禁预警\n[%s](%s) 请注意,您的消息中含有部分违禁词 \n⚠️您已被系统判断为高风险用户,已被封禁\n系统已向超管发送预警信息,若由超管判定为误杀,会及时将您解除封禁。\n您的违禁词包含:%s" #广告阻止 diff --git a/telegram/handle.go b/telegram/handle.go index 6523f95..bdeb119 100644 --- a/telegram/handle.go +++ b/telegram/handle.go @@ -64,7 +64,7 @@ func StartCaptcha(c tb.Context) error { File: tb.FromDisk(imgUrl), Caption: captchaMessage, } - refreshCaptchaImageBtn := captchaMessageMenu.Data("🔁刷新验证码", "refreshCaptchaImageBtn", captchaId) + refreshCaptchaImageBtn := captchaMessageMenu.Data("🔁Refresh", "refreshCaptchaImageBtn", captchaId) Bot.Handle(&refreshCaptchaImageBtn, refreshCaptcha()) captchaMessageMenu.Inline( captchaMessageMenu.Row(refreshCaptchaImageBtn), @@ -72,7 +72,7 @@ func StartCaptcha(c tb.Context) error { botMsg, err := Bot.Send(c.Chat(), sendMessage, captchaMessageMenu) if err != nil { log.Sugar.Error("[StartCaptcha] send image captcha err:", err) - return c.Send("服务器异常~,请稍后再试") + return c.Send("Service is busy,please try later") } err = service.SetCaptchaCodeMessageIdByCaptchaId(captchaId, botMsg.ID) if err != nil { @@ -165,12 +165,12 @@ func VerificationProcess(c tb.Context) error { captchaId, ok := captchaIdObj.(string) if !ok { log.Sugar.Error("Value is not a string") - return c.Send("服务器异常~,请稍后再试") + return c.Send("Service is busy,please try later") } captchaRecord, err := service.GetRecordByCaptchaId(captchaId) if err != nil { log.Sugar.Error("[VerificationProcess] GetRecordByCaptchaId err:", err) - return c.Send("服务器异常~,请稍后再试") + return c.Send("Service is busy,please try later") } if captchaRecord.ID <= 0 || captchaRecord.TelegramUserId != c.Sender().ID || captchaRecord.CaptchaStatus != model.CaptchaStatusPending { return c.Send("您在该群没有待验证记录,或已超时,请重新加入后验证") @@ -178,7 +178,7 @@ func VerificationProcess(c tb.Context) error { // 验证 replyCode := c.Message().Text if !captcha.VerifyCaptcha(captchaRecord.CaptchaCode, replyCode) { - return c.Send("验证码错误,请重新输入!") + return c.Send("Incorrect captcha") } // 解禁用户 err = Bot.Restrict(&tb.Chat{ID: captchaRecord.TelegramChatId}, &tb.ChatMember{ @@ -187,7 +187,7 @@ func VerificationProcess(c tb.Context) error { }) if err != nil { log.Sugar.Error("[OnTextMessage] unban err:", err) - return c.Send("服务器异常~,请稍后重试~") + return c.Send("Service is busy,please try later") } err = service.SuccessRecordByCaptchaId(captchaId) if err != nil { @@ -205,6 +205,8 @@ func VerificationProcess(c tb.Context) error { func UserJoinGroup(c tb.Context) error { var err error + m := c.ChatMember().NewChatMember.Role + _ = m if c.ChatMember().NewChatMember.Role != tb.Member { return nil } @@ -232,10 +234,10 @@ func UserJoinGroup(c tb.Context) error { chat.Title, config.SystemC.JoinHintAfterDelTime) captchaId := uuid.NewV4().String() - doCaptchaBtn := joinMessageMenu.URL("👉🏻点我开始人机验证🤖", fmt.Sprintf("https://t.me/%s?start=%s", Bot.Me.Username, captchaId)) + doCaptchaBtn := joinMessageMenu.URL("👉🏻To Verify🤖", fmt.Sprintf("https://t.me/%s?start=%s", Bot.Me.Username, captchaId)) var ( - manageBanBtn = joinMessageMenu.Data("👮‍管理员禁止🈲", "manageBanBtn", captchaId) - managePassBtn = joinMessageMenu.Data("👮‍管理员通过✅", "managePassBtn", captchaId) + manageBanBtn = joinMessageMenu.Data("👮Ban🈲", "manageBanBtn", captchaId) + managePassBtn = joinMessageMenu.Data("👮Pass✅", "managePassBtn", captchaId) ) // 按钮点击事件 Bot.Handle(&manageBanBtn, ManageBan(), isManageMiddleware) @@ -366,7 +368,7 @@ func refreshCaptcha() func(c tb.Context) error { }) } return c.Respond(&tb.CallbackResponse{ - Text: "验证码已刷新~", + Text: "Refreshed", }) } }