robot.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. package telegram
  2. import (
  3. "context"
  4. "fmt"
  5. "time"
  6. "github.com/usememos/memos/common/log"
  7. "go.uber.org/zap"
  8. )
  9. type Handler interface {
  10. RobotToken(ctx context.Context) string
  11. MessageHandle(ctx context.Context, message Message, blobs map[string][]byte) error
  12. }
  13. type Robot struct {
  14. handler Handler
  15. }
  16. // NewRobotWithHandler create a telegram robot with specified handler.
  17. func NewRobotWithHandler(h Handler) *Robot {
  18. return &Robot{handler: h}
  19. }
  20. const noTokenWait = 30 * time.Second
  21. const errRetryWait = 10 * time.Second
  22. // Start start an infinity call of getUpdates from Telegram, call r.MessageHandle while get new message updates.
  23. func (r *Robot) Start(ctx context.Context) {
  24. var offset int
  25. for {
  26. updates, err := r.GetUpdates(ctx, offset)
  27. if err == ErrNoToken {
  28. time.Sleep(noTokenWait)
  29. continue
  30. }
  31. if err != nil {
  32. log.Warn("fail to telegram.GetUpdates", zap.Error(err))
  33. time.Sleep(errRetryWait)
  34. continue
  35. }
  36. groupMessages := make([]Message, 0, len(updates))
  37. for _, update := range updates {
  38. offset = update.UpdateID + 1
  39. if update.Message == nil {
  40. continue
  41. }
  42. message := *update.Message
  43. // skip message other than text or photo
  44. if message.Text == nil && message.Photo == nil {
  45. _, err := r.SendReplyMessage(ctx, message.Chat.ID, message.MessageID, "Only text or photo message be supported")
  46. if err != nil {
  47. log.Error(fmt.Sprintf("fail to telegram.SendReplyMessage for messageID=%d", message.MessageID), zap.Error(err))
  48. }
  49. continue
  50. }
  51. // Group message need do more
  52. if message.MediaGroupID != nil {
  53. groupMessages = append(groupMessages, message)
  54. continue
  55. }
  56. err = r.handleSingleMessage(ctx, message)
  57. if err != nil {
  58. log.Error(fmt.Sprintf("fail to handleSingleMessage for messageID=%d", message.MessageID), zap.Error(err))
  59. continue
  60. }
  61. }
  62. err = r.handleGroupMessages(ctx, groupMessages)
  63. if err != nil {
  64. log.Error("fail to handle plain text message", zap.Error(err))
  65. }
  66. }
  67. }