diff --git a/conf/config.go b/conf/config.go index 28a310a..cc2d9e8 100644 --- a/conf/config.go +++ b/conf/config.go @@ -28,11 +28,12 @@ type Config struct { } `json:"push_plus" yaml:"push_plus"` } `json:"push" yaml:"push"` TG struct { - Enable bool `json:"enable" yaml:"enable"` - Token string `json:"token" yaml:"token"` - ChatID int64 `json:"chat_id" yaml:"chat_id"` - Proxy string `json:"proxy" yaml:"proxy"` - CustomApi string `json:"custom_api" yaml:"custom_api"` + Enable bool `json:"enable" yaml:"enable"` + Token string `json:"token" yaml:"token"` + ChatID int64 `json:"chat_id" yaml:"chat_id"` + Proxy string `json:"proxy" yaml:"proxy"` + CustomApi string `json:"custom_api" yaml:"custom_api"` + WhiteList []int64 `json:"white_list" yaml:"white_list"` } `json:"tg" yaml:"tg"` QQ struct { } diff --git a/conf/config_default.yml b/conf/config_default.yml index 1679d5e..a3d2472 100644 --- a/conf/config_default.yml +++ b/conf/config_default.yml @@ -41,7 +41,9 @@ tg: proxy: "" # 自定义tg的api,可通过cloudflare搭建,需自备域名 custom_api: "https://api.telegram.org" - + # 白名单id,包括群id或者用户id,若为空,则允许所有群所有用户使用,若仅用于单人,直接配置上面的chat_id就可以 + white_list: + - 123 # 网页端配置 web: # 是否启用网页 diff --git a/docs/config.md b/docs/config.md index fccee28..c6ab70a 100644 --- a/docs/config.md +++ b/docs/config.md @@ -46,7 +46,9 @@ tg: proxy: "" # 自定义tg的api,可通过cloudflare搭建,需自备域名 custom_api: "https://api.telegram.org" - + # 白名单id,包括群id或者用户id,若为空,则允许所有群所有用户使用,若仅用于单人,直接配置上面的chat_id就可以 + white_list: + - 123 # 网页端配置 web: # 是否启用网页 diff --git a/lib/tg.go b/lib/tg.go index 0e5796e..ab9a4c9 100644 --- a/lib/tg.go +++ b/lib/tg.go @@ -2,6 +2,7 @@ package lib import ( "encoding/base64" + "encoding/json" "fmt" "net/http" "net/url" @@ -40,18 +41,18 @@ type Handle interface { type Mather struct { command string - handle func(bot *Telegram, args []string) + handle func(bot *Telegram, from int64, args []string) } func (m Mather) getCommand() string { return m.command } -func (m Mather) execute(bot *Telegram, args []string) { - m.handle(bot, args) +func (m Mather) execute(bot *Telegram, from int64, args []string) { + m.handle(bot, from, args) } -func newPlugin(command string, handle func(bot *Telegram, args []string)) { +func newPlugin(command string, handle func(bot *Telegram, from int64, args []string)) { handles.Store(command, handle) } @@ -95,17 +96,39 @@ func (t *Telegram) Init() { } channel := t.bot.GetUpdatesChan(tgbotapi.NewUpdate(1)) - t.SendMsg("你的学习强国小助手上线了!") + t.SendMsg(0, "你的学习强国小助手上线了!") go func() { for { update := <-channel if update.Message == nil { - update.Message = &tgbotapi.Message{Text: update.CallbackQuery.Data} - t.bot.Send(tgbotapi.NewDeleteMessage(conf.GetConfig().TG.ChatID, update.CallbackQuery.Message.MessageID)) - log.Infoln(update.CallbackQuery.Data) + if update.CallbackQuery != nil { + update.Message = &tgbotapi.Message{Text: update.CallbackQuery.Data} + t.bot.Send(tgbotapi.NewDeleteMessage(conf.GetConfig().TG.ChatID, update.CallbackQuery.Message.MessageID)) + log.Infoln(update.CallbackQuery.Data) + } else { + data, _ := json.Marshal(update) + log.Infoln(string(data)) + return + } } - log.Infoln("收到tg消息 ", update) + if update.Message.Chat.Type == "group" || update.Message.Chat.Type == "supergroup" { + update.Message.Text = strings.ReplaceAll(update.Message.Text, "@"+t.bot.Self.UserName, "") + } + log.Infoln(fmt.Sprintf("收到tg消息,来自%v,内容 ==》 %v", update.Message.Chat.ID, update.Message.Text)) + if len(conf.GetConfig().TG.WhiteList) > 0 { + inWhiteList := false + for _, id := range conf.GetConfig().TG.WhiteList { + if id == update.Message.Chat.ID { + inWhiteList = true + break + } + } + if !inWhiteList { + log.Infoln("已过滤非白名单的消息") + continue + } + } handles.Range(func(key, value interface{}) bool { if strings.Split(update.Message.Text, " ")[0] == key.(string) { go func() { @@ -116,7 +139,7 @@ func (t *Telegram) Init() { log.Errorln("handle执行出现了不可挽回的错误") } }() - (value.(func(bot *Telegram, args []string)))(t, strings.Split(update.Message.Text, " ")[1:]) + (value.(func(bot *Telegram, from int64, args []string)))(t, update.Message.Chat.ID, strings.Split(update.Message.Text, " ")[1:]) }() } return true @@ -137,8 +160,8 @@ func (t *Telegram) Init() { } } -func (t *Telegram) SendPhoto(image []byte) { - photo := tgbotapi.NewPhoto(t.ChatId, tgbotapi.FileBytes{ +func (t *Telegram) SendPhoto(id int64, image []byte) { + photo := tgbotapi.NewPhoto(id, tgbotapi.FileBytes{ Name: "login code", Bytes: image, }) @@ -150,8 +173,11 @@ func (t *Telegram) SendPhoto(image []byte) { } } -func (t *Telegram) SendMsg(message string) int { - msg := tgbotapi.NewMessage(t.ChatId, message) +func (t *Telegram) SendMsg(id int64, message string) int { + if id == 0 { + id = t.ChatId + } + msg := tgbotapi.NewMessage(id, message) messa, err := t.bot.Send(msg) if err != nil { return 0 @@ -159,7 +185,7 @@ func (t *Telegram) SendMsg(message string) int { return messa.MessageID } -func login(bot *Telegram, args []string) { +func login(bot *Telegram, from int64, args []string) { config := conf.GetConfig() go func() { defer func() { @@ -176,17 +202,17 @@ func login(bot *Telegram, args []string) { switch { case kind == "image": bytes, _ := base64.StdEncoding.DecodeString(message) - bot.SendPhoto(bytes) + bot.SendPhoto(from, bytes) case kind == "markdown": newMessage := tgbotapi.NewMessage(bot.ChatId, message) newMessage.ParseMode = tgbotapi.ModeMarkdownV2 bot.bot.Send(newMessage) case kind == "text": if log.GetLevel() == log.DebugLevel { - bot.SendMsg(message) + bot.SendMsg(from, message) } case kind == "flush": - bot.SendMsg(message) + bot.SendMsg(from, message) } }, } @@ -194,17 +220,17 @@ func login(bot *Telegram, args []string) { defer core.Quit() _, err := core.L(config.Retry.Times, "") if err != nil { - bot.SendMsg(err.Error()) + bot.SendMsg(from, err.Error()) return } - bot.SendMsg("登录成功") + bot.SendMsg(from, "登录成功") }() } -func getAllUser(bot *Telegram, args []string) { +func getAllUser(bot *Telegram, from int64, args []string) { users, err := model.Query() if err != nil { - bot.SendMsg("获取用户失败" + err.Error()) + bot.SendMsg(from, "获取用户失败"+err.Error()) return } message := fmt.Sprintf("共获取到%v个有效用户信息\n", len(users)) @@ -212,21 +238,21 @@ func getAllUser(bot *Telegram, args []string) { message += fmt.Sprintf("%v %v", i, user.Nick) message += "\n" } - bot.SendMsg(message) + bot.SendMsg(from, message) } -func studyAll(bot *Telegram, args []string) { +func studyAll(bot *Telegram, from int64, args []string) { config := conf.GetConfig() users, err := model.Query() if err != nil { - bot.SendMsg(err.Error()) + bot.SendMsg(from, err.Error()) return } if len(users) == 0 { - bot.SendMsg("未发现用户信息,请输入/login进行用户登录") + bot.SendMsg(from, "未发现用户信息,请输入/login进行用户登录") return } - getAllUser(bot, args) + getAllUser(bot, from, args) for _, user := range users { s := func() { core := Core{ @@ -237,7 +263,7 @@ func studyAll(bot *Telegram, args []string) { switch { case kind == "image": bytes, _ := base64.StdEncoding.DecodeString(message) - bot.SendPhoto(bytes) + bot.SendPhoto(from, bytes) case kind == "markdown": newMessage := tgbotapi.NewMessage(bot.ChatId, message) newMessage.ParseMode = tgbotapi.ModeMarkdownV2 @@ -245,10 +271,10 @@ func studyAll(bot *Telegram, args []string) { case kind == "text": if log.GetLevel() == log.DebugLevel { - bot.SendMsg(message) + bot.SendMsg(from, message) } case kind == "flush": - bot.SendMsg(message) + bot.SendMsg(from, message) } }, } @@ -257,7 +283,7 @@ func studyAll(bot *Telegram, args []string) { c := make(chan int, 1) go func() { u := uuid.New().String() - bot.SendMsg("已创建运行实例:" + u) + bot.SendMsg(from, "已创建运行实例:"+u) datas.Store(u, &core) defer datas.Delete(u) core.Init() @@ -273,7 +299,7 @@ func studyAll(bot *Telegram, args []string) { select { case <-timer: { - bot.SendMsg("学习超时,请重新学习或检查日志") + bot.SendMsg(from, "学习超时,请重新学习或检查日志") log.Errorln("学习超时,已自动退出") core.Quit() } @@ -282,37 +308,37 @@ func studyAll(bot *Telegram, args []string) { } } score, _ := GetUserScore(user.ToCookies()) - bot.SendMsg(fmt.Sprintf("%v已学习完成\n%v", user.Nick, PrintScore(score))) + bot.SendMsg(from, fmt.Sprintf("%v已学习完成\n%v", user.Nick, PrintScore(score))) } s() } } -func study(bot *Telegram, args []string) { +func study(bot *Telegram, from int64, args []string) { config := conf.GetConfig() users, err := model.Query() if err != nil { - bot.SendMsg(err.Error()) + bot.SendMsg(from, err.Error()) return } var user *model.User switch { case len(users) == 1: - bot.SendMsg("仅存在一名用户信息,自动进行学习") + bot.SendMsg(from, "仅存在一名用户信息,自动进行学习") user = users[0] case len(users) == 0: - bot.SendMsg("未发现用户信息,请输入/login进行用户登录") + bot.SendMsg(from, "未发现用户信息,请输入/login进行用户登录") return default: if 0 < len(args) { i, err := strconv.Atoi(args[0]) if err != nil { - bot.SendMsg(err.Error()) + bot.SendMsg(from, err.Error()) return } user = users[i] } else { - msgID := bot.SendMsg("存在多名用户,未输入用户序号") + msgID := bot.SendMsg(from, "存在多名用户,未输入用户序号") markup := tgbotapi.InlineKeyboardMarkup{} for i, user := range users { markup.InlineKeyboard = append(markup.InlineKeyboard, append([]tgbotapi.InlineKeyboardButton{}, tgbotapi.NewInlineKeyboardButtonData(user.Nick, "/study "+strconv.Itoa(i)))) @@ -334,7 +360,7 @@ func study(bot *Telegram, args []string) { switch { case kind == "image": bytes, _ := base64.StdEncoding.DecodeString(message) - bot.SendPhoto(bytes) + bot.SendPhoto(from, bytes) case kind == "markdown": newMessage := tgbotapi.NewMessage(bot.ChatId, message) newMessage.ParseMode = tgbotapi.ModeMarkdownV2 @@ -342,10 +368,10 @@ func study(bot *Telegram, args []string) { case kind == "text": if log.GetLevel() == log.DebugLevel { - bot.SendMsg(message) + bot.SendMsg(from, message) } case kind == "flush": - bot.SendMsg(message) + bot.SendMsg(from, message) } }, } @@ -353,7 +379,7 @@ func study(bot *Telegram, args []string) { c := make(chan int, 1) go func() { u := uuid.New().String() - bot.SendMsg("已创建运行实例:" + u) + bot.SendMsg(from, "已创建运行实例:"+u) datas.Store(u, &core) defer datas.Delete(u) core.Init() @@ -370,7 +396,7 @@ func study(bot *Telegram, args []string) { case <-timer: { log.Errorln("学习超时,已自动退出") - bot.SendMsg("学习超时,请重新登录或检查日志") + bot.SendMsg(from, "学习超时,请重新登录或检查日志") core.Quit() } case <-c: @@ -379,32 +405,34 @@ func study(bot *Telegram, args []string) { } } score, _ := GetUserScore(user.ToCookies()) - bot.SendMsg(fmt.Sprintf("%v已学习完成\n%v", user.Nick, PrintScore(score))) + bot.SendMsg(from, fmt.Sprintf("%v已学习完成\n%v", user.Nick, PrintScore(score))) } -func getScores(bot *Telegram, args []string) { +func getScores(bot *Telegram, from int64, args []string) { users, err := model.Query() if err != nil { log.Errorln(err.Error()) - bot.SendMsg("获取用户信息失败" + err.Error()) + bot.SendMsg(from, "获取用户信息失败"+err.Error()) return } - message := fmt.Sprintf("共获取到%v个有效用户信息\n", len(users)) + message := "" for _, user := range users { message += user.Nick + "\n" score, err := GetUserScore(user.ToCookies()) if err != nil { message += err.Error() + "\n" + continue } message += FormatScore(score) + "\n" + bot.SendMsg(from, message) + message = "" } - bot.SendMsg(message) } -func quit(bot *Telegram, args []string) { +func quit(bot *Telegram, from int64, args []string) { if len(args) < 1 { datas.Range(func(key, value interface{}) bool { - bot.SendMsg("已退出运行实例" + key.(string)) + bot.SendMsg(from, "已退出运行实例"+key.(string)) core := value.(*Core) core.Quit() return true