feat: implement telegram bot plugin (#1740)

This commit is contained in:
Athurg Gooth
2023-05-26 09:43:51 +08:00
committed by GitHub
parent a07d11e820
commit 1282fe732e
23 changed files with 577 additions and 15 deletions

View File

@@ -38,7 +38,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
if createMemoRequest.Visibility == "" {
userMemoVisibilitySetting, err := s.Store.FindUserSetting(ctx, &api.UserSettingFind{
UserID: userID,
UserID: &userID,
Key: api.UserSettingMemoVisibilityKey,
})
if err != nil {
@@ -90,7 +90,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create memo").SetInternal(err)
}
if err := s.createMemoCreateActivity(c, memoMessage); err != nil {
if err := createMemoCreateActivity(c.Request().Context(), s.Store, memoMessage); err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create activity").SetInternal(err)
}
@@ -503,8 +503,7 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
})
}
func (s *Server) createMemoCreateActivity(c echo.Context, memo *store.MemoMessage) error {
ctx := c.Request().Context()
func createMemoCreateActivity(ctx context.Context, store *store.Store, memo *store.MemoMessage) error {
payload := api.ActivityMemoCreatePayload{
Content: memo.Content,
Visibility: memo.Visibility.String(),
@@ -513,7 +512,7 @@ func (s *Server) createMemoCreateActivity(c echo.Context, memo *store.MemoMessag
if err != nil {
return errors.Wrap(err, "failed to marshal activity payload")
}
activity, err := s.Store.CreateActivity(ctx, &api.ActivityCreate{
activity, err := store.CreateActivity(ctx, &api.ActivityCreate{
CreatorID: memo.CreatorID,
Type: api.ActivityMemoCreate,
Level: api.ActivityInfo,

View File

@@ -2,6 +2,7 @@ package server
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
@@ -23,6 +24,7 @@ import (
"github.com/usememos/memos/common"
"github.com/usememos/memos/common/log"
"github.com/usememos/memos/plugin/storage/s3"
"github.com/usememos/memos/store"
"go.uber.org/zap"
)
@@ -62,7 +64,7 @@ func (s *Server) registerResourceRoutes(g *echo.Group) {
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create resource").SetInternal(err)
}
if err := s.createResourceCreateActivity(c, resource); err != nil {
if err := createResourceCreateActivity(c.Request().Context(), s.Store, resource); err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create activity").SetInternal(err)
}
return c.JSON(http.StatusOK, composeResponse(resource))
@@ -224,7 +226,7 @@ func (s *Server) registerResourceRoutes(g *echo.Group) {
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create resource").SetInternal(err)
}
if err := s.createResourceCreateActivity(c, resource); err != nil {
if err := createResourceCreateActivity(c.Request().Context(), s.Store, resource); err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create activity").SetInternal(err)
}
return c.JSON(http.StatusOK, composeResponse(resource))
@@ -454,8 +456,7 @@ func (s *Server) registerResourcePublicRoutes(g *echo.Group) {
})
}
func (s *Server) createResourceCreateActivity(c echo.Context, resource *api.Resource) error {
ctx := c.Request().Context()
func createResourceCreateActivity(ctx context.Context, store *store.Store, resource *api.Resource) error {
payload := api.ActivityResourceCreatePayload{
Filename: resource.Filename,
Type: resource.Type,
@@ -465,7 +466,7 @@ func (s *Server) createResourceCreateActivity(c echo.Context, resource *api.Reso
if err != nil {
return errors.Wrap(err, "failed to marshal activity payload")
}
activity, err := s.Store.CreateActivity(ctx, &api.ActivityCreate{
activity, err := store.CreateActivity(ctx, &api.ActivityCreate{
CreatorID: resource.CreatorID,
Type: api.ActivityResourceCreate,
Level: api.ActivityInfo,

View File

@@ -9,6 +9,7 @@ import (
"github.com/pkg/errors"
"github.com/usememos/memos/api"
"github.com/usememos/memos/plugin/telegram"
"github.com/usememos/memos/server/profile"
"github.com/usememos/memos/store"
"github.com/usememos/memos/store/db"
@@ -24,6 +25,8 @@ type Server struct {
ID string
Profile *profile.Profile
Store *store.Store
telegramRobot *telegram.Robot
}
func NewServer(ctx context.Context, profile *profile.Profile) (*Server, error) {
@@ -45,6 +48,9 @@ func NewServer(ctx context.Context, profile *profile.Profile) (*Server, error) {
storeInstance := store.New(db.DBInstance, profile)
s.Store = storeInstance
telegramRobotHandler := newTelegramHandler(storeInstance)
s.telegramRobot = telegram.NewRobotWithHandler(telegramRobotHandler)
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
Format: `{"time":"${time_rfc3339}",` +
`"method":"${method}","uri":"${uri}",` +
@@ -118,6 +124,9 @@ func (s *Server) Start(ctx context.Context) error {
if err := s.createServerStartActivity(ctx); err != nil {
return errors.Wrap(err, "failed to create activity")
}
go s.telegramRobot.Start(ctx)
return s.e.Start(fmt.Sprintf(":%d", s.Profile.Port))
}

View File

@@ -64,7 +64,7 @@ func (s *Server) registerSystemRoutes(g *echo.Group) {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find system setting list").SetInternal(err)
}
for _, systemSetting := range systemSettingList {
if systemSetting.Name == api.SystemSettingServerIDName || systemSetting.Name == api.SystemSettingSecretSessionName || systemSetting.Name == api.SystemSettingOpenAIConfigName {
if systemSetting.Name == api.SystemSettingServerIDName || systemSetting.Name == api.SystemSettingSecretSessionName || systemSetting.Name == api.SystemSettingOpenAIConfigName || systemSetting.Name == api.SystemSettingTelegramRobotTokenName {
continue
}

102
server/telegram.go Normal file
View File

@@ -0,0 +1,102 @@
package server
import (
"context"
"fmt"
"path"
"strconv"
"github.com/usememos/memos/api"
"github.com/usememos/memos/common"
"github.com/usememos/memos/plugin/telegram"
"github.com/usememos/memos/store"
)
type telegramHandler struct {
store *store.Store
}
func newTelegramHandler(store *store.Store) *telegramHandler {
return &telegramHandler{store: store}
}
func (t *telegramHandler) RobotToken(ctx context.Context) string {
return t.store.GetSystemSettingValueOrDefault(&ctx, api.SystemSettingTelegramRobotTokenName, "")
}
func (t *telegramHandler) MessageHandle(ctx context.Context, message telegram.Message, blobs map[string][]byte) error {
var creatorID int
userSettingList, err := t.store.FindUserSettingList(ctx, &api.UserSettingFind{
Key: api.UserSettingTelegramUserIDKey,
})
if err != nil {
return fmt.Errorf("Fail to find memo user: %s", err)
}
for _, userSetting := range userSettingList {
if userSetting.Value == strconv.Itoa(message.From.ID) {
creatorID = userSetting.UserID
}
}
if creatorID == 0 {
return fmt.Errorf("Please set your telegram userid %d in UserSetting of Memos", message.From.ID)
}
// create memo
memoCreate := api.CreateMemoRequest{
CreatorID: creatorID,
Visibility: api.Private,
}
if message.Text != nil {
memoCreate.Content = *message.Text
}
if blobs != nil && message.Caption != nil {
memoCreate.Content = *message.Caption
}
memoMessage, err := t.store.CreateMemo(ctx, convertCreateMemoRequestToMemoMessage(&memoCreate))
if err != nil {
return fmt.Errorf("failed to CreateMemo: %s", err)
}
if err := createMemoCreateActivity(ctx, t.store, memoMessage); err != nil {
return fmt.Errorf("failed to createMemoCreateActivity: %s", err)
}
// create resources
for filename, blob := range blobs {
// TODO support more
mime := "application/octet-stream"
switch path.Ext(filename) {
case ".jpg":
mime = "image/jpeg"
case ".png":
mime = "image/png"
}
resourceCreate := api.ResourceCreate{
CreatorID: creatorID,
Filename: filename,
Type: mime,
Size: int64(len(blob)),
Blob: blob,
PublicID: common.GenUUID(),
}
resource, err := t.store.CreateResource(ctx, &resourceCreate)
if err != nil {
return fmt.Errorf("failed to CreateResource: %s", err)
}
if err := createResourceCreateActivity(ctx, t.store, resource); err != nil {
return fmt.Errorf("failed to createResourceCreateActivity: %s", err)
}
_, err = t.store.UpsertMemoResource(ctx, &api.MemoResourceUpsert{
MemoID: memoMessage.ID,
ResourceID: resource.ID,
})
if err != nil {
return fmt.Errorf("failed to UpsertMemoResource: %s", err)
}
}
return nil
}

View File

@@ -116,7 +116,7 @@ func (s *Server) registerUserRoutes(g *echo.Group) {
}
userSettingList, err := s.Store.FindUserSettingList(ctx, &api.UserSettingFind{
UserID: userID,
UserID: &userID,
})
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find userSettingList").SetInternal(err)
@@ -203,7 +203,7 @@ func (s *Server) registerUserRoutes(g *echo.Group) {
}
userSettingList, err := s.Store.FindUserSettingList(ctx, &api.UserSettingFind{
UserID: userID,
UserID: &userID,
})
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find userSettingList").SetInternal(err)