1056 lines
41 KiB
Go
1056 lines
41 KiB
Go
package saved_message
|
||
|
||
import (
|
||
"context"
|
||
"errors"
|
||
"fmt"
|
||
"trbot/plugins/saved_message/message_meilisearch"
|
||
"trbot/utils"
|
||
"trbot/utils/configs"
|
||
"trbot/utils/flaterr"
|
||
"trbot/utils/handler_params"
|
||
"trbot/utils/inline_utils"
|
||
"trbot/utils/meilisearch_utils"
|
||
"trbot/utils/origin_info"
|
||
"trbot/utils/plugin_utils"
|
||
"trbot/utils/type/message_utils"
|
||
|
||
"github.com/go-telegram/bot"
|
||
"github.com/go-telegram/bot/models"
|
||
"github.com/meilisearch/meilisearch-go"
|
||
"github.com/rs/zerolog"
|
||
)
|
||
|
||
func saveMessageHandler(opts *handler_params.Message) error {
|
||
logger := zerolog.Ctx(opts.Ctx).
|
||
With().
|
||
Str("pluginName", "Saved Message").
|
||
Str(utils.GetCurrentFuncName()).
|
||
Dict(utils.GetUserDict(opts.Message.From)).
|
||
Dict(utils.GetChatDict(&opts.Message.Chat)).
|
||
Logger()
|
||
|
||
var handlerErr flaterr.MultErr
|
||
|
||
if meilisearchClient == nil {
|
||
_, err := opts.Thebot.SendMessage(opts.Ctx, &bot.SendMessageParams{
|
||
ChatID: opts.Message.Chat.ID,
|
||
Text: "此功能不可用,因为 Meilisearch 服务尚未初始化",
|
||
ReplyParameters: &models.ReplyParameters{ MessageID: opts.Message.ID },
|
||
})
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Str("content", "meilisearch client uninitialized").
|
||
Msg(flaterr.SendMessage.Str())
|
||
handlerErr.Addt(flaterr.SendMessage, "meilisearch client uninitialized", err)
|
||
}
|
||
} else {
|
||
user := SavedMessageList.GetUser(opts.Message.From.ID)
|
||
if user == nil {
|
||
_, err := opts.Thebot.SendMessage(opts.Ctx, &bot.SendMessageParams{
|
||
ChatID: opts.Message.Chat.ID,
|
||
Text: "此功能需要保存一些信息才能正常工作,在使用这个功能前,请先阅读一下我们会保存哪些信息",
|
||
ReplyParameters: &models.ReplyParameters{ MessageID: opts.Message.ID },
|
||
ReplyMarkup: &models.InlineKeyboardMarkup{ InlineKeyboard: [][]models.InlineKeyboardButton{{{
|
||
Text: "点击查看",
|
||
URL: fmt.Sprintf("https://t.me/%s?start=savedmessage_privacy_policy", configs.BotMe.Username),
|
||
}}}},
|
||
})
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Str("content", "need agree privacy policy").
|
||
Msg(flaterr.SendMessage.Str())
|
||
handlerErr.Addt(flaterr.SendMessage, "need agree privacy policy", err)
|
||
}
|
||
} else {
|
||
messageParams := &bot.SendMessageParams{
|
||
ChatID: opts.Message.Chat.ID,
|
||
ParseMode: models.ParseModeHTML,
|
||
ReplyParameters: &models.ReplyParameters{ MessageID: opts.Message.ID },
|
||
ReplyMarkup: &models.InlineKeyboardMarkup{ InlineKeyboard: [][]models.InlineKeyboardButton{{
|
||
{
|
||
Text: "点击浏览您的收藏",
|
||
SwitchInlineQueryCurrentChat: configs.BotConfig.InlineSubCommandSymbol + "saved ",
|
||
},
|
||
{
|
||
Text: "关闭",
|
||
CallbackData: "delete_this_message",
|
||
},
|
||
}}},
|
||
}
|
||
|
||
if opts.Message.ReplyToMessage == nil {
|
||
messageParams.Text = "在回复一条消息的同时发送 <code>/save</code> 来收藏消息"
|
||
if opts.Message.Chat.Type == models.ChatTypePrivate {
|
||
messageParams.ReplyMarkup = &models.InlineKeyboardMarkup{ InlineKeyboard: [][]models.InlineKeyboardButton{{{
|
||
Text: "修改此功能偏好",
|
||
CallbackData: "savedmsg_switch",
|
||
}}}}
|
||
}
|
||
} else {
|
||
if user.Limit == 0 && user.Count == 0 {
|
||
// 每个用户初次添加时,默认限制 100 条
|
||
user.Limit = 100
|
||
}
|
||
|
||
// 若不是初次添加,为 0 就是不限制
|
||
if user.Limit != 0 && user.Count >= user.Limit {
|
||
messageParams.Text = "已达到限制,无法保存更多内容"
|
||
} else {
|
||
msgData := meilisearch_utils.BuildMessageData(opts.Ctx, opts.Thebot, opts.Message.ReplyToMessage)
|
||
|
||
var messageLength int
|
||
|
||
if opts.Message.ReplyToMessage.Caption != "" {
|
||
messageLength = utf16Length(opts.Message.ReplyToMessage.Caption)
|
||
msgData.Entities = opts.Message.ReplyToMessage.CaptionEntities
|
||
} else if opts.Message.ReplyToMessage.Text != "" {
|
||
messageLength = utf16Length(opts.Message.ReplyToMessage.Text)
|
||
msgData.Entities = opts.Message.ReplyToMessage.Entities
|
||
}
|
||
|
||
// 若字符长度大于设定的阈值,添加折叠样式引用再保存,如果是全文引用但不折叠,改成折叠样式
|
||
if messageLength > textExpandableLength && (len(msgData.Entities) == 0 || msgData.Entities[0].Type == models.MessageEntityTypeBlockquote && msgData.Entities[0].Length == messageLength) {
|
||
msgData.Entities = []models.MessageEntity{{
|
||
Type: models.MessageEntityTypeExpandableBlockquote,
|
||
Offset: 0,
|
||
Length: messageLength,
|
||
}}
|
||
}
|
||
|
||
msgData.ID = user.SavedTimes
|
||
|
||
if !user.DropOriginInfo {
|
||
msgData.OriginInfo = origin_info.GetOriginInfo(opts.Message.ReplyToMessage)
|
||
}
|
||
|
||
// 获取使用命令保存时设定的描述
|
||
if len(opts.Message.Text) > len(opts.Fields[0])+1 {
|
||
msgData.Desc = opts.Message.Text[len(opts.Fields[0])+1:]
|
||
}
|
||
|
||
_, err := meilisearchClient.Index(user.IDStr()).AddDocuments(msgData)
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Msg("Failed to send add documents task to meilisearch")
|
||
handlerErr.Addf("failed to send add documents task to meilisearch: %w", err)
|
||
messageParams.Text = "保存失败,可能是因为 Meilisearch 服务不可用或网络问题,请稍后再试"
|
||
messageParams.ReplyMarkup = nil
|
||
} else {
|
||
user.Count++
|
||
user.SavedTimes++
|
||
err = SaveSavedMessageList(opts.Ctx)
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Msg("Failed to save savedmessage list after save a item")
|
||
handlerErr.Addf("failed to save savedmessage list after save a item: %w", err)
|
||
messageParams.Text = "消息已保存,但保存统计数据失败"
|
||
messageParams.ReplyMarkup = nil
|
||
} else {
|
||
messageParams.Text = "已保存内容"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
_, err := opts.Thebot.SendMessage(opts.Ctx, messageParams)
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Dict(utils.GetUserDict(opts.Message.From)).
|
||
Str("content", "saved message response").
|
||
Msg(flaterr.SendMessage.Str())
|
||
handlerErr.Addt(flaterr.SendMessage, "saved message response", err)
|
||
}
|
||
}
|
||
}
|
||
|
||
return handlerErr.Flat()
|
||
}
|
||
|
||
func saveMessageFromCallbackQueryHandler(opts *handler_params.Message) error {
|
||
if opts.Message == nil { return nil }
|
||
|
||
logger := zerolog.Ctx(opts.Ctx).
|
||
With().
|
||
Str("pluginName", "Saved Message").
|
||
Str(utils.GetCurrentFuncName()).
|
||
Dict(utils.GetUserDict(opts.Message.From)).
|
||
Logger()
|
||
|
||
var handlerErr flaterr.MultErr
|
||
|
||
if meilisearchClient == nil {
|
||
_, err := opts.Thebot.SendMessage(opts.Ctx, &bot.SendMessageParams{
|
||
ChatID: opts.Message.Chat.ID,
|
||
Text: "此功能不可用,因为 Meilisearch 服务尚未初始化",
|
||
ReplyParameters: &models.ReplyParameters{ MessageID: opts.Message.ID },
|
||
})
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Str("content", "meilisearch client uninitialized").
|
||
Msg(flaterr.SendMessage.Str())
|
||
handlerErr.Addt(flaterr.SendMessage, "meilisearch client uninitialized", err)
|
||
}
|
||
} else {
|
||
user := SavedMessageList.GetUser(opts.Message.From.ID)
|
||
if user == nil {
|
||
_, err := opts.Thebot.SendMessage(opts.Ctx, &bot.SendMessageParams{
|
||
ChatID: opts.Message.Chat.ID,
|
||
Text: "此功能需要保存一些信息才能正常工作,在使用这个功能前,请先阅读一下我们会保存哪些信息",
|
||
ReplyParameters: &models.ReplyParameters{ MessageID: opts.Message.ID },
|
||
ReplyMarkup: &models.InlineKeyboardMarkup{ InlineKeyboard: [][]models.InlineKeyboardButton{{{
|
||
Text: "点击查看",
|
||
URL: fmt.Sprintf("https://t.me/%s?start=savedmessage_privacy_policy", configs.BotMe.Username),
|
||
}}}},
|
||
})
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Str("content", "need agree privacy policy").
|
||
Msg(flaterr.SendMessage.Str())
|
||
handlerErr.Addt(flaterr.SendMessage, "need agree privacy policy", err)
|
||
}
|
||
} else {
|
||
messageParams := &bot.SendMessageParams{
|
||
ChatID: opts.ChatInfo.ID,
|
||
ParseMode: models.ParseModeHTML,
|
||
ReplyParameters: &models.ReplyParameters{ MessageID: opts.Message.ID },
|
||
ReplyMarkup: &models.InlineKeyboardMarkup{ InlineKeyboard: [][]models.InlineKeyboardButton{{{
|
||
Text: "关闭",
|
||
CallbackData: "delete_this_message",
|
||
}}}},
|
||
}
|
||
|
||
if user.Limit == 0 && user.Count == 0 {
|
||
// 每个用户初次添加时,默认限制 100 条
|
||
user.Limit = 100
|
||
}
|
||
|
||
// 若不是初次添加,为 0 就是不限制
|
||
if user.Limit != 0 && user.Count >= user.Limit {
|
||
messageParams.Text = "已达到限制,无法保存更多内容"
|
||
} else {
|
||
msgData := meilisearch_utils.BuildMessageData(opts.Ctx, opts.Thebot, opts.Message)
|
||
|
||
var messageLength int
|
||
|
||
if opts.Message.Caption != "" {
|
||
messageLength = utf16Length(opts.Message.Caption)
|
||
msgData.Entities = opts.Message.CaptionEntities
|
||
} else if opts.Message.Text != "" {
|
||
messageLength = utf16Length(opts.Message.Text)
|
||
msgData.Entities = opts.Message.Entities
|
||
}
|
||
|
||
// 若字符长度大于设定的阈值,添加折叠样式引用再保存,如果是全文引用但不折叠,改成折叠样式
|
||
if messageLength > textExpandableLength && (len(msgData.Entities) == 0 || msgData.Entities[0].Type == models.MessageEntityTypeBlockquote && msgData.Entities[0].Length == messageLength) {
|
||
msgData.Entities = []models.MessageEntity{{
|
||
Type: models.MessageEntityTypeExpandableBlockquote,
|
||
Offset: 0,
|
||
Length: messageLength,
|
||
}}
|
||
}
|
||
|
||
msgData.ID = user.SavedTimes
|
||
|
||
if !user.DropOriginInfo {
|
||
msgData.OriginInfo = origin_info.GetOriginInfo(opts.Message)
|
||
}
|
||
|
||
_, err := meilisearchClient.Index(user.IDStr()).AddDocuments(msgData)
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Msg("Failed to send add documents task to meilisearch")
|
||
handlerErr.Addf("failed to send add documents task to meilisearch: %w", err)
|
||
messageParams.Text = "保存失败,可能是因为 Meilisearch 服务不可用或网络问题,请稍后再试"
|
||
messageParams.ReplyMarkup = nil
|
||
} else {
|
||
user.Count++
|
||
user.SavedTimes++
|
||
err = SaveSavedMessageList(opts.Ctx)
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Msg("Failed to save savedmessage list after save a item")
|
||
handlerErr.Addf("failed to save savedmessage list after save a item: %w", err)
|
||
messageParams.Text = "消息已保存,但保存统计数据失败"
|
||
messageParams.ReplyMarkup = nil
|
||
} else {
|
||
messageParams.Text = "已保存内容"
|
||
}
|
||
}
|
||
}
|
||
|
||
_, err := opts.Thebot.SendMessage(opts.Ctx, messageParams)
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Dict(utils.GetUserDict(opts.Message.From)).
|
||
Str("content", "saved message response").
|
||
Msg(flaterr.SendMessage.Str())
|
||
handlerErr.Addt(flaterr.SendMessage, "saved message response", err)
|
||
}
|
||
}
|
||
}
|
||
|
||
return handlerErr.Flat()
|
||
}
|
||
|
||
func InlineSavedMessageHandler(opts *handler_params.InlineQuery) error {
|
||
logger := zerolog.Ctx(opts.Ctx).
|
||
With().
|
||
Str("pluginName", "Saved Message").
|
||
Str(utils.GetCurrentFuncName()).
|
||
Dict(utils.GetUserDict(opts.InlineQuery.From)).
|
||
Str("query", opts.InlineQuery.Query).
|
||
Logger()
|
||
var handlerErr flaterr.MultErr
|
||
|
||
if meilisearchClient == nil {
|
||
_, err := opts.Thebot.AnswerInlineQuery(opts.Ctx, &bot.AnswerInlineQueryParams{
|
||
InlineQueryID: opts.InlineQuery.ID,
|
||
Results: []models.InlineQueryResult{ &models.InlineQueryResultArticle{
|
||
ID: "error",
|
||
Title: "此功能不可用",
|
||
Description: "Meilisearch 服务尚未初始化",
|
||
InputMessageContent: &models.InputTextMessageContent{ MessageText: "Meilisearch 服务尚未初始化,无法使用收藏功能" },
|
||
}},
|
||
IsPersonal: true,
|
||
CacheTime: 0,
|
||
})
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Str("content", "meilisearch client uninitialized").
|
||
Msg(flaterr.AnswerInlineQuery.Str())
|
||
handlerErr.Addt(flaterr.AnswerInlineQuery, "meilisearch client uninitialized", err)
|
||
}
|
||
} else {
|
||
var button *models.InlineQueryResultsButton
|
||
var resultList []models.InlineQueryResult
|
||
var targetChatID string
|
||
var filter string
|
||
|
||
channelID := SavedMessageList.ChannelIDStr()
|
||
|
||
user := SavedMessageList.GetUser(opts.InlineQuery.From.ID)
|
||
if user == nil || user.Count == 0 {
|
||
targetChatID = channelID
|
||
button = &models.InlineQueryResultsButton{
|
||
Text: "当前为公共收藏内容",
|
||
StartParameter: "via-inline_savedmessage-help",
|
||
}
|
||
} else {
|
||
targetChatID = user.IDStr()
|
||
}
|
||
|
||
parsedQuery := inline_utils.ParseInlineFields(opts.Fields)
|
||
|
||
if parsedQuery.LastChar != "" {
|
||
switch parsedQuery.LastChar {
|
||
case configs.BotConfig.InlineCategorySymbol:
|
||
_, err := opts.Thebot.AnswerInlineQuery(opts.Ctx, &bot.AnswerInlineQueryParams{
|
||
InlineQueryID: opts.InlineQuery.ID,
|
||
Results: []models.InlineQueryResult{&models.InlineQueryResultArticle{
|
||
ID: "keepInputCategory",
|
||
Title: "请继续输入分类名称",
|
||
Description: fmt.Sprintf("当前列表有 %s 分类", resultCategorys.StrList()),
|
||
InputMessageContent: &models.InputTextMessageContent{ MessageText: "用户在尝试选择分类时点击了提示信息..." },
|
||
}},
|
||
IsPersonal: true,
|
||
CacheTime: 0,
|
||
})
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Str("content", "need a category name").
|
||
Msg(flaterr.AnswerInlineQuery.Str())
|
||
handlerErr.Addt(flaterr.AnswerInlineQuery, "need a category name", err)
|
||
}
|
||
return handlerErr.Flat()
|
||
case configs.BotConfig.InlinePaginationSymbol:
|
||
_, err := opts.Thebot.AnswerInlineQuery(opts.Ctx, &bot.AnswerInlineQueryParams{
|
||
InlineQueryID: opts.InlineQuery.ID,
|
||
Results: []models.InlineQueryResult{&models.InlineQueryResultArticle{
|
||
ID: "noPagination",
|
||
Title: "分页功能不可用",
|
||
Description: "由于更换了存储消息的数据库,现在仅可通过输入搜索关键词来查找内容,您可以点击此处来查看公开收藏内容",
|
||
InputMessageContent: &models.InputTextMessageContent{
|
||
MessageText: fmt.Sprintf("点击访问公共收藏频道:\nhttps://t.me/%s/\n<blockquote>链接为空?那可能是机器人管理员没有设定公开收藏频道,或未收藏频道设为公开频道</blockquote>", SavedMessageList.ChannelUsername),
|
||
ParseMode: models.ParseModeHTML,
|
||
},
|
||
}},
|
||
IsPersonal: true,
|
||
CacheTime: 0,
|
||
})
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Str("content", "need a category name").
|
||
Msg(flaterr.AnswerInlineQuery.Str())
|
||
handlerErr.Addt(flaterr.AnswerInlineQuery, "need a category name", err)
|
||
}
|
||
return handlerErr.Flat()
|
||
}
|
||
}
|
||
|
||
if parsedQuery.LastChar == configs.BotConfig.InlineCategorySymbol {
|
||
|
||
return handlerErr.Flat()
|
||
}
|
||
|
||
if parsedQuery.Category != "" {
|
||
category, isExist := resultCategorys.GetCategory(parsedQuery.Category)
|
||
if !isExist {
|
||
_, err := opts.Thebot.AnswerInlineQuery(opts.Ctx, &bot.AnswerInlineQueryParams{
|
||
InlineQueryID: opts.InlineQuery.ID,
|
||
Results: []models.InlineQueryResult{&models.InlineQueryResultArticle{
|
||
ID: "noThisCategory",
|
||
Title: fmt.Sprintf("无效的 [ %s ] 分类", parsedQuery.Category),
|
||
Description: fmt.Sprintf("当前列表有 %s 分类", resultCategorys.StrList()),
|
||
InputMessageContent: &models.InputTextMessageContent{ MessageText: "用户在尝试访问不存在的分类时点击了提示信息..." },
|
||
}},
|
||
IsPersonal: true,
|
||
CacheTime: 0,
|
||
})
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Str("content", "invalid category name").
|
||
Msg(flaterr.AnswerInlineQuery.Str())
|
||
handlerErr.Addt(flaterr.AnswerInlineQuery, "invalid category name", err)
|
||
}
|
||
return handlerErr.Flat()
|
||
}
|
||
filter = "type=" + category.Str()
|
||
}
|
||
datas, err := meilisearchClient.Index(targetChatID).Search(parsedQuery.KeywordQuery(), &meilisearch.SearchRequest{ Limit: int64(configs.BotConfig.InlineResultsPerPage), Filter: filter })
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Msg("Failed to get message")
|
||
handlerErr.Addf("failed to get message: %w", err)
|
||
_, err = opts.Thebot.AnswerInlineQuery(opts.Ctx, &bot.AnswerInlineQueryParams{
|
||
InlineQueryID: opts.InlineQuery.ID,
|
||
Results: []models.InlineQueryResult{&models.InlineQueryResultArticle{
|
||
ID: "error",
|
||
Title: "获取消息发生错误",
|
||
Description: "点击查看错误信息",
|
||
InputMessageContent: &models.InputTextMessageContent{
|
||
MessageText: fmt.Sprintf("获取消息时发生了错误:<blockquote expandable>%s</blockquote>", err.Error()),
|
||
ParseMode: models.ParseModeHTML,
|
||
},
|
||
}},
|
||
IsPersonal: true,
|
||
CacheTime: 0,
|
||
})
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Str("content", "get message error").
|
||
Msg(flaterr.AnswerInlineQuery.Str())
|
||
handlerErr.Addt(flaterr.AnswerInlineQuery, "get message error", err)
|
||
}
|
||
} else {
|
||
var msgDatas []meilisearch_utils.MessageData
|
||
err = meilisearch_utils.UnmarshalMessageData(&datas.Hits, &msgDatas)
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Msg("Failed to unmarshal message data")
|
||
handlerErr.Addf("Failed to unmarshal message data: %w", err)
|
||
_, err = opts.Thebot.AnswerInlineQuery(opts.Ctx, &bot.AnswerInlineQueryParams{
|
||
InlineQueryID: opts.InlineQuery.ID,
|
||
Results: []models.InlineQueryResult{&models.InlineQueryResultArticle{
|
||
ID: "error",
|
||
Title: "解析消息发生错误",
|
||
Description: "点击查看错误信息",
|
||
InputMessageContent: &models.InputTextMessageContent{
|
||
MessageText: fmt.Sprintf("解析消息时发生了错误:<blockquote expandable>%s</blockquote>", err.Error()),
|
||
ParseMode: models.ParseModeHTML,
|
||
},
|
||
}},
|
||
IsPersonal: true,
|
||
CacheTime: 0,
|
||
})
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Str("content", "unmarshal message error").
|
||
Msg(flaterr.AnswerInlineQuery.Str())
|
||
handlerErr.Addt(flaterr.AnswerInlineQuery, "unmarshal message error", err)
|
||
}
|
||
} else {
|
||
for _, msgData := range msgDatas {
|
||
switch msgData.Type {
|
||
case message_utils.Text:
|
||
resultList = append(resultList, &models.InlineQueryResultArticle{
|
||
ID: msgData.MsgIDStr(),
|
||
Title: msgData.Text,
|
||
Description: msgData.Desc,
|
||
ReplyMarkup: msgData.OriginInfo.BuildButton(),
|
||
InputMessageContent: &models.InputTextMessageContent{
|
||
MessageText: msgData.Text,
|
||
Entities: msgData.Entities,
|
||
LinkPreviewOptions: msgData.LinkPreviewOptions,
|
||
},
|
||
})
|
||
case message_utils.Audio:
|
||
resultList = append(resultList, &models.InlineQueryResultCachedAudio{
|
||
ID: msgData.MsgIDStr(),
|
||
AudioFileID: msgData.FileID,
|
||
Caption: msgData.Text,
|
||
CaptionEntities: msgData.Entities,
|
||
ReplyMarkup: msgData.OriginInfo.BuildButton(),
|
||
})
|
||
case message_utils.Document:
|
||
resultList = append(resultList, &models.InlineQueryResultCachedDocument{
|
||
ID: msgData.MsgIDStr(),
|
||
DocumentFileID: msgData.FileID,
|
||
Title: msgData.FileName,
|
||
Caption: msgData.Text,
|
||
CaptionEntities: msgData.Entities,
|
||
Description: msgData.Desc,
|
||
ReplyMarkup: msgData.OriginInfo.BuildButton(),
|
||
})
|
||
case message_utils.Animation:
|
||
resultList = append(resultList, &models.InlineQueryResultCachedMpeg4Gif{
|
||
ID: msgData.MsgIDStr(),
|
||
Mpeg4FileID: msgData.FileID,
|
||
Title: msgData.FileName,
|
||
Caption: msgData.Text,
|
||
CaptionEntities: msgData.Entities,
|
||
ReplyMarkup: msgData.OriginInfo.BuildButton(),
|
||
})
|
||
case message_utils.Photo:
|
||
resultList = append(resultList, &models.InlineQueryResultCachedPhoto{
|
||
ID: msgData.MsgIDStr(),
|
||
PhotoFileID: msgData.FileID,
|
||
Caption: msgData.Text,
|
||
CaptionEntities: msgData.Entities,
|
||
Description: msgData.Desc,
|
||
ShowCaptionAboveMedia: msgData.ShowCaptionAboveMedia,
|
||
ReplyMarkup: msgData.OriginInfo.BuildButton(),
|
||
})
|
||
case message_utils.Sticker:
|
||
resultList = append(resultList, &models.InlineQueryResultCachedSticker{
|
||
ID: msgData.MsgIDStr(),
|
||
StickerFileID: msgData.FileID,
|
||
ReplyMarkup: msgData.OriginInfo.BuildButton(),
|
||
})
|
||
case message_utils.Video:
|
||
resultList = append(resultList, &models.InlineQueryResultCachedVideo{
|
||
ID: msgData.MsgIDStr(),
|
||
VideoFileID: msgData.FileID,
|
||
Title: msgData.FileName,
|
||
Description: msgData.Desc,
|
||
Caption: msgData.Text,
|
||
CaptionEntities: msgData.Entities,
|
||
ReplyMarkup: msgData.OriginInfo.BuildButton(),
|
||
})
|
||
case message_utils.VideoNote:
|
||
resultList = append(resultList, &models.InlineQueryResultCachedDocument{
|
||
ID: msgData.MsgIDStr(),
|
||
DocumentFileID: msgData.FileID,
|
||
Title: msgData.FileName,
|
||
Description: msgData.Desc,
|
||
Caption: msgData.Text,
|
||
CaptionEntities: msgData.Entities,
|
||
ReplyMarkup: msgData.OriginInfo.BuildButton(),
|
||
})
|
||
case message_utils.Voice:
|
||
resultList = append(resultList, &models.InlineQueryResultCachedVoice{
|
||
ID: msgData.MsgIDStr(),
|
||
VoiceFileID: msgData.FileID,
|
||
Title: msgData.FileTitle,
|
||
Caption: msgData.Text,
|
||
CaptionEntities: msgData.Entities,
|
||
ReplyMarkup: msgData.OriginInfo.BuildButton(),
|
||
})
|
||
}
|
||
}
|
||
// 如果当前查询的 ID 与公共收藏夹 ID 不同,且用户存在并设定包含公共收藏内容,则添加公共收藏内容
|
||
if len(resultList) < configs.BotConfig.InlineResultsPerPage && targetChatID != channelID && user != nil && user.IncludeChannel {
|
||
button = &models.InlineQueryResultsButton{
|
||
Text: "当前包含了个人和公共收藏内容",
|
||
StartParameter: "via-inline_savedmessage-help",
|
||
}
|
||
datas, err := meilisearchClient.Index(channelID).Search(parsedQuery.KeywordQuery(), &meilisearch.SearchRequest{ Limit: int64(configs.BotConfig.InlineResultsPerPage - len(resultList)), Filter: filter })
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Msg("Failed to get message from channel")
|
||
handlerErr.Addf("failed to get message from channel: %w", err)
|
||
} else {
|
||
var msgDatasChannel []meilisearch_utils.MessageData
|
||
err = meilisearch_utils.UnmarshalMessageData(&datas.Hits, &msgDatasChannel)
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Msg("Failed to unmarshal message data from channel")
|
||
handlerErr.Addf("Failed to unmarshal message data from channel: %w", err)
|
||
} else {
|
||
for _, msgData := range msgDatasChannel {
|
||
switch msgData.Type {
|
||
case message_utils.Text:
|
||
resultList = append(resultList, &models.InlineQueryResultArticle{
|
||
ID: "channel" + msgData.MsgIDStr(),
|
||
Title: msgData.Text,
|
||
Description: msgData.Desc,
|
||
ReplyMarkup: msgData.OriginInfo.BuildButton(),
|
||
InputMessageContent: &models.InputTextMessageContent{
|
||
MessageText: msgData.Text,
|
||
Entities: msgData.Entities,
|
||
LinkPreviewOptions: msgData.LinkPreviewOptions,
|
||
},
|
||
})
|
||
case message_utils.Audio:
|
||
resultList = append(resultList, &models.InlineQueryResultCachedAudio{
|
||
ID: "channel" + msgData.MsgIDStr(),
|
||
AudioFileID: msgData.FileID,
|
||
Caption: msgData.Text,
|
||
CaptionEntities: msgData.Entities,
|
||
ReplyMarkup: msgData.OriginInfo.BuildButton(),
|
||
})
|
||
case message_utils.Document:
|
||
resultList = append(resultList, &models.InlineQueryResultCachedDocument{
|
||
ID: "channel" + msgData.MsgIDStr(),
|
||
DocumentFileID: msgData.FileID,
|
||
Title: msgData.FileName,
|
||
Caption: msgData.Text,
|
||
CaptionEntities: msgData.Entities,
|
||
Description: msgData.Desc,
|
||
ReplyMarkup: msgData.OriginInfo.BuildButton(),
|
||
})
|
||
case message_utils.Animation:
|
||
resultList = append(resultList, &models.InlineQueryResultCachedMpeg4Gif{
|
||
ID: "channel" + msgData.MsgIDStr(),
|
||
Mpeg4FileID: msgData.FileID,
|
||
Title: msgData.FileName,
|
||
Caption: msgData.Text,
|
||
CaptionEntities: msgData.Entities,
|
||
ReplyMarkup: msgData.OriginInfo.BuildButton(),
|
||
})
|
||
case message_utils.Photo:
|
||
resultList = append(resultList, &models.InlineQueryResultCachedPhoto{
|
||
ID: "channel" + msgData.MsgIDStr(),
|
||
PhotoFileID: msgData.FileID,
|
||
Caption: msgData.Text,
|
||
CaptionEntities: msgData.Entities,
|
||
Description: msgData.Desc,
|
||
ShowCaptionAboveMedia: msgData.ShowCaptionAboveMedia,
|
||
ReplyMarkup: msgData.OriginInfo.BuildButton(),
|
||
})
|
||
case message_utils.Sticker:
|
||
resultList = append(resultList, &models.InlineQueryResultCachedSticker{
|
||
ID: "channel" + msgData.MsgIDStr(),
|
||
StickerFileID: msgData.FileID,
|
||
ReplyMarkup: msgData.OriginInfo.BuildButton(),
|
||
})
|
||
case message_utils.Video:
|
||
resultList = append(resultList, &models.InlineQueryResultCachedVideo{
|
||
ID: "channel" + msgData.MsgIDStr(),
|
||
VideoFileID: msgData.FileID,
|
||
Title: msgData.FileName,
|
||
Description: msgData.Desc,
|
||
Caption: msgData.Text,
|
||
CaptionEntities: msgData.Entities,
|
||
ReplyMarkup: msgData.OriginInfo.BuildButton(),
|
||
})
|
||
case message_utils.VideoNote:
|
||
resultList = append(resultList, &models.InlineQueryResultCachedDocument{
|
||
ID: "channel" + msgData.MsgIDStr(),
|
||
DocumentFileID: msgData.FileID,
|
||
Title: msgData.FileName,
|
||
Description: msgData.Desc,
|
||
Caption: msgData.Text,
|
||
CaptionEntities: msgData.Entities,
|
||
ReplyMarkup: msgData.OriginInfo.BuildButton(),
|
||
})
|
||
case message_utils.Voice:
|
||
resultList = append(resultList, &models.InlineQueryResultCachedVoice{
|
||
ID: "channel" + msgData.MsgIDStr(),
|
||
VoiceFileID: msgData.FileID,
|
||
Title: msgData.FileTitle,
|
||
Caption: msgData.Text,
|
||
CaptionEntities: msgData.Entities,
|
||
ReplyMarkup: msgData.OriginInfo.BuildButton(),
|
||
})
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if len(resultList) == 0 {
|
||
if len(parsedQuery.Keywords) > 0 {
|
||
resultList = append(resultList, &models.InlineQueryResultArticle{
|
||
ID: "none",
|
||
Title: fmt.Sprintf("没有符合 %s 关键词的内容", parsedQuery.Keywords),
|
||
InputMessageContent: &models.InputTextMessageContent{ MessageText: "用户在找不到想看的东西时无奈点击了提示信息..." },
|
||
})
|
||
} else if user != nil {
|
||
resultList = append(resultList, &models.InlineQueryResultArticle{
|
||
ID: "empty",
|
||
Title: "没有保存内容(点击查看详细教程)",
|
||
Description: "对一条信息回复 /save 来保存它",
|
||
InputMessageContent: &models.InputTextMessageContent{
|
||
MessageText: fmt.Sprintf("您可以在任何聊天的输入栏中输入 <code>@%s +saved </code>来查看您的收藏\n若要添加,您需要确保机器人可以读取到您的指令,例如在群组中需要添加机器人,或点击 @%s 进入与机器人的聊天窗口,找到想要收藏的信息,然后对着那条信息回复 /save 即可\n若收藏成功,机器人会回复您并提示收藏成功,您也可以手动发送一条想要收藏的息,再使用 /save 命令回复它", configs.BotMe.Username, configs.BotMe.Username),
|
||
ParseMode: models.ParseModeHTML,
|
||
},
|
||
})
|
||
button = &models.InlineQueryResultsButton{
|
||
Text: "点击此处快速跳转到机器人",
|
||
StartParameter: "via-inline_noreply",
|
||
}
|
||
} else {
|
||
resultList = append(resultList, &models.InlineQueryResultArticle{
|
||
ID: "none",
|
||
Title: "什么都没有",
|
||
InputMessageContent: &models.InputTextMessageContent{ MessageText: "用户在找不到想看的东西时无奈点击了提示信息..." },
|
||
})
|
||
}
|
||
}
|
||
|
||
_, err := opts.Thebot.AnswerInlineQuery(opts.Ctx, &bot.AnswerInlineQueryParams{
|
||
InlineQueryID: opts.InlineQuery.ID,
|
||
Results: resultList,
|
||
Button: button,
|
||
IsPersonal: true,
|
||
CacheTime: 0,
|
||
})
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Str("content", "saved message result").
|
||
Msg(flaterr.AnswerInlineQuery.Str())
|
||
handlerErr.Addt(flaterr.AnswerInlineQuery, "saved message result", err)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return handlerErr.Flat()
|
||
}
|
||
|
||
func SendPrivacyPolicy(opts *handler_params.Message) error {
|
||
var handlerErr flaterr.MultErr
|
||
|
||
_, err := opts.Thebot.SendMessage(opts.Ctx, &bot.SendMessageParams{
|
||
ChatID: opts.Message.Chat.ID,
|
||
Text: "目前此机器人仍在开发阶段中,此信息可能会有更改\n" +
|
||
"<blockquote expandable>本机器人提供收藏信息功能,您可以在回复一条信息时输入 /save 来收藏它,之后在 inline 模式下随时浏览您的收藏内容并发送\n\n" +
|
||
|
||
"我们会记录哪些数据?\n" +
|
||
"1. 您的用户信息,例如 用户昵称、用户 ID、聊天类型(当您将此机器人添加到群组或频道中时)\n" +
|
||
"2. 您的使用情况,例如 消息计数、inline 调用计数、inline 条目计数、最后向机器人发送的消息、callback_query、inline_query 以及选择的 inline 结果\n" +
|
||
"3. 收藏信息内容,您需要注意这个,因为您是为了这个而阅读此内容,例如 存储的收藏信息数量、其图片上传到 Telegram 时的文件 ID、图片下方的文本,还有您在使用添加命令时所自定义的搜索关键词" +
|
||
"\n\n" +
|
||
|
||
"我的数据安全吗?\n" +
|
||
"这是一个早期的项目,还有很多未发现的 bug 与漏洞,因此您不能也不应该将敏感的数据存储在此机器人中,若您觉得我们收集的信息不妥,您可以不点击底部的同意按钮,我们仅会收集一些基本的信息,防止对机器人造成滥用,基本信息为前一段的 1 至 2 条目" +
|
||
"\n\n" +
|
||
|
||
"我收藏的消息,有谁可以看到?\n" +
|
||
"此功能被设计为每个人有单独的存储空间,如果您不手动从 inline 模式下选择信息并发送,其他用户是没法查看您的收藏列表的。不过,与上一个条目一样,为了防止滥用,我们是可以也有权利查看您收藏的内容的,请不要在其中保存隐私数据" +
|
||
"</blockquote>" +
|
||
|
||
"\n\n" +
|
||
"内容待补充...",
|
||
ReplyParameters: &models.ReplyParameters{ MessageID: opts.Message.ID },
|
||
ReplyMarkup: &models.InlineKeyboardMarkup{ InlineKeyboard: [][]models.InlineKeyboardButton{{{
|
||
Text: "点击同意以上内容",
|
||
URL: fmt.Sprintf("https://t.me/%s?start=savedmessage_privacy_policy_agree", configs.BotMe.Username),
|
||
}}}},
|
||
ParseMode: models.ParseModeHTML,
|
||
})
|
||
if err != nil {
|
||
zerolog.Ctx(opts.Ctx).Error().
|
||
Err(err).
|
||
Str("pluginName", "Saved Message").
|
||
Str(utils.GetCurrentFuncName()).
|
||
Dict(utils.GetUserDict(opts.Message.From)).
|
||
Str("content", "saved message privacy policy").
|
||
Msg(flaterr.SendMessage.Str())
|
||
handlerErr.Addt(flaterr.SendMessage, "saved message privacy policy", err)
|
||
}
|
||
|
||
return handlerErr.Flat()
|
||
}
|
||
|
||
func AgreePrivacyPolicy(opts *handler_params.Message) error {
|
||
logger := zerolog.Ctx(opts.Ctx).
|
||
With().
|
||
Str("pluginName", "Saved Message").
|
||
Str(utils.GetCurrentFuncName()).
|
||
Dict(utils.GetUserDict(opts.Message.From)).
|
||
Logger()
|
||
|
||
var handlerErr flaterr.MultErr
|
||
|
||
if SavedMessageList.GetUser(opts.Message.From.ID) != nil { return nil }
|
||
|
||
var user SavedMessageUser
|
||
user.UserID = opts.Message.From.ID
|
||
SavedMessageList.User = append(SavedMessageList.User, user)
|
||
err := meilisearch_utils.CreateChatIndex(opts.Ctx, &meilisearchClient, user.IDStr())
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Msg("failed to create chat index for saved message user")
|
||
handlerErr.Addf("failed to create chat index for saved message user: %w", err)
|
||
_, err = opts.Thebot.SendMessage(opts.Ctx, &bot.SendMessageParams{
|
||
ChatID: opts.Message.Chat.ID,
|
||
Text: fmt.Sprintf("创建收藏信息索引失败,请稍后再试或联系机器人管理员:\n<blockquote expandable>%s</blockquote>", err.Error()),
|
||
ParseMode: models.ParseModeHTML,
|
||
})
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Str("content", "failed to create chat index notice").
|
||
Msg(flaterr.SendMessage.Str())
|
||
handlerErr.Addt(flaterr.SendMessage, "failed to create chat index notice", err)
|
||
}
|
||
return handlerErr.Flat()
|
||
}
|
||
|
||
err = SaveSavedMessageList(opts.Ctx)
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Msg("failed to save savemessage list after user agree privacy policy")
|
||
handlerErr.Addf("failed to save savemessage list after user agree privacy policy: %w", err)
|
||
|
||
_, err = opts.Thebot.SendMessage(opts.Ctx, &bot.SendMessageParams{
|
||
ChatID: opts.Message.Chat.ID,
|
||
Text: fmt.Sprintf("保存收藏列表数据库失败,请稍后再试或联系机器人管理员\n<blockquote expandable>%s</blockquote>", err.Error()),
|
||
ParseMode: models.ParseModeHTML,
|
||
})
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Str("content", "failed to save savedmessage list notice").
|
||
Msg(flaterr.SendMessage.Str())
|
||
handlerErr.Addt(flaterr.SendMessage, "failed to save savedmessage list notice", err)
|
||
}
|
||
return handlerErr.Flat()
|
||
}
|
||
|
||
_, err = opts.Thebot.SendMessage(opts.Ctx, &bot.SendMessageParams{
|
||
ChatID: opts.Message.Chat.ID,
|
||
Text: "您已成功开启收藏信息功能,回复一条信息的时候发送 /save 来使用收藏功能吧!\n由于服务器性能原因,每个人的收藏数量上限默认为 100 个,您也可以从机器人的个人信息中寻找管理员来申请更高的上限\n点击下方按钮来浏览您的收藏内容",
|
||
ReplyParameters: &models.ReplyParameters{ MessageID: opts.Message.ID },
|
||
ReplyMarkup: &models.InlineKeyboardMarkup{ InlineKeyboard: [][]models.InlineKeyboardButton{{{
|
||
Text: "点击浏览您的收藏",
|
||
SwitchInlineQueryCurrentChat: configs.BotConfig.InlineSubCommandSymbol + "saved ",
|
||
}}}},
|
||
})
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Str("content", "saved message function enabled").
|
||
Msg(flaterr.SendMessage.Str())
|
||
handlerErr.Addt(flaterr.SendMessage, "saved message function enabled", err)
|
||
} else {
|
||
buildSavedMessageByMessageHandlers()
|
||
}
|
||
|
||
return handlerErr.Flat()
|
||
}
|
||
|
||
func configKeyboardCallbackHandler(opts *handler_params.CallbackQuery) error {
|
||
logger := zerolog.Ctx(opts.Ctx).
|
||
With().
|
||
Str("pluginName", "Saved Message").
|
||
Str(utils.GetCurrentFuncName()).
|
||
Dict(utils.GetUserDict(&opts.CallbackQuery.From)).
|
||
Str("callbackData", opts.CallbackQuery.Data).
|
||
Logger()
|
||
|
||
var handlerErr flaterr.MultErr
|
||
var needSave bool = true
|
||
|
||
user := SavedMessageList.GetUser(opts.CallbackQuery.From.ID)
|
||
|
||
switch opts.CallbackQuery.Data {
|
||
case "savedmsg_switch_include_channel":
|
||
user.IncludeChannel = !user.IncludeChannel
|
||
case "savedmsg_switch_drop_origin_info":
|
||
user.DropOriginInfo = !user.DropOriginInfo
|
||
default:
|
||
needSave = false
|
||
}
|
||
|
||
if needSave {
|
||
err := SaveSavedMessageList(opts.Ctx)
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Msg("failed to save savedmessage list after user config")
|
||
handlerErr.Addf("failed to save savedmessage list after user config: %w", err)
|
||
_, err = opts.Thebot.AnswerCallbackQuery(opts.Ctx, &bot.AnswerCallbackQueryParams{
|
||
CallbackQueryID: opts.CallbackQuery.ID,
|
||
Text: "保存配置失败,请稍后再试或联系机器人管理员",
|
||
ShowAlert: true,
|
||
})
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Str("content", "failed to save user config notice").
|
||
Msg(flaterr.AnswerCallbackQuery.Str())
|
||
handlerErr.Addt(flaterr.AnswerCallbackQuery, "failed to save user config notice", err)
|
||
}
|
||
return handlerErr.Flat()
|
||
}
|
||
}
|
||
|
||
_, err := opts.Thebot.EditMessageText(opts.Ctx, &bot.EditMessageTextParams{
|
||
ChatID: opts.CallbackQuery.Message.Message.Chat.ID,
|
||
MessageID: opts.CallbackQuery.Message.Message.ID,
|
||
Text: "修改您的收藏偏好选项",
|
||
ParseMode: models.ParseModeHTML,
|
||
ReplyMarkup: user.buildUserConfigButtons(),
|
||
})
|
||
if err != nil {
|
||
logger.Error().
|
||
Err(err).
|
||
Str("content", "config keyboard").
|
||
Msg(flaterr.EditMessageText.Str())
|
||
handlerErr.Addt(flaterr.EditMessageText, "config keyboard", err)
|
||
}
|
||
|
||
return handlerErr.Flat()
|
||
|
||
}
|
||
|
||
func Init() {
|
||
plugin_utils.AddInitializer(plugin_utils.Initializer{
|
||
Name: "Saved Message",
|
||
Func: func(ctx context.Context) error{
|
||
err := ReadSavedMessageList(ctx)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
// if SavedMessageList.User == nil { SavedMessageList.User = []SavedMessageUser{} }
|
||
|
||
if SavedMessageList.MeiliURL == "" {
|
||
return errors.New("Meilisearch URL is not set")
|
||
} else {
|
||
meilisearchClient = meilisearch.New(SavedMessageList.MeiliURL, meilisearch.WithAPIKey(SavedMessageList.MeiliAPI))
|
||
if SavedMessageList.ChannelID == 0 {
|
||
return errors.New("channel ID is not set")
|
||
} else {
|
||
chatIDString := SavedMessageList.ChannelIDStr()
|
||
|
||
plugin_utils.AddHandlerByMessageChatIDHandlers(plugin_utils.ByMessageChatIDHandler{
|
||
ForChatID: SavedMessageList.ChannelID,
|
||
PluginName: "savedmessage_channel",
|
||
MessageHandler: channelSaveMessageHandler,
|
||
})
|
||
|
||
channelPubliclink = "https://t.me/" + SavedMessageList.ChannelUsername
|
||
channelPrivateLink = "https://t.me/c/" + utils.RemoveIDPrefix(SavedMessageList.ChannelID)
|
||
|
||
plugin_utils.AddFullCommandHandlers([]plugin_utils.FullCommand{
|
||
{
|
||
FullCommand: channelPubliclink,
|
||
ForChatType: []models.ChatType{models.ChatTypePrivate},
|
||
MessageHandler: channelMetadataHandler,
|
||
},
|
||
{
|
||
FullCommand: channelPrivateLink,
|
||
ForChatType: []models.ChatType{models.ChatTypePrivate},
|
||
MessageHandler: channelMetadataHandler,
|
||
},
|
||
}...)
|
||
|
||
_, err := meilisearchClient.GetIndex(chatIDString)
|
||
if err != nil {
|
||
if err.(*meilisearch.Error).MeilisearchApiError.Code == "index_not_found" {
|
||
err := meilisearch_utils.CreateChatIndex(ctx, &meilisearchClient, chatIDString)
|
||
if err != nil {
|
||
return fmt.Errorf("failed to create index: %w", err)
|
||
}
|
||
} else {
|
||
return fmt.Errorf("failed to get index: %w", err)
|
||
}
|
||
}
|
||
}
|
||
|
||
message_meilisearch.Init(&meilisearchClient)
|
||
}
|
||
return nil
|
||
},
|
||
})
|
||
plugin_utils.AddDataBaseHandler(plugin_utils.DatabaseHandler{
|
||
Name: "Saved Message",
|
||
Saver: SaveSavedMessageList,
|
||
Loader: ReadSavedMessageList,
|
||
})
|
||
plugin_utils.AddSlashCommandHandlers(plugin_utils.SlashCommand{
|
||
SlashCommand: "save",
|
||
MessageHandler: saveMessageHandler,
|
||
})
|
||
plugin_utils.AddInlineManualHandlers(plugin_utils.InlineManualHandler{
|
||
Command: "saved",
|
||
InlineHandler: InlineSavedMessageHandler,
|
||
Description: "显示保存的消息",
|
||
})
|
||
plugin_utils.AddSlashStartCommandHandlers([]plugin_utils.SlashStartHandler{
|
||
{
|
||
Argument: "savedmessage_privacy_policy",
|
||
MessageHandler: SendPrivacyPolicy,
|
||
},
|
||
{
|
||
Argument: "savedmessage_privacy_policy_agree",
|
||
MessageHandler: AgreePrivacyPolicy,
|
||
},
|
||
}...)
|
||
plugin_utils.AddSlashStartWithPrefixCommandHandlers(plugin_utils.SlashStartWithPrefixHandler{
|
||
Prefix: "via-inline",
|
||
Argument: "savedmessage-help",
|
||
MessageHandler: saveMessageHandler,
|
||
})
|
||
plugin_utils.AddCallbackQueryHandlers([]plugin_utils.CallbackQuery{
|
||
{
|
||
CallbackDataPrefix: "savedmsg_switch",
|
||
CallbackQueryHandler: configKeyboardCallbackHandler,
|
||
},
|
||
{
|
||
CallbackDataPrefix: "savedmsg_channel",
|
||
CallbackQueryHandler: channelCallbackHandler,
|
||
},
|
||
}...)
|
||
plugin_utils.AddHandlerHelpInfo(plugin_utils.HandlerHelp{
|
||
Name: "收藏消息",
|
||
Description: "此功能可以收藏用户指定的消息,之后使用 inline 模式查看并发送保存的内容\n\n保存消息:\n向机器人发送要保存的消息,然后使用 <code>/save 关键词</code> 命令回复要保存的消息,关键词可以忽略。若机器人在群组中,也可以直接使用 <code>/save 关键词</code> 命令回复要保存的消息。\n\n发送保存的消息:\n点击下方的按钮来使用 inline 模式,当您多次在 inline 模式下使用此 bot 时,在输入框中输入 <code>@</code> 即可看到 bot 会出现在列表中",
|
||
ParseMode: models.ParseModeHTML,
|
||
ReplyMarkup: &models.InlineKeyboardMarkup{ InlineKeyboard: [][]models.InlineKeyboardButton{
|
||
{{
|
||
Text: "点击浏览您的收藏",
|
||
SwitchInlineQueryCurrentChat: configs.BotConfig.InlineSubCommandSymbol + "saved ",
|
||
}},
|
||
{{
|
||
Text: "将此功能设定为您的默认 inline 命令",
|
||
CallbackData: "inline_default_noedit_saved",
|
||
}},
|
||
{
|
||
{
|
||
Text: "返回",
|
||
CallbackData: "help",
|
||
},
|
||
{
|
||
Text: "关闭",
|
||
CallbackData: "delete_this_message",
|
||
},
|
||
},
|
||
}},
|
||
})
|
||
}
|