From 626ff5e3a75b8b02e417582e561e8ae0e0480ba6 Mon Sep 17 00:00:00 2001 From: Athurg Gooth Date: Wed, 13 Sep 2023 21:36:43 +0800 Subject: [PATCH] feat: notify by telegram while new memo create by HTTP (#2215) * Inject telegram bot into API service * Add support for send telegram message * Send notification by telegram while new memo post --- api/v1/memo.go | 34 +++++++++++++++++++++++++++++ api/v1/v1.go | 17 +++++++++------ plugin/telegram/api_send_message.go | 14 +++++++++--- server/server.go | 5 +++-- 4 files changed, 58 insertions(+), 12 deletions(-) diff --git a/api/v1/memo.go b/api/v1/memo.go index da7b7236..95aeb899 100644 --- a/api/v1/memo.go +++ b/api/v1/memo.go @@ -11,8 +11,10 @@ import ( "github.com/labstack/echo/v4" "github.com/pkg/errors" "github.com/usememos/memos/api/auth" + "github.com/usememos/memos/common/log" "github.com/usememos/memos/common/util" "github.com/usememos/memos/store" + "go.uber.org/zap" ) // Visibility is the type of a visibility. @@ -351,6 +353,38 @@ func (s *APIV1Service) CreateMemo(c echo.Context) error { if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to compose memo response").SetInternal(err) } + + // send notification by telegram bot if memo is not Private + if memoResponse.Visibility != Private { + // fetch all telegram UserID + userSettings, err := s.Store.ListUserSettings(ctx, &store.FindUserSetting{Key: UserSettingTelegramUserIDKey.String()}) + if err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, "Failed to ListUserSettings").SetInternal(err) + } + for _, userSetting := range userSettings { + // parse telegram UserID setting value into a int64 + var tgUserIDStr string + err := json.Unmarshal([]byte(userSetting.Value), &tgUserIDStr) + if err != nil { + log.Error("failed to parse Telegram UserID", zap.Error(err)) + continue + } + + tgUserID, err := strconv.ParseInt(tgUserIDStr, 10, 64) + if err != nil { + log.Error("failed to parse Telegram UserID", zap.Error(err)) + continue + } + + // send notification to telegram + content := memoResponse.CreatorName + " Says:\n\n" + memoResponse.Content + _, err = s.telegramBot.SendMessage(ctx, tgUserID, content) + if err != nil { + log.Error("Failed to send Telegram notification", zap.Error(err)) + continue + } + } + } return c.JSON(http.StatusOK, memoResponse) } diff --git a/api/v1/v1.go b/api/v1/v1.go index 328cfddc..1051ade8 100644 --- a/api/v1/v1.go +++ b/api/v1/v1.go @@ -2,14 +2,16 @@ package v1 import ( "github.com/labstack/echo/v4" + "github.com/usememos/memos/plugin/telegram" "github.com/usememos/memos/server/profile" "github.com/usememos/memos/store" ) type APIV1Service struct { - Secret string - Profile *profile.Profile - Store *store.Store + Secret string + Profile *profile.Profile + Store *store.Store + telegramBot *telegram.Bot } // @title memos API @@ -31,11 +33,12 @@ type APIV1Service struct { // @in query // @name openId // @description Insert your Open ID API Key here. -func NewAPIV1Service(secret string, profile *profile.Profile, store *store.Store) *APIV1Service { +func NewAPIV1Service(secret string, profile *profile.Profile, store *store.Store, telegramBot *telegram.Bot) *APIV1Service { return &APIV1Service{ - Secret: secret, - Profile: profile, - Store: store, + Secret: secret, + Profile: profile, + Store: store, + telegramBot: telegramBot, } } diff --git a/plugin/telegram/api_send_message.go b/plugin/telegram/api_send_message.go index b53f9115..f4bce9a8 100644 --- a/plugin/telegram/api_send_message.go +++ b/plugin/telegram/api_send_message.go @@ -9,9 +9,12 @@ import ( // SendReplyMessage make a sendMessage api request. func (b *Bot) SendReplyMessage(ctx context.Context, chatID, replyID int64, text string) (*Message, error) { formData := url.Values{ - "reply_to_message_id": {strconv.FormatInt(replyID, 10)}, - "chat_id": {strconv.FormatInt(chatID, 10)}, - "text": {text}, + "chat_id": {strconv.FormatInt(chatID, 10)}, + "text": {text}, + } + + if replyID > 0 { + formData.Set("reply_to_message_id", strconv.FormatInt(replyID, 10)) } var result Message @@ -22,3 +25,8 @@ func (b *Bot) SendReplyMessage(ctx context.Context, chatID, replyID int64, text return &result, nil } + +// SendMessage make a sendMessage api request. +func (b *Bot) SendMessage(ctx context.Context, chatID int64, text string) (*Message, error) { + return b.SendReplyMessage(ctx, chatID, 0, text) +} diff --git a/server/server.go b/server/server.go index 3edd4c85..c879ea3d 100644 --- a/server/server.go +++ b/server/server.go @@ -46,6 +46,7 @@ func NewServer(ctx context.Context, profile *profile.Profile, store *store.Store e.HideBanner = true e.HidePort = true + telegramBot := telegram.NewBotWithHandler(newTelegramHandler(store)) s := &Server{ e: e, Store: store, @@ -53,7 +54,7 @@ func NewServer(ctx context.Context, profile *profile.Profile, store *store.Store // Asynchronous runners. backupRunner: service.NewBackupRunner(store), - telegramBot: telegram.NewBotWithHandler(newTelegramHandler(store)), + telegramBot: telegramBot, } e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{ @@ -103,7 +104,7 @@ func NewServer(ctx context.Context, profile *profile.Profile, store *store.Store s.Secret = secret rootGroup := e.Group("") - apiV1Service := apiv1.NewAPIV1Service(s.Secret, profile, store) + apiV1Service := apiv1.NewAPIV1Service(s.Secret, profile, store, telegramBot) apiV1Service.Register(rootGroup) s.apiV2Service = apiv2.NewAPIV2Service(s.Secret, profile, store, s.Profile.Port+1)