mirror of
https://github.com/krau/SaveAny-Bot.git
synced 2026-05-10 17:52:44 +08:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
40ad12a892 | ||
|
|
697e419643 | ||
|
|
eef051de3b | ||
|
|
6e29442c05 | ||
|
|
a3f1f75caf |
@@ -19,7 +19,7 @@ import (
|
|||||||
"golang.org/x/net/proxy"
|
"golang.org/x/net/proxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Init(ctx context.Context) (<-chan struct{}) {
|
func Init(ctx context.Context) <-chan struct{} {
|
||||||
log.FromContext(ctx).Info("初始化 Bot...")
|
log.FromContext(ctx).Info("初始化 Bot...")
|
||||||
resultChan := make(chan struct {
|
resultChan := make(chan struct {
|
||||||
client *gotgproto.Client
|
client *gotgproto.Client
|
||||||
@@ -75,18 +75,9 @@ func Init(ctx context.Context) (<-chan struct{}) {
|
|||||||
client.API().BotsSetBotCommands(ctx, &tg.BotsSetBotCommandsRequest{
|
client.API().BotsSetBotCommands(ctx, &tg.BotsSetBotCommandsRequest{
|
||||||
Scope: &tg.BotCommandScopeDefault{},
|
Scope: &tg.BotCommandScopeDefault{},
|
||||||
})
|
})
|
||||||
commands := []tg.BotCommand{
|
commands := make([]tg.BotCommand, 0, len(handlers.CommandHandlers))
|
||||||
{Command: "start", Description: "开始使用"},
|
for _, info := range handlers.CommandHandlers {
|
||||||
{Command: "help", Description: "显示帮助"},
|
commands = append(commands, tg.BotCommand{Command: info.Cmd, Description: info.Desc})
|
||||||
{Command: "silent", Description: "开启/关闭静默模式"},
|
|
||||||
{Command: "storage", Description: "设置默认存储端"},
|
|
||||||
{Command: "save", Description: "保存文件"},
|
|
||||||
{Command: "dir", Description: "管理存储文件夹"},
|
|
||||||
{Command: "rule", Description: "管理规则"},
|
|
||||||
}
|
|
||||||
if config.C().Telegram.Userbot.Enable {
|
|
||||||
commands = append(commands, tg.BotCommand{Command: "watch", Description: "监听聊天"})
|
|
||||||
commands = append(commands, tg.BotCommand{Command: "unwatch", Description: "取消监听聊天"})
|
|
||||||
}
|
}
|
||||||
_, err = client.API().BotsSetBotCommands(ctx, &tg.BotsSetBotCommandsRequest{
|
_, err = client.API().BotsSetBotCommands(ctx, &tg.BotsSetBotCommandsRequest{
|
||||||
Scope: &tg.BotCommandScopeDefault{},
|
Scope: &tg.BotCommandScopeDefault{},
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package handlers
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
"github.com/celestix/gotgproto/dispatcher"
|
"github.com/celestix/gotgproto/dispatcher"
|
||||||
"github.com/celestix/gotgproto/ext"
|
"github.com/celestix/gotgproto/ext"
|
||||||
@@ -101,3 +102,41 @@ func handleConfigFnameSTCallback(ctx *ext.Context, update *ext.Update) error {
|
|||||||
})
|
})
|
||||||
return dispatcher.EndGroups
|
return dispatcher.EndGroups
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleConfigFnameTmpl(ctx *ext.Context, update *ext.Update) error {
|
||||||
|
userID := update.GetUserChat().GetID()
|
||||||
|
user, err := database.GetUserByChatID(ctx, userID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
args := strings.Fields(string(update.EffectiveMessage.Text))
|
||||||
|
if len(args) <= 1 {
|
||||||
|
text := `使用该命令设置文件名模板, 示例:
|
||||||
|
/fnametmpl 图片_{{.msgid}}_{{.msgdate}}.jpg
|
||||||
|
|
||||||
|
可用变量:
|
||||||
|
- {{.msgid}}: 消息ID
|
||||||
|
- {{.msgtags}}: 消息中的标签, 将以下划线分隔输出
|
||||||
|
- {{.msggen}}: 根据消息生成的文件名
|
||||||
|
- {{.msgdate}}: 消息日期, 格式 YYYY-MM-DD_HH-MM-SS
|
||||||
|
- {{.origname}}: 媒体的原始文件名 (如果有)`
|
||||||
|
if user.FilenameTemplate != "" {
|
||||||
|
text += fmt.Sprintf("\n\n当前模板: %s", user.FilenameTemplate)
|
||||||
|
}
|
||||||
|
text += "\n\n模板仅在文件名策略设置为 '自定义模板' 时生效, 且模板解析错误时会回退到默认文件名"
|
||||||
|
ctx.Reply(update, ext.ReplyTextString(text), nil)
|
||||||
|
return dispatcher.EndGroups
|
||||||
|
}
|
||||||
|
newTmpl := strings.Join(args[1:], " ")
|
||||||
|
_, err = template.New("filename").Parse(newTmpl)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Reply(update, ext.ReplyTextString("无效的模板, 请检查语法\n"+err.Error()), nil)
|
||||||
|
return dispatcher.EndGroups
|
||||||
|
}
|
||||||
|
user.FilenameTemplate = newTmpl
|
||||||
|
if err := database.UpdateUser(ctx, user); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ctx.Reply(update, ext.ReplyTextString("已更新文件名模板"), nil)
|
||||||
|
return dispatcher.EndGroups
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import (
|
|||||||
"github.com/krau/SaveAny-Bot/client/bot/handlers/utils/shortcut"
|
"github.com/krau/SaveAny-Bot/client/bot/handlers/utils/shortcut"
|
||||||
"github.com/krau/SaveAny-Bot/common/utils/tgutil"
|
"github.com/krau/SaveAny-Bot/common/utils/tgutil"
|
||||||
"github.com/krau/SaveAny-Bot/database"
|
"github.com/krau/SaveAny-Bot/database"
|
||||||
"github.com/krau/SaveAny-Bot/pkg/enums/fnamest"
|
|
||||||
"github.com/krau/SaveAny-Bot/pkg/tcbdata"
|
"github.com/krau/SaveAny-Bot/pkg/tcbdata"
|
||||||
"github.com/krau/SaveAny-Bot/pkg/tfile"
|
"github.com/krau/SaveAny-Bot/pkg/tfile"
|
||||||
"github.com/krau/SaveAny-Bot/storage"
|
"github.com/krau/SaveAny-Bot/storage"
|
||||||
@@ -33,12 +32,13 @@ func handleMediaMessage(ctx *ext.Context, update *ext.Update) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tfOpts := make([]tfile.TGFileOption, 0)
|
// tfOpts := make([]tfile.TGFileOption, 0)
|
||||||
switch userDB.FilenameStrategy {
|
// switch userDB.FilenameStrategy {
|
||||||
case fnamest.Message.String():
|
// case fnamest.Message.String():
|
||||||
tfOpts = append(tfOpts, tfile.WithName(tgutil.GenFileNameFromMessage(*message)))
|
// tfOpts = append(tfOpts, tfile.WithName(tgutil.GenFileNameFromMessage(*message)))
|
||||||
default:
|
// default:
|
||||||
}
|
// }
|
||||||
|
tfOpts := mediautil.TfileOptions(ctx, userDB, message)
|
||||||
msg, file, err := shortcut.GetFileFromMessageWithReply(ctx, update, message, tfOpts...)
|
msg, file, err := shortcut.GetFileFromMessageWithReply(ctx, update, message, tfOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -74,12 +74,13 @@ func handleSilentSaveMedia(ctx *ext.Context, update *ext.Update) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tfOpts := make([]tfile.TGFileOption, 0)
|
// tfOpts := make([]tfile.TGFileOption, 0)
|
||||||
switch userDB.FilenameStrategy {
|
// switch userDB.FilenameStrategy {
|
||||||
case fnamest.Message.String():
|
// case fnamest.Message.String():
|
||||||
tfOpts = append(tfOpts, tfile.WithName(tgutil.GenFileNameFromMessage(*message)))
|
// tfOpts = append(tfOpts, tfile.WithName(tgutil.GenFileNameFromMessage(*message)))
|
||||||
default:
|
// default:
|
||||||
}
|
// }
|
||||||
|
tfOpts := mediautil.TfileOptions(ctx, userDB, message)
|
||||||
msg, file, err := shortcut.GetFileFromMessageWithReply(ctx, update, message, tfOpts...)
|
msg, file, err := shortcut.GetFileFromMessageWithReply(ctx, update, message, tfOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -24,6 +24,27 @@ import (
|
|||||||
"github.com/rs/xid"
|
"github.com/rs/xid"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type DescCommandHandler struct {
|
||||||
|
Cmd string
|
||||||
|
Desc string
|
||||||
|
handler func(ctx *ext.Context, u *ext.Update) error
|
||||||
|
}
|
||||||
|
|
||||||
|
var CommandHandlers = []DescCommandHandler{
|
||||||
|
{"start", "开始使用", handleHelpCmd},
|
||||||
|
{"silent", "切换静默模式", handleSilentCmd},
|
||||||
|
{"storage", "设置默认存储端", handleStorageCmd},
|
||||||
|
{"dir", "管理存储文件夹", handleDirCmd},
|
||||||
|
{"rule", "管理自动存储规则", handleRuleCmd},
|
||||||
|
{"watch", "监听聊天(UserBot)", handleWatchCmd},
|
||||||
|
{"unwatch", "取消监听聊天(UserBot)", handleUnwatchCmd},
|
||||||
|
{"save", "保存文件", handleSilentMode(handleSaveCmd, handleSilentSaveReplied)},
|
||||||
|
{"config", "修改配置", handleConfigCmd},
|
||||||
|
{"fnametmpl", "设置文件命名模板", handleConfigFnameTmpl},
|
||||||
|
{"update", "检查更新", handleUpdateCmd},
|
||||||
|
{"help", "显示帮助", handleHelpCmd},
|
||||||
|
}
|
||||||
|
|
||||||
func Register(disp dispatcher.Dispatcher) {
|
func Register(disp dispatcher.Dispatcher) {
|
||||||
disp.AddHandler(handlers.NewMessage(filters.Message.ChatType(filters.ChatTypeChannel), func(ctx *ext.Context, u *ext.Update) error {
|
disp.AddHandler(handlers.NewMessage(filters.Message.ChatType(filters.ChatTypeChannel), func(ctx *ext.Context, u *ext.Update) error {
|
||||||
return dispatcher.EndGroups
|
return dispatcher.EndGroups
|
||||||
@@ -32,17 +53,9 @@ func Register(disp dispatcher.Dispatcher) {
|
|||||||
return dispatcher.EndGroups
|
return dispatcher.EndGroups
|
||||||
}))
|
}))
|
||||||
disp.AddHandler(handlers.NewMessage(filters.Message.All, checkPermission))
|
disp.AddHandler(handlers.NewMessage(filters.Message.All, checkPermission))
|
||||||
disp.AddHandler(handlers.NewCommand("start", handleHelpCmd))
|
for _, info := range CommandHandlers {
|
||||||
disp.AddHandler(handlers.NewCommand("help", handleHelpCmd))
|
disp.AddHandler(handlers.NewCommand(info.Cmd, info.handler))
|
||||||
disp.AddHandler(handlers.NewCommand("silent", handleSilentCmd))
|
}
|
||||||
disp.AddHandler(handlers.NewCommand("storage", handleStorageCmd))
|
|
||||||
disp.AddHandler(handlers.NewCommand("dir", handleDirCmd))
|
|
||||||
disp.AddHandler(handlers.NewCommand("rule", handleRuleCmd))
|
|
||||||
disp.AddHandler(handlers.NewCommand("watch", handleWatchCmd))
|
|
||||||
disp.AddHandler(handlers.NewCommand("unwatch", handleUnwatchCmd))
|
|
||||||
disp.AddHandler(handlers.NewCommand("save", handleSilentMode(handleSaveCmd, handleSilentSaveReplied)))
|
|
||||||
disp.AddHandler(handlers.NewCommand("config", handleConfigCmd))
|
|
||||||
disp.AddHandler(handlers.NewCommand("update", handleUpdateCmd))
|
|
||||||
disp.AddHandler(handlers.NewCallbackQuery(filters.CallbackQuery.Prefix("update"), handleUpdateCallback))
|
disp.AddHandler(handlers.NewCallbackQuery(filters.CallbackQuery.Prefix("update"), handleUpdateCallback))
|
||||||
disp.AddHandler(handlers.NewCallbackQuery(filters.CallbackQuery.Prefix(tcbdata.TypeAdd), handleAddCallback))
|
disp.AddHandler(handlers.NewCallbackQuery(filters.CallbackQuery.Prefix(tcbdata.TypeAdd), handleAddCallback))
|
||||||
disp.AddHandler(handlers.NewCallbackQuery(filters.CallbackQuery.Prefix(tcbdata.TypeSetDefault), handleSetDefaultCallback))
|
disp.AddHandler(handlers.NewCallbackQuery(filters.CallbackQuery.Prefix(tcbdata.TypeSetDefault), handleSetDefaultCallback))
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/krau/SaveAny-Bot/common/i18n/i18nk"
|
"github.com/krau/SaveAny-Bot/common/i18n/i18nk"
|
||||||
"github.com/krau/SaveAny-Bot/common/utils/strutil"
|
"github.com/krau/SaveAny-Bot/common/utils/strutil"
|
||||||
"github.com/krau/SaveAny-Bot/common/utils/tgutil"
|
"github.com/krau/SaveAny-Bot/common/utils/tgutil"
|
||||||
|
"github.com/krau/SaveAny-Bot/database"
|
||||||
"github.com/krau/SaveAny-Bot/pkg/tcbdata"
|
"github.com/krau/SaveAny-Bot/pkg/tcbdata"
|
||||||
"github.com/krau/SaveAny-Bot/pkg/tfile"
|
"github.com/krau/SaveAny-Bot/pkg/tfile"
|
||||||
|
|
||||||
@@ -33,18 +34,27 @@ func handleSaveCmd(ctx *ext.Context, update *ext.Update) error {
|
|||||||
ctx.Reply(update, ext.ReplyTextString(i18n.T(i18nk.BotMsgSaveHelpText)), nil)
|
ctx.Reply(update, ext.ReplyTextString(i18n.T(i18nk.BotMsgSaveHelpText)), nil)
|
||||||
return dispatcher.EndGroups
|
return dispatcher.EndGroups
|
||||||
}
|
}
|
||||||
genFilename := func() string {
|
// genFilename := func() string {
|
||||||
if len(args) > 1 {
|
// if len(args) > 1 {
|
||||||
return args[1]
|
// return args[1]
|
||||||
}
|
// }
|
||||||
filename := tgutil.GenFileNameFromMessage(*replyTo.Message)
|
// filename := tgutil.GenFileNameFromMessage(*replyTo.Message)
|
||||||
return filename
|
// return filename
|
||||||
}()
|
// }()
|
||||||
option := tfile.WithNameIfEmpty(genFilename)
|
// option := tfile.WithNameIfEmpty(genFilename)
|
||||||
if len(args) > 1 {
|
// if len(args) > 1 {
|
||||||
option = tfile.WithName(genFilename)
|
// option = tfile.WithName(genFilename)
|
||||||
|
// }
|
||||||
|
userDB, err := database.GetUserByChatID(ctx, update.GetUserChat().GetID())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
msg, file, err := shortcut.GetFileFromMessageWithReply(ctx, update, replyTo.Message, option)
|
opts := mediautil.TfileOptions(ctx, userDB, replyTo.Message)
|
||||||
|
if len(args) > 1 {
|
||||||
|
// custom filename via command arg
|
||||||
|
opts = append(opts, tfile.WithName(strings.Join(args[1:], " ")))
|
||||||
|
}
|
||||||
|
msg, file, err := shortcut.GetFileFromMessageWithReply(ctx, update, replyTo.Message, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -77,18 +87,27 @@ func handleSilentSaveReplied(ctx *ext.Context, update *ext.Update) error {
|
|||||||
ctx.Reply(update, ext.ReplyTextString(i18n.T(i18nk.BotMsgSaveHelpText)), nil)
|
ctx.Reply(update, ext.ReplyTextString(i18n.T(i18nk.BotMsgSaveHelpText)), nil)
|
||||||
return dispatcher.EndGroups
|
return dispatcher.EndGroups
|
||||||
}
|
}
|
||||||
genFilename := func() string {
|
// genFilename := func() string {
|
||||||
if len(args) > 1 {
|
// if len(args) > 1 {
|
||||||
return args[1]
|
// return args[1]
|
||||||
}
|
// }
|
||||||
filename := tgutil.GenFileNameFromMessage(*replyTo.Message)
|
// filename := tgutil.GenFileNameFromMessage(*replyTo.Message)
|
||||||
return filename
|
// return filename
|
||||||
}()
|
// }()
|
||||||
option := tfile.WithNameIfEmpty(genFilename)
|
// option := tfile.WithNameIfEmpty(genFilename)
|
||||||
if len(args) > 1 {
|
// if len(args) > 1 {
|
||||||
option = tfile.WithName(genFilename)
|
// option = tfile.WithName(genFilename)
|
||||||
|
// }
|
||||||
|
userDB, err := database.GetUserByChatID(ctx, update.GetUserChat().GetID())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
msg, file, err := shortcut.GetFileFromMessageWithReply(ctx, update, replyTo.Message, option)
|
opts := mediautil.TfileOptions(ctx, userDB, replyTo.Message)
|
||||||
|
if len(args) > 1 {
|
||||||
|
// custom filename via command arg
|
||||||
|
opts = append(opts, tfile.WithName(strings.Join(args[1:], " ")))
|
||||||
|
}
|
||||||
|
msg, file, err := shortcut.GetFileFromMessageWithReply(ctx, update, replyTo.Message, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -126,7 +145,7 @@ func handleBatchSave(ctx *ext.Context, update *ext.Update, args []string) error
|
|||||||
return dispatcher.EndGroups
|
return dispatcher.EndGroups
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: generator istead of get all messages
|
// [TODO]: generator istead of get all messages
|
||||||
msgs, err := tgutil.GetMessagesRange(ctx, chatID, int(startID), int(endID))
|
msgs, err := tgutil.GetMessagesRange(ctx, chatID, int(startID), int(endID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Reply(update, ext.ReplyTextString("获取消息失败: "+err.Error()), nil)
|
ctx.Reply(update, ext.ReplyTextString("获取消息失败: "+err.Error()), nil)
|
||||||
|
|||||||
@@ -1,6 +1,20 @@
|
|||||||
package mediautil
|
package mediautil
|
||||||
|
|
||||||
import "github.com/gotd/td/tg"
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/charmbracelet/log"
|
||||||
|
"github.com/gotd/td/tg"
|
||||||
|
"github.com/krau/SaveAny-Bot/common/utils/strutil"
|
||||||
|
"github.com/krau/SaveAny-Bot/common/utils/tgutil"
|
||||||
|
"github.com/krau/SaveAny-Bot/database"
|
||||||
|
"github.com/krau/SaveAny-Bot/pkg/enums/fnamest"
|
||||||
|
"github.com/krau/SaveAny-Bot/pkg/tfile"
|
||||||
|
)
|
||||||
|
|
||||||
func IsSupported(media tg.MessageMediaClass) bool {
|
func IsSupported(media tg.MessageMediaClass) bool {
|
||||||
switch media.(type) {
|
switch media.(type) {
|
||||||
@@ -10,3 +24,83 @@ func IsSupported(media tg.MessageMediaClass) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FilenameTemplateData struct {
|
||||||
|
MsgID string `json:"msgid,omitempty"`
|
||||||
|
MsgTags string `json:"msgtags,omitempty"`
|
||||||
|
MsgGen string `json:"msggen,omitempty"`
|
||||||
|
MsgDate string `json:"msgdate,omitempty"`
|
||||||
|
OrigName string `json:"origname,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f FilenameTemplateData) ToMap() map[string]string {
|
||||||
|
return map[string]string{
|
||||||
|
"msgid": f.MsgID,
|
||||||
|
"msgtags": f.MsgTags,
|
||||||
|
"msggen": f.MsgGen,
|
||||||
|
"msgdate": f.MsgDate,
|
||||||
|
"origname": f.OrigName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TfileOptions(ctx context.Context, user *database.User, message *tg.Message) []tfile.TGFileOption {
|
||||||
|
opts := make([]tfile.TGFileOption, 0)
|
||||||
|
var fnameOpt tfile.TGFileOption
|
||||||
|
switch user.FilenameStrategy {
|
||||||
|
case fnamest.Message.String():
|
||||||
|
fnameOpt = tfile.WithName(tgutil.GenFileNameFromMessage(*message))
|
||||||
|
case fnamest.Template.String():
|
||||||
|
if user.FilenameTemplate == "" {
|
||||||
|
log.FromContext(ctx).Warnf("empty filename template")
|
||||||
|
fnameOpt = tfile.WithNameIfEmpty(tgutil.GenFileNameFromMessage(*message))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
tmpl, err := template.New("filename").Parse(user.FilenameTemplate)
|
||||||
|
if err != nil {
|
||||||
|
log.FromContext(ctx).Errorf("failed to parse filename template: %s", err)
|
||||||
|
fnameOpt = tfile.WithNameIfEmpty(tgutil.GenFileNameFromMessage(*message))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
data := FilenameTemplateData{
|
||||||
|
MsgID: func() string {
|
||||||
|
id := message.GetID()
|
||||||
|
if id == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%d", id)
|
||||||
|
}(),
|
||||||
|
MsgTags: func() string {
|
||||||
|
tags := strutil.ExtractTagsFromText(message.GetMessage())
|
||||||
|
if len(tags) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return strings.Join(tags, "_")
|
||||||
|
}(),
|
||||||
|
MsgGen: tgutil.GenFileNameFromMessage(*message),
|
||||||
|
OrigName: func() string {
|
||||||
|
f, _ := tgutil.GetMediaFileName(message.Media)
|
||||||
|
return f
|
||||||
|
}(),
|
||||||
|
MsgDate: func() string {
|
||||||
|
date := message.GetDate()
|
||||||
|
if date == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
t := time.Unix(int64(date), 0)
|
||||||
|
return t.Format("2006-01-02_15-04-05")
|
||||||
|
}(),
|
||||||
|
}.ToMap()
|
||||||
|
var sb strings.Builder
|
||||||
|
err = tmpl.Execute(&sb, data)
|
||||||
|
if err != nil {
|
||||||
|
log.FromContext(ctx).Errorf("failed to execute filename template: %s", err)
|
||||||
|
fnameOpt = tfile.WithNameIfEmpty(tgutil.GenFileNameFromMessage(*message))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
fnameOpt = tfile.WithName(sb.String())
|
||||||
|
default:
|
||||||
|
fnameOpt = tfile.WithNameIfEmpty(tgutil.GenFileNameFromMessage(*message))
|
||||||
|
}
|
||||||
|
opts = append(opts, fnameOpt, tfile.WithMessage(message))
|
||||||
|
return opts
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import (
|
|||||||
"github.com/krau/SaveAny-Bot/common/utils/tphutil"
|
"github.com/krau/SaveAny-Bot/common/utils/tphutil"
|
||||||
"github.com/krau/SaveAny-Bot/config"
|
"github.com/krau/SaveAny-Bot/config"
|
||||||
"github.com/krau/SaveAny-Bot/database"
|
"github.com/krau/SaveAny-Bot/database"
|
||||||
"github.com/krau/SaveAny-Bot/pkg/enums/fnamest"
|
|
||||||
"github.com/krau/SaveAny-Bot/pkg/telegraph"
|
"github.com/krau/SaveAny-Bot/pkg/telegraph"
|
||||||
"github.com/krau/SaveAny-Bot/pkg/tfile"
|
"github.com/krau/SaveAny-Bot/pkg/tfile"
|
||||||
)
|
)
|
||||||
@@ -42,15 +41,15 @@ func GetFileFromMessageWithReply(ctx *ext.Context, update *ext.Update, message *
|
|||||||
logger.Errorf("Failed to reply: %s", err)
|
logger.Errorf("Failed to reply: %s", err)
|
||||||
return nil, nil, dispatcher.EndGroups
|
return nil, nil, dispatcher.EndGroups
|
||||||
}
|
}
|
||||||
options := []tfile.TGFileOption{
|
// options := []tfile.TGFileOption{
|
||||||
tfile.WithMessage(message),
|
// tfile.WithMessage(message),
|
||||||
}
|
// }
|
||||||
if len(tfileopts) > 0 {
|
// if len(tfileopts) > 0 {
|
||||||
options = append(options, tfileopts...)
|
// options = append(options, tfileopts...)
|
||||||
} else {
|
// } else {
|
||||||
options = append(options, tfile.WithNameIfEmpty(tgutil.GenFileNameFromMessage(*message)))
|
// options = append(options, tfile.WithNameIfEmpty(tgutil.GenFileNameFromMessage(*message)))
|
||||||
}
|
// }
|
||||||
file, err = tfile.FromMediaMessage(media, ctx.Raw, message, options...)
|
file, err = tfile.FromMediaMessage(media, ctx.Raw, message, tfileopts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("Failed to get file from media: %s", err)
|
logger.Errorf("Failed to get file from media: %s", err)
|
||||||
ctx.Reply(update, ext.ReplyTextString("获取文件失败: "+err.Error()), nil)
|
ctx.Reply(update, ext.ReplyTextString("获取文件失败: "+err.Error()), nil)
|
||||||
@@ -100,14 +99,15 @@ func GetFilesFromUpdateLinkMessageWithReplyEdit(ctx *ext.Context, update *ext.Up
|
|||||||
logger.Debugf("message %d has no media", msg.GetID())
|
logger.Debugf("message %d has no media", msg.GetID())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var opt tfile.TGFileOption
|
// var opt tfile.TGFileOption
|
||||||
switch user.FilenameStrategy {
|
// switch user.FilenameStrategy {
|
||||||
case fnamest.Message.String():
|
// case fnamest.Message.String():
|
||||||
opt = tfile.WithName(tgutil.GenFileNameFromMessage(*msg))
|
// opt = tfile.WithName(tgutil.GenFileNameFromMessage(*msg))
|
||||||
default:
|
// default:
|
||||||
opt = tfile.WithNameIfEmpty(tgutil.GenFileNameFromMessage(*msg))
|
// opt = tfile.WithNameIfEmpty(tgutil.GenFileNameFromMessage(*msg))
|
||||||
}
|
// }
|
||||||
file, err := tfile.FromMediaMessage(media, client, msg, opt)
|
opts := mediautil.TfileOptions(ctx, user, msg)
|
||||||
|
file, err := tfile.FromMediaMessage(media, client, msg, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("failed to create file from media: %s", err)
|
logger.Errorf("failed to create file from media: %s", err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ func Run(cmd *cobra.Command, _ []string) {
|
|||||||
|
|
||||||
exitChan, err := initAll(ctx)
|
exitChan, err := initAll(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatal(i18n.T(i18nk.LifetimeInitfailed), "error", err)
|
logger.Fatal("Init failed", "error", err)
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
<-exitChan
|
<-exitChan
|
||||||
|
|||||||
@@ -43,11 +43,10 @@ func NewProxyHTTPClient(proxyUrl string) (*http.Client, error) {
|
|||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
case "socks5":
|
case "socks5":
|
||||||
dialer, err := proxy.SOCKS5("tcp", u.Host, nil, proxy.Direct)
|
dialer, err := proxy.FromURL(u, proxy.Direct)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &http.Client{
|
return &http.Client{
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ type User struct {
|
|||||||
Rules []Rule
|
Rules []Rule
|
||||||
WatchChats []WatchChat
|
WatchChats []WatchChat
|
||||||
FilenameStrategy string
|
FilenameStrategy string
|
||||||
|
FilenameTemplate string
|
||||||
}
|
}
|
||||||
|
|
||||||
type WatchChat struct {
|
type WatchChat struct {
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ Stream 模式对于磁盘空间有限的部署环境十分有用, 但也有一
|
|||||||
<br />
|
<br />
|
||||||
开启 userbot 集成后第一次启动 bot 时需要通过终端交互输入手机号, 2FA 和验证码.
|
开启 userbot 集成后第一次启动 bot 时需要通过终端交互输入手机号, 2FA 和验证码.
|
||||||
<br />
|
<br />
|
||||||
如果你使用 docker 部署, 请进入容器内执行相关操作.
|
如果你使用 docker 部署, 请使用 -it 参数为容器提供交互式环境, 然后执行登录操作.
|
||||||
{{< /hint >}}
|
{{< /hint >}}
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ package fnamest
|
|||||||
|
|
||||||
// FnameST
|
// FnameST
|
||||||
/* ENUM(
|
/* ENUM(
|
||||||
default, message
|
default, message, template
|
||||||
) */
|
) */
|
||||||
type FnameST string
|
type FnameST string
|
||||||
|
|
||||||
var FnameSTDisplay = map[FnameST]string{
|
var FnameSTDisplay = map[FnameST]string{
|
||||||
Default: "默认",
|
Default: "默认",
|
||||||
Message: "优先从消息生成",
|
Message: "优先从消息生成",
|
||||||
|
Template: "自定义模板",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ const (
|
|||||||
Default FnameST = "default"
|
Default FnameST = "default"
|
||||||
// Message is a FnameST of type message.
|
// Message is a FnameST of type message.
|
||||||
Message FnameST = "message"
|
Message FnameST = "message"
|
||||||
|
// Template is a FnameST of type template.
|
||||||
|
Template FnameST = "template"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrInvalidFnameST = fmt.Errorf("not a valid FnameST, try [%s]", strings.Join(_FnameSTNames, ", "))
|
var ErrInvalidFnameST = fmt.Errorf("not a valid FnameST, try [%s]", strings.Join(_FnameSTNames, ", "))
|
||||||
@@ -23,6 +25,7 @@ var ErrInvalidFnameST = fmt.Errorf("not a valid FnameST, try [%s]", strings.Join
|
|||||||
var _FnameSTNames = []string{
|
var _FnameSTNames = []string{
|
||||||
string(Default),
|
string(Default),
|
||||||
string(Message),
|
string(Message),
|
||||||
|
string(Template),
|
||||||
}
|
}
|
||||||
|
|
||||||
// FnameSTNames returns a list of possible string values of FnameST.
|
// FnameSTNames returns a list of possible string values of FnameST.
|
||||||
@@ -37,6 +40,7 @@ func FnameSTValues() []FnameST {
|
|||||||
return []FnameST{
|
return []FnameST{
|
||||||
Default,
|
Default,
|
||||||
Message,
|
Message,
|
||||||
|
Template,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,8 +57,9 @@ func (x FnameST) IsValid() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var _FnameSTValue = map[string]FnameST{
|
var _FnameSTValue = map[string]FnameST{
|
||||||
"default": Default,
|
"default": Default,
|
||||||
"message": Message,
|
"message": Message,
|
||||||
|
"template": Template,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseFnameST attempts to convert a string to a FnameST.
|
// ParseFnameST attempts to convert a string to a FnameST.
|
||||||
|
|||||||
Reference in New Issue
Block a user