Files

849 lines
32 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package channel
import (
"context"
"fmt"
"strconv"
"strings"
"time"
"trbot/plugins/saved_message/common"
"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/contain"
"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"
)
var channelPubliclink string
var channelPrivateLink string
var stateMessageID int
var editingMessageID int // 用于编辑消息时的消息ID
// by chat ID handler
func channelSaveMessageHandler(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()
if common.MeilisearchClient == nil {
logger.Warn().
Int("messageID", opts.Message.ID).
Msg("Meilisearch client is not initialized, skipping indexing")
} else {
msgData := meilisearch_utils.BuildMessageData(opts.Ctx, opts.Thebot, opts.Message)
var messageLength int
if opts.Message.Caption != "" {
messageLength = common.UTF16Length(opts.Message.Caption)
msgData.Entities = opts.Message.CaptionEntities
} else if opts.Message.Text != "" {
messageLength = common.UTF16Length(opts.Message.Text)
msgData.Entities = opts.Message.Entities
}
// 若字符长度大于设定的阈值,添加折叠样式引用再保存,如果是全文引用但不折叠,改成折叠样式
if messageLength > common.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.OriginInfo = origin_info.GetOriginInfo(opts.Message)
taskinfo, err := common.MeilisearchClient.Index(common.SavedMessageList.ChannelIDStr()).AddDocuments(msgData)
if err != nil {
logger.Error().
Err(err).
Int("messageID", opts.Message.ID).
Msg("failed to send add document request to Meilisearch")
return fmt.Errorf("failed to send add document request to Meilisearch: %w", err)
} else {
task, err := meilisearch_utils.WaitForTask(opts.Ctx, &common.MeilisearchClient, taskinfo.TaskUID, time.Second * 1)
if err != nil {
return fmt.Errorf("wait for add document task failed: %w", err)
} else if task.Status != meilisearch.TaskStatusSucceeded {
return fmt.Errorf("failed to add document: %s", task.Error.Message)
}
}
if common.SavedMessageList.NoticeChatID != 0 {
_, err = opts.Thebot.SendMessage(opts.Ctx, &bot.SendMessageParams{
ChatID: common.SavedMessageList.NoticeChatID,
Text: "已经在频道中保存了一个新消息,要为它添加关键词吗?",
DisableNotification: true,
ReplyMarkup: buildMetadataKeyboard(msgData),
ReplyParameters: &models.ReplyParameters{
MessageID: opts.Message.ID,
ChatID: common.SavedMessageList.ChannelID,
},
})
if err != nil {
logger.Error().
Err(err).
Int("messageID", opts.Message.ID).
Str("content", "channel message saved").
Msg(flaterr.SendMessage.Str())
return fmt.Errorf(flaterr.SendMessage.Fmt(), "channel message saved", err)
}
}
}
return nil
}
// send link to bot to edit metadata
func channelMetadataHandler(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
var msgIDString string
var msgData meilisearch_utils.MessageData
indexManager := common.MeilisearchClient.Index(common.SavedMessageList.ChannelIDStr())
if !contain.Int64(opts.Message.From.ID, configs.BotConfig.AdminIDs...) {
_, err := opts.Thebot.SendMessage(opts.Ctx, &bot.SendMessageParams{
ChatID: opts.Message.Chat.ID,
Text: "??",
ReplyParameters: &models.ReplyParameters{ MessageID: opts.Message.ID },
})
if err != nil {
logger.Error().
Err(err).
Int("messageID", opts.Message.ID).
Str("content", "no permission to edit metadata").
Msg(flaterr.SendMessage.Str())
handlerErr.Addt(flaterr.SendMessage, "no permission to edit metadata", err)
}
} else {
if len(opts.Fields) > 1 {
msgIDString = opts.Fields[1]
} else if strings.HasPrefix(opts.Message.Text, channelPubliclink) {
msgIDString = strings.TrimPrefix(opts.Message.Text, channelPubliclink + "/")
} else if strings.HasPrefix(opts.Message.Text, channelPrivateLink) {
msgIDString = strings.TrimPrefix(opts.Message.Text, channelPrivateLink + "/")
}
if msgIDString != "" {
err := indexManager.GetDocument(msgIDString, nil, &msgData)
if err != nil {
if err.(*meilisearch.Error).MeilisearchApiError.Code == "document_not_found" {
_, err = opts.Thebot.SendMessage(opts.Ctx, &bot.SendMessageParams{
ChatID: opts.Message.Chat.ID,
Text: "未找到该消息,请检查消息 ID 是否正确",
ReplyParameters: &models.ReplyParameters{ MessageID: opts.Message.ID },
LinkPreviewOptions: &models.LinkPreviewOptions{
},
})
if err != nil {
logger.Error().
Err(err).
Int("messageID", opts.Message.ID).
Str("content", "document not found in index").
Msg(flaterr.SendMessage.Str())
handlerErr.Addt(flaterr.SendMessage, "document not found in index", err)
}
} else {
logger.Error().
Err(err).
Int("messageID", opts.Message.ID).
Msg("Failed to get message from index")
handlerErr.Addf("failed to get message from index: %w", err)
_, err = opts.Thebot.SendMessage(opts.Ctx, &bot.SendMessageParams{
ChatID: opts.Message.Chat.ID,
Text: "获取消息失败,请稍后再试",
ReplyParameters: &models.ReplyParameters{ MessageID: opts.Message.ID },
LinkPreviewOptions: &models.LinkPreviewOptions{
},
})
if err != nil {
logger.Error().
Err(err).
Int("messageID", opts.Message.ID).
Str("content", "failed to get message notice").
Msg(flaterr.SendMessage.Str())
handlerErr.Addt(flaterr.SendMessage, "failed to get message notice", err)
}
}
} else {
var pendingMessage string
pendingMessage += fmt.Sprintf("ID: %d\n", msgData.ID)
pendingMessage += fmt.Sprintf("类型: %s\n", msgData.Type)
if msgData.FileID != "" {
pendingMessage += fmt.Sprintf("文件 ID: %s\n", msgData.FileID)
}
if msgData.FileName != "" {
pendingMessage += fmt.Sprintf("文件名: %s\n", msgData.FileName)
}
if msgData.FileTitle != "" {
pendingMessage += fmt.Sprintf("文件标题: %s\n", msgData.FileTitle)
}
if msgData.Text != "" {
pendingMessage += fmt.Sprintf("文本: <blockquote expandable>%s</blockquote>\n", msgData.Text)
}
if msgData.Desc != "" {
pendingMessage += fmt.Sprintf("描述: <blockquote expandable>%s</blockquote>\n", msgData.Desc)
}
_, err = opts.Thebot.SendMessage(opts.Ctx, &bot.SendMessageParams{
ChatID: opts.Message.Chat.ID,
Text: pendingMessage,
ParseMode: models.ParseModeHTML,
ReplyMarkup: buildMetadataKeyboard(msgData),
ReplyParameters: &models.ReplyParameters{ MessageID: opts.Message.ID },
})
if err != nil {
logger.Error().
Err(err).
Int("messageID", opts.Message.ID).
Str("content", "channel document info").
Msg(flaterr.SendMessage.Str())
handlerErr.Addt(flaterr.SendMessage, "channel document info", err)
}
logger.Info().
Interface("msgData", msgData).
Msg("Retrieved message data from index")
}
}
}
return handlerErr.Flat()
}
func buildMetadataKeyboard(msgData meilisearch_utils.MessageData) models.ReplyMarkup {
return &models.InlineKeyboardMarkup{
InlineKeyboard: [][]models.InlineKeyboardButton{
{
{
Text: "修改描述",
CallbackData: fmt.Sprintf("savedmsg_channel_add_desc_%d", msgData.ID),
},
{
Text: "折叠消息",
CallbackData: fmt.Sprintf("savedmsg_channel_expandable_%d", msgData.ID),
},
},
{
{
Text: "查看消息",
URL: utils.MsgLinkPrivate(common.SavedMessageList.ChannelID, msgData.ID),
},
},
},
}
}
func channelCallbackHandler(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()
if strings.HasPrefix(opts.CallbackQuery.Data, "savedmsg_channel_add_desc_") {
msgIDString := strings.TrimPrefix(opts.CallbackQuery.Data, "savedmsg_channel_add_desc_")
msgID, err := strconv.Atoi(msgIDString)
if err != nil {
logger.Error().
Err(err).
Msg("Failed to parse message ID from callback data")
return fmt.Errorf("failed to parse message ID: %w", err)
}
msg, err := opts.Thebot.EditMessageText(opts.Ctx, &bot.EditMessageTextParams{
ChatID: opts.CallbackQuery.Message.Message.Chat.ID,
MessageID: opts.CallbackQuery.Message.Message.ID,
Text: "请输入新的描述信息,或发送 /cancel 取消编辑。",
ReplyMarkup: &models.InlineKeyboardMarkup{ InlineKeyboard: [][]models.InlineKeyboardButton{{{
Text: "查看消息",
URL: utils.MsgLinkPrivate(common.SavedMessageList.ChannelID, editingMessageID),
}}}},
})
if err != nil {
logger.Error().
Err(err).
Int("messageID", opts.CallbackQuery.Message.Message.ID).
Str("content", "send text to edit description").
Msg(flaterr.EditMessageText.Str())
return fmt.Errorf(flaterr.EditMessageText.Fmt(), "send text to edit description", err)
} else {
stateMessageID = msg.ID
editingMessageID = msgID
plugin_utils.AddMessageStateHandler(plugin_utils.MessageStateHandler{
ForChatID: opts.CallbackQuery.Message.Message.Chat.ID,
PluginName: "edit_description_state",
Remaining: 1,
MessageHandler: editDescriptionHandler,
CancelHandler: func(opts *handler_params.Message) error {
_, err := opts.Thebot.EditMessageText(opts.Ctx, &bot.EditMessageTextParams{
ChatID: opts.Message.Chat.ID,
MessageID: stateMessageID,
Text: "已取消编辑",
ReplyMarkup: &models.InlineKeyboardMarkup{ InlineKeyboard: [][]models.InlineKeyboardButton{{{
Text: "查看消息",
URL: utils.MsgLinkPrivate(common.SavedMessageList.ChannelID, editingMessageID),
}}}},
})
stateMessageID = 0
editingMessageID = 0
if err != nil {
return fmt.Errorf(flaterr.EditMessageText.Fmt(), "cancel edit description notice", err)
}
_, err = opts.Thebot.DeleteMessage(opts.Ctx, &bot.DeleteMessageParams{
ChatID: opts.Message.Chat.ID,
MessageID: opts.Message.ID,
})
if err != nil {
return fmt.Errorf(flaterr.DeleteMessage.Fmt(), "cancel edit description command", err)
}
return nil
},
})
}
} else if strings.HasPrefix(opts.CallbackQuery.Data, "savedmsg_channel_expandable_") {
msgIDString := strings.TrimPrefix(opts.CallbackQuery.Data, "savedmsg_channel_expandable_")
var msgData meilisearch_utils.MessageData
err := common.MeilisearchClient.Index(common.SavedMessageList.ChannelIDStr()).GetDocument(msgIDString, nil, &msgData)
if err != nil {
logger.Error().
Err(err).
Msg("Failed to get message data that need edit to expandable blockquote")
return fmt.Errorf("failed to get message data that need edit to expandable blockquote: %w", err)
}
taskinfo, err := common.MeilisearchClient.Index(common.SavedMessageList.ChannelIDStr()).UpdateDocuments(&meilisearch_utils.MessageData{
ID: msgData.ID,
Entities: append(msgData.Entities, models.MessageEntity{
Type: models.MessageEntityTypeExpandableBlockquote,
Offset: 0,
Length: common.UTF16Length(msgData.Text),
}),
})
if err != nil {
logger.Error().
Err(err).
Msg("Failed to send update document entities request to Meilisearch")
return fmt.Errorf("failed to send update document entities request to Meilisearch: %w", err)
} else {
task, err := meilisearch_utils.WaitForTask(opts.Ctx, &common.MeilisearchClient, taskinfo.TaskUID, time.Second * 1)
if err != nil {
return fmt.Errorf("wait for update document entities failed: %w", err)
} else if task.Status != meilisearch.TaskStatusSucceeded {
return fmt.Errorf("failed to update document entities: %s", task.Error.Message)
}
_, err = opts.Thebot.EditMessageText(opts.Ctx, &bot.EditMessageTextParams{
ChatID: opts.CallbackQuery.Message.Message.Chat.ID,
MessageID: opts.CallbackQuery.Message.Message.ID,
Text: "已为消息启用折叠样式",
ReplyMarkup: &models.InlineKeyboardMarkup{ InlineKeyboard: [][]models.InlineKeyboardButton{{{
Text: "查看消息",
URL: utils.MsgLinkPrivate(common.SavedMessageList.ChannelID, editingMessageID),
}}}},
})
editingMessageID = 0 // Reset the editing message ID after successful update
if err != nil {
logger.Error().
Err(err).
Int("messageID", opts.CallbackQuery.Message.Message.ID).
Str("content", "entities updated notice").
Msg(flaterr.EditMessageText.Str())
return fmt.Errorf(flaterr.EditMessageText.Fmt(), "entities updated notice", err)
}
}
}
return nil
}
func editDescriptionHandler(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)).
Int("editingMessageID", editingMessageID).
Logger()
taskinfo, err := common.MeilisearchClient.Index(common.SavedMessageList.ChannelIDStr()).UpdateDocuments(&meilisearch_utils.MessageData{
ID: editingMessageID,
Desc: opts.Message.Text,
})
if err != nil {
logger.Error().
Err(err).
Msg("Failed to send update document description request to Meilisearch")
return fmt.Errorf("failed to send update document description request to Meilisearch: %w", err)
} else {
task, err := meilisearch_utils.WaitForTask(opts.Ctx, &common.MeilisearchClient, taskinfo.TaskUID, time.Second * 1)
if err != nil {
return fmt.Errorf("wait for update document description failed: %w", err)
} else if task.Status != meilisearch.TaskStatusSucceeded {
return fmt.Errorf("failed to update document description: %s", task.Error.Message)
}
_, err = opts.Thebot.EditMessageText(opts.Ctx, &bot.EditMessageTextParams{
ChatID: opts.Message.Chat.ID,
MessageID: stateMessageID,
Text: fmt.Sprintf("消息描述已更新为:[ %s ]", opts.Message.Text),
ReplyMarkup: &models.InlineKeyboardMarkup{ InlineKeyboard: [][]models.InlineKeyboardButton{{{
Text: "查看消息",
URL: utils.MsgLinkPrivate(common.SavedMessageList.ChannelID, editingMessageID),
}}}},
})
editingMessageID = 0 // Reset the editing message ID after successful update
if err != nil {
logger.Error().
Err(err).
Int("messageID", opts.Message.ID).
Str("content", "description updated notice").
Msg(flaterr.EditMessageText.Str())
return fmt.Errorf(flaterr.EditMessageText.Fmt(), "description updated notice", err)
}
_, err = opts.Thebot.DeleteMessage(opts.Ctx, &bot.DeleteMessageParams{
ChatID: opts.Message.Chat.ID,
MessageID: opts.Message.ID,
})
if err != nil {
logger.Error().
Err(err).
Int("messageID", opts.Message.ID).
Str("content", "update description text message").
Msg(flaterr.DeleteMessage.Str())
return fmt.Errorf(flaterr.DeleteMessage.Fmt(), "update description text message", err)
}
}
return nil
}
func channelInlineHandler(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
var resultList []models.InlineQueryResult
if common.MeilisearchClient == nil {
resultList = append(resultList, &models.InlineQueryResultArticle{
ID: "error",
Title: "此功能不可用",
Description: "Meilisearch 服务尚未初始化",
InputMessageContent: &models.InputTextMessageContent{ MessageText: "Meilisearch 服务尚未初始化,无法使用收藏功能" },
})
} else {
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 分类", common.ResultCategorys.StrList()),
InputMessageContent: &models.InputTextMessageContent{ MessageText: "用户在尝试选择分类时点击了提示信息..." },
}},
})
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: "keepInputNumber",
Title: "请继续输入页码",
Description: "请手动输入页码来尝试可用的页面",
InputMessageContent: &models.InputTextMessageContent{ MessageText: "用户在尝试输入页码时点击了提示信息..." },
}},
})
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.Page < 1 {
_, err := opts.Thebot.AnswerInlineQuery(opts.Ctx, &bot.AnswerInlineQueryParams{
InlineQueryID: opts.InlineQuery.ID,
Results: []models.InlineQueryResult{&models.InlineQueryResultArticle{
ID: "wrongPageNumber",
Title: "错误的页码",
Description: fmt.Sprintf("您输入的页码 %d 为负数", parsedQuery.Page),
InputMessageContent: &models.InputTextMessageContent{ MessageText: "用户在浏览不存在的页面时点击了错误页码提示..." },
}},
})
if err != nil {
logger.Error().
Err(err).
Str("content", "invalid page number").
Msg(flaterr.AnswerInlineQuery.Str())
handlerErr.Addt(flaterr.AnswerInlineQuery, "invalid page number", err)
}
return handlerErr.Flat()
}
var filter string
if parsedQuery.Category != "" {
category, isExist := common.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 分类", common.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 := common.MeilisearchClient.Index(common.SavedMessageList.ChannelIDStr()).Search(parsedQuery.KeywordQuery(), &meilisearch.SearchRequest{
HitsPerPage: int64(configs.BotConfig.InlineResultsPerPage - 1),
Page: int64(parsedQuery.Page),
Filter: filter,
})
if err != nil {
logger.Error().
Err(err).
Msg("Failed to get channel saved message")
handlerErr.Addf("failed to get channel saved message: %w", err)
resultList = append(resultList, &models.InlineQueryResultArticle{
ID: "error",
Title: "获取消息发生错误",
Description: "点击查看错误信息",
InputMessageContent: &models.InputTextMessageContent{
MessageText: fmt.Sprintf("获取消息时发生了错误:<blockquote expandable>%s</blockquote>", utils.IgnoreHTMLTags(err.Error())),
ParseMode: models.ParseModeHTML,
},
})
} else if int64(parsedQuery.Page) > datas.TotalPages {
if len(parsedQuery.Keywords) > 0 {
resultList = append(resultList, &models.InlineQueryResultArticle{
ID: "noMatchItem",
Title: fmt.Sprintf("没有符合 %s 关键词的内容", parsedQuery.Keywords),
Description: "试试其他关键词?",
InputMessageContent: &models.InputTextMessageContent{ MessageText: "用户在找不到想看的东西时无奈点击了提示信息..." },
})
} else if parsedQuery.Page > 1 {
resultList = append(resultList, &models.InlineQueryResultArticle{
ID: "noMorePage",
Title: "没有更多消息了",
InputMessageContent: &models.InputTextMessageContent{ MessageText: "用户在找不到想看的东西时无奈点击了提示信息..." },
})
} else {
resultList = append(resultList, &models.InlineQueryResultArticle{
ID: "noItemInChannel",
Title: "什么都没有",
Description: "公共频道中没有保存任何内容",
InputMessageContent: &models.InputTextMessageContent{ MessageText: "用户在找不到想看的东西时无奈点击了提示信息..." },
})
}
} else {
var msgDatas []meilisearch_utils.MessageData
err = meilisearch_utils.UnmarshalMessageData(&datas.Hits, &msgDatas)
if err != nil {
logger.Error().
Err(err).
Msg("Failed to unmarshal channel saved message data")
handlerErr.Addf("Failed to unmarshal channel saved message data: %w", err)
resultList = append(resultList, &models.InlineQueryResultArticle{
ID: "error",
Title: "解析消息发生错误",
Description: "点击查看错误信息",
InputMessageContent: &models.InputTextMessageContent{
MessageText: fmt.Sprintf("解析消息时发生了错误:<blockquote expandable>%s</blockquote>", utils.IgnoreHTMLTags(err.Error())),
ParseMode: models.ParseModeHTML,
},
})
} 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.BuildButton(common.SavedMessageList.ChannelUsername),
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.BuildButton(common.SavedMessageList.ChannelUsername),
})
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.BuildButton(common.SavedMessageList.ChannelUsername),
})
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.BuildButton(common.SavedMessageList.ChannelUsername),
})
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.BuildButton(common.SavedMessageList.ChannelUsername),
})
case message_utils.Sticker:
resultList = append(resultList, &models.InlineQueryResultCachedSticker{
ID: msgData.MsgIDStr(),
StickerFileID: msgData.FileID,
ReplyMarkup: msgData.BuildButton(common.SavedMessageList.ChannelUsername),
})
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.BuildButton(common.SavedMessageList.ChannelUsername),
})
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.BuildButton(common.SavedMessageList.ChannelUsername),
})
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.BuildButton(common.SavedMessageList.ChannelUsername),
})
}
}
if datas.TotalPages != int64(parsedQuery.Page) && datas.TotalHits > int64(configs.BotConfig.InlineResultsPerPage - 1) {
resultList = append(resultList, &models.InlineQueryResultArticle{
ID: "paginationPage",
Title: fmt.Sprintf("当前您在第 %d 页", parsedQuery.Page),
Description: fmt.Sprintf("后面还有 %d 页内容,输入 %s%d 查看下一页", datas.TotalPages - int64(parsedQuery.Page), configs.BotConfig.InlinePaginationSymbol, parsedQuery.Page + 1),
InputMessageContent: &models.InputTextMessageContent{ MessageText: "用户在挑选内容时点击了分页提示..." },
})
}
}
}
}
_, err := opts.Thebot.AnswerInlineQuery(opts.Ctx, &bot.AnswerInlineQueryParams{
InlineQueryID: opts.InlineQuery.ID,
Results: resultList,
Button: &models.InlineQueryResultsButton{
Text: "当前为公共收藏内容",
StartParameter: "savedmessage_viewchannel",
},
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 showChannelLink(opts *handler_params.Message) error {
var handlerErr flaterr.MultErr
_, err := opts.Thebot.SendMessage(opts.Ctx, &bot.SendMessageParams{
ChatID: opts.Message.Chat.ID,
Text: fmt.Sprintf("当前频道链接: https://t.me/%s", common.SavedMessageList.ChannelUsername),
ReplyParameters: &models.ReplyParameters{ MessageID: opts.Message.ID },
ReplyMarkup: &models.InlineKeyboardMarkup{ InlineKeyboard: [][]models.InlineKeyboardButton{{{
Text: "查看频道",
URL: "https://t.me/" + common.SavedMessageList.ChannelUsername,
}}}},
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 channel link").
Msg(flaterr.SendMessage.Str())
handlerErr.Addt(flaterr.SendMessage, "saved message channel link", err)
}
return handlerErr.Flat()
}
func InitChannelPart(ctx context.Context) error {
chatIDString := common.SavedMessageList.ChannelIDStr()
_, err := common.MeilisearchClient.GetIndex(chatIDString)
if err != nil {
if err.(*meilisearch.Error).MeilisearchApiError.Code == "index_not_found" {
err := meilisearch_utils.CreateChatIndex(ctx, &common.MeilisearchClient, chatIDString)
if err != nil {
return fmt.Errorf("failed to create channel index: %w", err)
}
} else {
return fmt.Errorf("failed to get channel index: %w", err)
}
}
channelPubliclink = "https://t.me/" + common.SavedMessageList.ChannelUsername
channelPrivateLink = "https://t.me/c/" + utils.RemoveIDPrefix(common.SavedMessageList.ChannelID)
plugin_utils.AddHandlerByMessageChatIDHandlers(plugin_utils.ByMessageChatIDHandler{
ForChatID: common.SavedMessageList.ChannelID,
PluginName: "savedmessage_channel",
MessageHandler: channelSaveMessageHandler,
})
plugin_utils.AddInlineManualHandlers(plugin_utils.InlineManualHandler{
Command: "saved",
InlineHandler: channelInlineHandler,
Description: "公共频道中保存的消息",
})
plugin_utils.AddSlashStartCommandHandlers(plugin_utils.SlashStartHandler{
Argument: "savedmessage_viewchannel",
MessageHandler: showChannelLink,
})
plugin_utils.AddCallbackQueryHandlers(plugin_utils.CallbackQuery{
CallbackDataPrefix: "savedmsg_channel",
CallbackQueryHandler: channelCallbackHandler,
})
plugin_utils.AddFullCommandHandlers([]plugin_utils.FullCommand{
{
FullCommand: channelPubliclink,
ForChatType: []models.ChatType{models.ChatTypePrivate},
MessageHandler: channelMetadataHandler,
},
{
FullCommand: channelPrivateLink,
ForChatType: []models.ChatType{models.ChatTypePrivate},
MessageHandler: channelMetadataHandler,
},
}...)
plugin_utils.AddHandlerHelpInfo(plugin_utils.HandlerHelp{
Name: "收藏消息-公共频道",
Description: "此功能会实时记录一个频道中的消息并保存它,在之后可以使用 inline 模式查看并发送保存的内容\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",
},
},
}},
})
return nil
}