Files
Hubert Chen 65b929eee9 record oversize sticker set info
add auto save sticker config task
2025-11-21 23:58:41 +08:00

397 lines
14 KiB
Go

package collect
import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
"time"
"trbot/plugins/sticker_download/config"
"trbot/plugins/sticker_download/download"
"trbot/utils"
"trbot/utils/configs"
"trbot/utils/flaterr"
"trbot/utils/handler_params"
"trbot/utils/type/contain"
"trbot/utils/yaml"
"github.com/go-telegram/bot"
"github.com/go-telegram/bot/models"
"github.com/rs/zerolog"
)
var stickerCollect collectedSticker
var stickerCollectPath string = filepath.Join(configs.YAMLDatabaseDir, "collectsticker/", configs.YAMLFileName)
type stickerSetInfo struct {
Title string `yaml:"Title"` // 贴纸包的名称
Name string `yaml:"Name"` // 贴纸包的 urlname
MsgID int `yaml:"MsgID"` // 发送到频道的消息 ID
Count int `yaml:"Count"` // 贴纸包中的贴纸数量
}
type collectedSticker struct {
ChannelID int64 `yaml:"ChannelID"`
StickerSet []stickerSetInfo `yaml:"StickerSet"` // 已收藏的贴纸包列表
}
func (cs collectedSticker) GetStickerSetByName(name string) *stickerSetInfo {
for i, set := range cs.StickerSet {
if set.Name == name {
return &cs.StickerSet[i]
}
}
return nil
}
func ReadCollectStickerList(ctx context.Context) error {
logger := zerolog.Ctx(ctx).
With().
Str("pluginName", "sticker").
Str(utils.GetCurrentFuncName()).
Logger()
err := yaml.LoadYAML(stickerCollectPath, &stickerCollect)
if err != nil {
if os.IsNotExist(err) {
logger.Warn().
Err(err).
Str("path", stickerCollectPath).
Msg("Not found collect sticker list file. Created new one")
// 如果是找不到文件,新建一个
err = yaml.SaveYAML(stickerCollectPath, &stickerCollect)
if err != nil {
logger.Error().
Err(err).
Str("path", stickerCollectPath).
Msg("Failed to create empty collect sticker list file")
return fmt.Errorf("failed to create empty collect sticker list file: %w", err)
}
} else {
logger.Error().
Err(err).
Str("path", stickerCollectPath).
Msg("Failed to load collect sticker list file")
return fmt.Errorf("failed to load collect sticker list file: %w", err)
}
}
if stickerCollect.ChannelID == 0 {
return errors.New("channelID is empty")
}
return nil
}
func SaveCollectStickerList(ctx context.Context) error {
logger := zerolog.Ctx(ctx).
With().
Str("pluginName", "sticker").
Str(utils.GetCurrentFuncName()).
Logger()
err := yaml.SaveYAML(stickerCollectPath, &stickerCollect)
if err != nil {
logger.Error().
Err(err).
Str("path", stickerCollectPath).
Msg("Failed to save collect sticker list")
return fmt.Errorf("failed to save collect sticker list: %w", err)
}
return nil
}
func CollectStickerSet(opts *handler_params.CallbackQuery) error {
logger := zerolog.Ctx(opts.Ctx).
With().
Str("pluginName", "StickerDownload").
Str(utils.GetCurrentFuncName()).
Dict(utils.GetUserDict(&opts.CallbackQuery.From)).
Str("callbackQueryData", opts.CallbackQuery.Data).
Logger()
var handlerErr flaterr.MultErr
if stickerCollect.ChannelID == 0 {
_, err := opts.Thebot.AnswerCallbackQuery(opts.Ctx, &bot.AnswerCallbackQueryParams{
CallbackQueryID: opts.CallbackQuery.ID,
Text: "未设置贴纸包收集频道",
ShowAlert: true,
})
if err != nil {
logger.Error().
Err(err).
Str("content", "collect channel ID not set").
Msg(flaterr.AnswerCallbackQuery.Str())
handlerErr.Addt(flaterr.AnswerCallbackQuery, "collect channel ID not set", err)
}
} else if !contain.Int64(opts.CallbackQuery.From.ID, configs.BotConfig.AdminIDs...) {
_, err := opts.Thebot.AnswerCallbackQuery(opts.Ctx, &bot.AnswerCallbackQueryParams{
CallbackQueryID: opts.CallbackQuery.ID,
Text: "只有管理员才能使用此功能",
ShowAlert: true,
})
if err != nil {
logger.Error().
Err(err).
Str("content", "only admin can use this function").
Msg(flaterr.AnswerCallbackQuery.Str())
handlerErr.Addt(flaterr.AnswerCallbackQuery, "only admin can use this function", err)
}
} else {
stickerSetName := strings.TrimPrefix(opts.CallbackQuery.Data, "c_")
// 有下划线开头即代表这是一个超出了长度的贴纸包,下划线后面的数据是一个 ID
// 解析这个 ID 并从 config.Config.OversizeSets 中拿到对应的贴纸包名称
if stickerSetName[0:1] == "_" {
setID, err := strconv.Atoi(strings.TrimPrefix(stickerSetName, "_"))
if err != nil {
logger.Error().
Err(err).
Msg("Failed to parser oversize sticker set ID")
handlerErr.Addf("failed to parser oversize sticker set ID [%s]: %w", stickerSetName, err)
_, err = opts.Thebot.AnswerCallbackQuery(opts.Ctx, &bot.AnswerCallbackQueryParams{
CallbackQueryID: opts.CallbackQuery.ID,
Text: "解析贴纸包 ID 失败,请重新尝试发送此贴纸再点击按钮",
ShowAlert: true,
})
if err != nil {
logger.Error().
Err(err).
Str("content", "failed to parser oversize sticker set ID notice").
Msg(flaterr.AnswerCallbackQuery.Str())
handlerErr.Addt(flaterr.AnswerCallbackQuery, "failed to parser oversize sticker set ID notice", err)
}
return handlerErr.Flat()
}
stickerSetName = config.Config.GetOversizeSetNameByID(setID)
if stickerSetName == "" {
logger.Error().
Int("setID", setID).
Msg("Failed to find oversize sticker set")
handlerErr.Addf("Failed to find oversize sticker set [%d]", setID)
_, err = opts.Thebot.AnswerCallbackQuery(opts.Ctx, &bot.AnswerCallbackQueryParams{
CallbackQueryID: opts.CallbackQuery.ID,
Text: "未找到 ID 对应的贴纸包,请重新尝试发送此贴纸再点击按钮",
ShowAlert: true,
})
if err != nil {
logger.Error().
Err(err).
Str("content", "no sticker set found for set ID notice").
Msg(flaterr.AnswerCallbackQuery.Str())
handlerErr.Addt(flaterr.AnswerCallbackQuery, "no sticker set found for set ID notice", err)
}
return handlerErr.Flat()
}
}
stickerSet, err := opts.Thebot.GetStickerSet(opts.Ctx, &bot.GetStickerSetParams{ Name: stickerSetName })
if err != nil {
logger.Error().
Err(err).
Str("stickerSetName", stickerSetName).
Msg(flaterr.GetStickerSet.Str())
handlerErr.Addt(flaterr.GetStickerSet, stickerSetName, err)
_, err = opts.Thebot.SendMessage(opts.Ctx, &bot.SendMessageParams{
ChatID: opts.CallbackQuery.From.ID,
Text: fmt.Sprintf("获取贴纸包时发生了一些错误\n<blockquote expandable>Failed to get sticker set info: %s</blockquote>", utils.IgnoreHTMLTags(err.Error())),
ParseMode: models.ParseModeHTML,
})
if err != nil {
logger.Error().
Err(err).
Str("content", "get sticker set info error").
Msg(flaterr.SendMessage.Str())
handlerErr.Addt(flaterr.SendMessage, "get sticker set info error", err)
}
} else {
logger.Info().
Dict("stickerSet", zerolog.Dict().
Str("title", stickerSet.Title).
Str("name", stickerSet.Name).
Int("allCount", len(stickerSet.Stickers)),
).
Dict(utils.GetUserDict(&opts.CallbackQuery.From)).
Msg("Start download and collect sticker set")
if opts.CallbackQuery.Message.Message.Text != "" {
_, err = opts.Thebot.EditMessageText(opts.Ctx, &bot.EditMessageTextParams{
ChatID: opts.CallbackQuery.Message.Message.Chat.ID,
MessageID: opts.CallbackQuery.Message.Message.ID,
Text: fmt.Sprintf("正在收藏 <a href=\"https://t.me/addstickers/%s\">%s</a> 贴纸包,请稍候...", stickerSet.Name, stickerSet.Title),
ParseMode: models.ParseModeHTML,
})
if err != nil {
logger.Error().
Err(err).
Dict(utils.GetUserDict(&opts.CallbackQuery.From)).
Str("content", "start download stickerset notice").
Msg(flaterr.EditMessageText.Str())
handlerErr.Addt(flaterr.EditMessageText, "start download stickerset notice", err)
}
} else {
_, err = opts.Thebot.EditMessageCaption(opts.Ctx, &bot.EditMessageCaptionParams{
ChatID: opts.CallbackQuery.Message.Message.Chat.ID,
MessageID: opts.CallbackQuery.Message.Message.ID,
Caption: fmt.Sprintf("正在收藏 <a href=\"https://t.me/addstickers/%s\">%s</a> 贴纸包,请稍候...", stickerSet.Name, stickerSet.Title),
ParseMode: models.ParseModeHTML,
})
if err != nil {
logger.Error().
Err(err).
Dict(utils.GetUserDict(&opts.CallbackQuery.From)).
Str("content", "start download stickerset notice").
Msg(flaterr.EditMessageCaption.Str())
handlerErr.Addt(flaterr.EditMessageCaption, "start download stickerset notice", err)
}
}
stickerData, err := download.GetStickerPack(opts.Ctx, opts.Thebot, stickerSet, false)
if err != nil {
logger.Error().
Err(err).
Msg("Failed to download sticker set")
handlerErr.Addf("failed to download sticker set: %w", err)
_, err = opts.Thebot.SendMessage(opts.Ctx, &bot.SendMessageParams{
ChatID: opts.CallbackQuery.From.ID,
Text: fmt.Sprintf("下载贴纸包时发生了一些错误\n<blockquote expandable>Failed to download sticker set: %s</blockquote>", utils.IgnoreHTMLTags(err.Error())),
ParseMode: models.ParseModeHTML,
})
if err != nil {
logger.Error().
Err(err).
Str("content", "download sticker set error").
Msg(flaterr.SendMessage.Str())
handlerErr.Addt(flaterr.SendMessage, "download sticker set error", err)
}
} else {
var reply *models.ReplyParameters
collected := stickerCollect.GetStickerSetByName(stickerSetName)
if collected != nil {
// 已经收藏过了,更新贴纸包信息
reply = &models.ReplyParameters{
MessageID: collected.MsgID,
AllowSendingWithoutReply: true, // 如果旧消息被删除了也允许发送
}
}
var pendingMessage string
if stickerData.WebP > 0 { pendingMessage += fmt.Sprintf(" %d(静态)", stickerData.WebP) }
if stickerData.WebM > 0 { pendingMessage += fmt.Sprintf(" %d(动态)", stickerData.WebM) }
if stickerData.TGS > 0 { pendingMessage += fmt.Sprintf(" %d(矢量)", stickerData.TGS) }
channelMessage, err := opts.Thebot.SendDocument(opts.Ctx, &bot.SendDocumentParams{
ChatID: stickerCollect.ChannelID,
ParseMode: models.ParseModeMarkdownV1,
ReplyParameters: reply,
Caption: fmt.Sprintf("[%s](https://t.me/addstickers/%s)\n共 %d 个贴纸:%s\n存档时间 %s", stickerData.StickerSetTitle, stickerData.StickerSetName, stickerData.StickerCount, pendingMessage, time.Now().Format(time.RFC3339)),
Document: &models.InputFileUpload{ Filename: fmt.Sprintf("%s(%d).zip", stickerData.StickerSetName, stickerData.StickerCount), Data: stickerData.Data },
ReplyMarkup: &models.InlineKeyboardMarkup{ InlineKeyboard: [][]models.InlineKeyboardButton{{{
Text: "查看贴纸包", URL: "https://t.me/addstickers/" + stickerData.StickerSetName },
}}},
})
if err != nil {
logger.Error().
Err(err).
Int64("channelID", stickerCollect.ChannelID).
Str("stickerSetName", stickerSetName).
Str("content", "collect sticker set file").
Msg(flaterr.SendDocument.Str())
handlerErr.Addt(flaterr.SendDocument, "collect sticker set", err)
_, err = opts.Thebot.SendMessage(opts.Ctx, &bot.SendMessageParams{
ChatID: opts.CallbackQuery.From.ID,
Text: fmt.Sprintf("将贴纸包发送到收藏频道失败: <blockquote expandable>%s</blockquote>", utils.IgnoreHTMLTags(err.Error())),
ParseMode: models.ParseModeHTML,
})
if err != nil {
logger.Error().
Err(err).
Int64("channelID", stickerCollect.ChannelID).
Str("stickerSetName", stickerSetName).
Str("content", "collect sticker set failed notice").
Msg(flaterr.SendMessage.Str())
handlerErr.Addt(flaterr.SendMessage, "collect sticker set failed notice", err)
}
} else {
if collected == nil {
stickerCollect.StickerSet = append(stickerCollect.StickerSet, stickerSetInfo{
Title: stickerSet.Title,
Name: stickerSet.Name,
MsgID: channelMessage.ID,
Count: stickerData.StickerCount,
})
} else {
// 更新已收藏的贴纸包信息
collected.Title = stickerSet.Title
collected.MsgID = channelMessage.ID
}
err = SaveCollectStickerList(opts.Ctx)
if err != nil {
logger.Error().
Err(err).
Dict("collectSticker", zerolog.Dict().
Str("title", collected.Title).
Str("name", collected.Name),
).
Msg("Failed to save collect sticker list")
handlerErr.Addf("failed to save collect sticker list: %w", err)
}
_, err = opts.Thebot.EditMessageReplyMarkup(opts.Ctx, &bot.EditMessageReplyMarkupParams{
ChatID: opts.CallbackQuery.From.ID,
MessageID: opts.CallbackQuery.Message.Message.ID,
ReplyMarkup: &models.InlineKeyboardMarkup{InlineKeyboard: [][]models.InlineKeyboardButton{{{
Text: "✅ 已收藏至频道", URL: utils.MsgLinkPrivate(channelMessage.Chat.ID, channelMessage.ID),
}}}},
})
if err != nil {
logger.Err(err).
Int64("channelID", stickerCollect.ChannelID).
Str("stickerSetName", stickerSetName).
Str("content", "collect sticker set success notice").
Msg(flaterr.EditMessageReplyMarkup.Str())
handlerErr.Addt(flaterr.EditMessageReplyMarkup, "collect sticker set success notice", err)
}
}
}
}
}
return handlerErr.Flat()
}
func AddButton(setName string, newCount int, isManager bool, button *[][]models.InlineKeyboardButton) {
if stickerCollect.ChannelID != 0 {
set := stickerCollect.GetStickerSetByName(setName)
if set != nil {
if isManager {
*button = append(*button, []models.InlineKeyboardButton{
{
Text: fmt.Sprintf("🔁 更新 (%d>%d)", set.Count, newCount),
CallbackData: fmt.Sprintf("c_%s", setName),
},
{
Text: "✅ 已收藏至频道",
URL: utils.MsgLinkPrivate(stickerCollect.ChannelID, set.MsgID),
},
})
} else {
*button = append(*button, []models.InlineKeyboardButton{{
Text: "✅ 已收藏至频道",
URL: utils.MsgLinkPrivate(stickerCollect.ChannelID, set.MsgID),
}})
}
} else if isManager {
*button = append(*button, []models.InlineKeyboardButton{{
Text: "⭐️ 收藏至频道",
CallbackData: fmt.Sprintf("c_%s", setName),
}})
}
}
}