package telegram import ( "errors" "strings" "sync" "github.com/forestgiant/sliceutil" "github.com/micro/go-micro/v2/agent/input" log "github.com/micro/go-micro/v2/logger" tgbotapi "gopkg.in/telegram-bot-api.v4" ) type telegramConn struct { input *telegramInput recv <-chan tgbotapi.Update exit chan bool syncCond *sync.Cond mutex sync.Mutex } func newConn(input *telegramInput) (*telegramConn, error) { conn := &telegramConn{ input: input, } conn.syncCond = sync.NewCond(&conn.mutex) go conn.run() return conn, nil } func (tc *telegramConn) run() { u := tgbotapi.NewUpdate(0) u.Timeout = 60 updates, err := tc.input.api.GetUpdatesChan(u) if err != nil { return } tc.recv = updates tc.syncCond.Signal() select { case <-tc.exit: return } } func (tc *telegramConn) Close() error { return nil } func (tc *telegramConn) Recv(event *input.Event) error { if event == nil { return errors.New("event cannot be nil") } for { if tc.recv == nil { tc.mutex.Lock() tc.syncCond.Wait() } update := <-tc.recv if update.Message == nil || (len(tc.input.whitelist) > 0 && !sliceutil.Contains(tc.input.whitelist, update.Message.From.UserName)) { continue } if event.Meta == nil { event.Meta = make(map[string]interface{}) } event.Type = input.TextEvent event.From = update.Message.From.UserName event.To = tc.input.api.Self.UserName event.Data = []byte(update.Message.Text) event.Meta["chatId"] = update.Message.Chat.ID event.Meta["chatType"] = update.Message.Chat.Type event.Meta["messageId"] = update.Message.MessageID return nil } } func (tc *telegramConn) Send(event *input.Event) error { messageText := strings.TrimSpace(string(event.Data)) chatId := event.Meta["chatId"].(int64) chatType := ChatType(event.Meta["chatType"].(string)) msgConfig := tgbotapi.NewMessage(chatId, messageText) msgConfig.ParseMode = tgbotapi.ModeHTML if sliceutil.Contains([]ChatType{Group, Supergroup}, chatType) { msgConfig.ReplyToMessageID = event.Meta["messageId"].(int) } _, err := tc.input.api.Send(msgConfig) if err != nil { // probably it could be because of nested HTML tags -- telegram doesn't allow nested tags log.Error("[telegram][Send] error:", err) msgConfig.Text = "This bot couldn't send the response (Internal error)" tc.input.api.Send(msgConfig) } return nil }