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"
2023-06-26 23:06:53 +08:00
"github.com/pkg/errors"
apiv1 "github.com/usememos/memos/api/v1"
2023-05-26 09:43:51 +08:00
"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 {
2023-07-02 18:56:25 +08:00
return t . store . GetSystemSettingValueWithDefault ( & ctx , apiv1 . SystemSettingTelegramBotTokenName . String ( ) , "" )
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
2023-06-29 22:55:03 +08:00
userSettingList , err := t . store . ListUserSettings ( ctx , & store . FindUserSetting {
2023-06-26 23:06:53 +08:00
Key : apiv1 . UserSettingTelegramUserIDKey . String ( ) ,
2023-05-26 09:43:51 +08:00
} )
if err != nil {
2023-06-26 23:06:53 +08:00
return errors . Wrap ( err , "Failed to find userSettingList" )
2023-05-26 09:43:51 +08:00
}
2023-06-29 22:55:03 +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
}
2023-07-06 21:56:42 +08:00
create := & store . Memo {
2023-05-26 09:43:51 +08:00
CreatorID : creatorID ,
2023-07-06 21:56:42 +08:00
Visibility : store . Private ,
2023-05-26 09:43:51 +08:00
}
if message . Text != nil {
2023-07-06 21:56:42 +08:00
create . Content = * message . Text
2023-05-26 09:43:51 +08:00
}
if blobs != nil && message . Caption != nil {
2023-07-06 21:56:42 +08:00
create . Content = * message . Caption
2023-05-26 09:43:51 +08:00
}
2023-07-06 21:56:42 +08:00
memoMessage , err := t . store . CreateMemo ( ctx , create )
2023-05-26 09:43:51 +08:00
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
}
// 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"
}
2023-07-06 21:56:42 +08:00
resource , err := t . store . CreateResource ( ctx , & store . Resource {
2023-05-26 09:43:51 +08:00
CreatorID : creatorID ,
Filename : filename ,
Type : mime ,
Size : int64 ( len ( blob ) ) ,
Blob : blob ,
2023-07-06 00:01:40 +08:00
} )
2023-05-26 09:43:51 +08:00
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
}
2023-07-06 21:56:42 +08:00
_ , err = t . store . UpsertMemoResource ( ctx , & store . UpsertMemoResource {
2023-05-26 09:43:51 +08:00
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 ) )
}
2023-07-06 21:56:42 +08:00
update := store . UpdateMemo {
2023-06-14 22:10:01 +08:00
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
}