2023-05-26 09:43:51 +08:00
package server
import (
"context"
2023-05-26 19:16:51 +08:00
"encoding/json"
2023-05-26 09:43:51 +08:00
"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 }
}
2023-05-29 19:49:05 +08:00
func ( t * telegramHandler ) BotToken ( ctx context . Context ) string {
return t . store . GetSystemSettingValueOrDefault ( & ctx , api . SystemSettingTelegramBotTokenName , "" )
2023-05-26 09:43:51 +08:00
}
2023-06-14 22:10:01 +08:00
const (
workingMessage = "Working on send your memo..."
successMessage = "Success"
)
func ( t * telegramHandler ) MessageHandle ( ctx context . Context , bot * telegram . Bot , message telegram . Message , blobs map [ string ] [ ] byte ) error {
reply , err := bot . SendReplyMessage ( ctx , message . Chat . ID , message . MessageID , workingMessage )
if err != nil {
return fmt . Errorf ( "fail to SendReplyMessage: %s" , err )
}
2023-05-26 09:43:51 +08:00
var creatorID int
userSettingList , err := t . store . FindUserSettingList ( ctx , & api . UserSettingFind {
Key : api . UserSettingTelegramUserIDKey ,
} )
if err != nil {
2023-06-14 22:10:01 +08:00
_ , err := bot . EditMessage ( ctx , message . Chat . ID , reply . MessageID , fmt . Sprintf ( "Fail to find memo user: %s" , err ) , nil )
return err
2023-05-26 09:43:51 +08:00
}
for _ , userSetting := range userSettingList {
2023-05-26 19:16:51 +08:00
var value string
if err := json . Unmarshal ( [ ] byte ( userSetting . Value ) , & value ) ; err != nil {
continue
}
if value == strconv . Itoa ( message . From . ID ) {
2023-05-26 09:43:51 +08:00
creatorID = userSetting . UserID
}
}
if creatorID == 0 {
2023-06-14 22:10:01 +08:00
_ , err := bot . EditMessage ( ctx , message . Chat . ID , reply . MessageID , fmt . Sprintf ( "Please set your telegram userid %d in UserSetting of Memos" , message . From . ID ) , nil )
return err
2023-05-26 09:43:51 +08:00
}
// 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 {
2023-06-14 22:10:01 +08:00
_ , err := bot . EditMessage ( ctx , message . Chat . ID , reply . MessageID , fmt . Sprintf ( "failed to CreateMemo: %s" , err ) , nil )
return err
2023-05-26 09:43:51 +08:00
}
if err := createMemoCreateActivity ( ctx , t . store , memoMessage ) ; err != nil {
2023-06-14 22:10:01 +08:00
_ , err := bot . EditMessage ( ctx , message . Chat . ID , reply . MessageID , fmt . Sprintf ( "failed to createMemoCreateActivity: %s" , err ) , nil )
return err
2023-05-26 09:43:51 +08:00
}
// 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 {
2023-06-14 22:10:01 +08:00
_ , err := bot . EditMessage ( ctx , message . Chat . ID , reply . MessageID , fmt . Sprintf ( "failed to CreateResource: %s" , err ) , nil )
return err
2023-05-26 09:43:51 +08:00
}
if err := createResourceCreateActivity ( ctx , t . store , resource ) ; err != nil {
2023-06-14 22:10:01 +08:00
_ , err := bot . EditMessage ( ctx , message . Chat . ID , reply . MessageID , fmt . Sprintf ( "failed to createResourceCreateActivity: %s" , err ) , nil )
return err
2023-05-26 09:43:51 +08:00
}
_ , err = t . store . UpsertMemoResource ( ctx , & api . MemoResourceUpsert {
MemoID : memoMessage . ID ,
ResourceID : resource . ID ,
} )
if err != nil {
2023-06-14 22:10:01 +08:00
_ , err := bot . EditMessage ( ctx , message . Chat . ID , reply . MessageID , fmt . Sprintf ( "failed to UpsertMemoResource: %s" , err ) , nil )
return err
}
}
keyboard := generateKeyboardForMemoID ( memoMessage . ID )
_ , err = bot . EditMessage ( ctx , message . Chat . ID , reply . MessageID , fmt . Sprintf ( "Saved as %s Memo %d" , memoMessage . Visibility , memoMessage . ID ) , keyboard )
return err
}
func ( t * telegramHandler ) CallbackQueryHandle ( ctx context . Context , bot * telegram . Bot , callbackQuery telegram . CallbackQuery ) error {
var memoID int
var visibility store . Visibility
n , err := fmt . Sscanf ( callbackQuery . Data , "%s %d" , & visibility , & memoID )
if err != nil || n != 2 {
return bot . AnswerCallbackQuery ( ctx , callbackQuery . ID , fmt . Sprintf ( "fail to parse callbackQuery.Data %s" , callbackQuery . Data ) )
}
update := store . UpdateMemoMessage {
ID : memoID ,
Visibility : & visibility ,
}
err = t . store . UpdateMemo ( ctx , & update )
if err != nil {
return bot . AnswerCallbackQuery ( ctx , callbackQuery . ID , fmt . Sprintf ( "fail to call UpdateMemo %s" , err ) )
}
keyboard := generateKeyboardForMemoID ( memoID )
_ , err = bot . EditMessage ( ctx , callbackQuery . Message . Chat . ID , callbackQuery . Message . MessageID , fmt . Sprintf ( "Saved as %s Memo %d" , visibility , memoID ) , keyboard )
if err != nil {
return bot . AnswerCallbackQuery ( ctx , callbackQuery . ID , fmt . Sprintf ( "fail to EditMessage %s" , err ) )
}
return bot . AnswerCallbackQuery ( ctx , callbackQuery . ID , fmt . Sprintf ( "Success change Memo %d to %s" , memoID , visibility ) )
}
func generateKeyboardForMemoID ( id int ) [ ] [ ] telegram . InlineKeyboardButton {
allVisibility := [ ] store . Visibility {
store . Public ,
store . Protected ,
store . Private ,
}
buttons := make ( [ ] telegram . InlineKeyboardButton , 0 , len ( allVisibility ) )
for _ , v := range allVisibility {
button := telegram . InlineKeyboardButton {
Text : v . String ( ) ,
CallbackData : fmt . Sprintf ( "%s %d" , v , id ) ,
2023-05-26 09:43:51 +08:00
}
2023-06-14 22:10:01 +08:00
buttons = append ( buttons , button )
2023-05-26 09:43:51 +08:00
}
2023-06-14 22:10:01 +08:00
return [ ] [ ] telegram . InlineKeyboardButton { buttons }
2023-05-26 09:43:51 +08:00
}