From 833966afb2578c459bf8b5d571279f9f331634a7 Mon Sep 17 00:00:00 2001 From: ShukeBta <272197458+ShukeBta@users.noreply.github.com> Date: Tue, 16 Jun 2026 02:47:00 +0800 Subject: [PATCH] Clarify cleanup rule bot commands --- internal/service/bot_features_test.go | 17 +++++++++++++++-- internal/service/bot_settings.go | 18 ++++-------------- internal/service/device_service.go | 2 +- internal/service/service.go | 2 +- internal/service/telegram_api_test.go | 10 ++++++++-- internal/service/telegram_bot.go | 2 +- internal/service/telegram_commands.go | 7 ++++--- internal/service/telegram_menu.go | 12 +++++++----- 8 files changed, 41 insertions(+), 29 deletions(-) diff --git a/internal/service/bot_features_test.go b/internal/service/bot_features_test.go index bf6d9a1..7fd5614 100644 --- a/internal/service/bot_features_test.go +++ b/internal/service/bot_features_test.go @@ -377,6 +377,16 @@ func TestBotAdminCommandsManageDevicePolicy(t *testing.T) { } } +func TestBotCleanupRulesDefaultToEmpty(t *testing.T) { + ctx := context.Background() + repos, _ := newBotTestService(t) + + cfg := loadBotConfig(ctx, repos) + if len(cfg.AccountCleanupRules) != 0 { + t.Fatalf("default cleanup rules should be empty, got %+v", cfg.AccountCleanupRules) + } +} + func TestBotCleanupRulesCanBeDeletedUntilEmpty(t *testing.T) { ctx := context.Background() repos, bot := newBotTestService(t) @@ -387,6 +397,9 @@ func TestBotCleanupRulesCanBeDeletedUntilEmpty(t *testing.T) { channel := &model.NotifyChannel{Name: "Telegram", Type: "telegram", Enabled: true, Config: `{"admin_user_ids":"9001"}`} msg := &TelegramMessage{From: TelegramUser{ID: 9001, Username: "root"}, Chat: TelegramChat{ID: 9001, Type: "private"}} + if _, err := bot.executeCommand(ctx, channel, msg, "/cleanup_rule add watch_hours watch_3_5d_6h 观看3到5天满6小时 3 5 6"); err != nil { + t.Fatal(err) + } reply, err := bot.executeCommand(ctx, channel, msg, "/cleanup_rule del watch_3_5d_6h") if err != nil { t.Fatal(err) @@ -421,11 +434,11 @@ func TestBotCleanupRuleListInfersDaysAndHidesDuplicateNames(t *testing.T) { channel := &model.NotifyChannel{Name: "Telegram", Type: "telegram", Enabled: true, Config: `{"admin_user_ids":"9001"}`} msg := &TelegramMessage{From: TelegramUser{ID: 9001, Username: "root"}, Chat: TelegramChat{ID: 9001, Type: "private"}} - reply, err := bot.executeCommand(ctx, channel, msg, "/cleanup_rule list") + reply, err := bot.executeCommand(ctx, channel, msg, "/cleanup_rule") if err != nil { t.Fatal(err) } - for _, bad := range []string{"login_7d · login_7d", "new_7d · new_7d", "5 天内登录", "新号宽限 1 天"} { + for _, bad := range []string{"login_7d · login_7d", "new_7d · new_7d", "5 天内登录", "新号宽限 1 天", "add watch_hours", "Mgo 保号规则命令"} { if strings.Contains(reply.Text, bad) { t.Fatalf("rule list still contains bad fragment %q: %s", bad, reply.Text) } diff --git a/internal/service/bot_settings.go b/internal/service/bot_settings.go index 4046d33..ae00235 100644 --- a/internal/service/bot_settings.go +++ b/internal/service/bot_settings.go @@ -35,13 +35,13 @@ const ( SettingPlayWindowSeconds = "device.play_window_seconds" // 并发播放判定窗口(秒) SettingClientActiveDays = "device.client_active_days" // 登录设备活跃天数窗口 - // Sakura 风格保号规则。规则默认关闭;开启后按 KeepMode 计算用户 + // Mgo 保号规则。规则默认关闭;开启后按 KeepMode 计算用户 // 是否满足足够的保号条件,未满足才会被清理。 SettingAccountCleanupEnabled = "device.account_cleanup_enabled" SettingAccountCleanupKeepMode = "device.account_cleanup_keep_mode" // any / all / count SettingAccountCleanupRequiredCount = "device.account_cleanup_required_count" // keep_mode=count 时需要满足几条 SettingAccountCleanupRules = "device.account_cleanup_rules" // JSON []accountCleanupRule - SettingProtectedUserIDs = "device.protected_user_ids" // comma separated user IDs; Sakura /prouser + SettingProtectedUserIDs = "device.protected_user_ids" // comma separated user IDs; Mgo /prouser ) // botConfig 是设备管控的已解析配置(含默认值)。 @@ -92,17 +92,7 @@ func defaultBotConfig() botConfig { AccountCleanupEnabled: false, AccountCleanupKeepMode: "any", AccountCleanupRequiredCount: 1, - AccountCleanupRules: []accountCleanupRule{ - { - ID: "watch_3_5d_6h", - Name: "3~5 天观看满 6 小时", - Type: "watch_hours", - Enabled: true, - WindowDaysMin: 3, - WindowDaysMax: 5, - MinHours: 6, - }, - }, + AccountCleanupRules: nil, } } @@ -138,7 +128,7 @@ func loadBotConfig(ctx context.Context, repo *repository.Container) botConfig { return cfg } -// ProtectedUserIDSet returns the explicit Sakura-compatible protected user list. +// ProtectedUserIDSet returns the explicit Mgo-compatible protected user list. // Admins and the default admin are protected separately by UserIsProtectedAccount. func ProtectedUserIDSet(ctx context.Context, repo *repository.Container) map[string]struct{} { out := make(map[string]struct{}) diff --git a/internal/service/device_service.go b/internal/service/device_service.go index cc42203..b856b9a 100644 --- a/internal/service/device_service.go +++ b/internal/service/device_service.go @@ -20,7 +20,7 @@ import ( // ① 防共享: too many concurrent playbacks / logged-in clients disables the // account immediately; fingerprint mismatch is warning-based and disables // the account after the configured warning threshold. -// ② Sakura 保号规则: admins define one or more keep rules; a sweep deletes +// ② Mgo 保号规则: admins define one or more keep rules; a sweep deletes // accounts that do not satisfy the configured any/all/count rule set. // // Safeguards: admin / protected accounts are never auto disabled or deleted; diff --git a/internal/service/service.go b/internal/service/service.go index bd5b3e5..7a1a58a 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -283,7 +283,7 @@ func (c *Container) Boot() { // 自动扫描云盘媒体库,使内容对所有用户立即可见 c.BootCloudLibraries(c.stopCtx) - // Sakura 保号规则巡检:默认关闭,由管理员通过 Telegram Bot 命令开启。 + // Mgo 保号规则巡检:默认关闭,由管理员通过 Telegram Bot 命令开启。 // 每天触发一次评估;规则里的窗口可随机,不固定。 if c.Device != nil { go c.runInactivitySweeper(c.stopCtx) diff --git a/internal/service/telegram_api_test.go b/internal/service/telegram_api_test.go index a365840..fc0e4ff 100644 --- a/internal/service/telegram_api_test.go +++ b/internal/service/telegram_api_test.go @@ -171,8 +171,9 @@ func TestTelegramCommandMenusSeparateGroupAndAdminCommands(t *testing.T) { t.Fatalf("group menu should include %s", required) } } - adminNames := telegramCommandNames(telegramAdminBotCommandMenu()) - for _, required := range []string{"users", "status", "cleanup_rule"} { + adminCommands := telegramAdminBotCommandMenu() + adminNames := telegramCommandNames(adminCommands) + for _, required := range []string{"users", "status", "cleanup_mode", "cleanup_rule"} { if !adminNames[required] { t.Fatalf("admin menu should include %s", required) } @@ -182,6 +183,11 @@ func TestTelegramCommandMenusSeparateGroupAndAdminCommands(t *testing.T) { t.Fatalf("admin menu should hide compatibility alias %s", hiddenAlias) } } + for _, command := range adminCommands { + if strings.Contains(command.Description, "Sakura") { + t.Fatalf("admin menu command %s should not mention Sakura: %q", command.Command, command.Description) + } + } } func telegramCommandNames(commands []telegramBotCommand) map[string]bool { diff --git a/internal/service/telegram_bot.go b/internal/service/telegram_bot.go index 4c43787..1d7993f 100644 --- a/internal/service/telegram_bot.go +++ b/internal/service/telegram_bot.go @@ -525,7 +525,7 @@ func (s *TelegramBotService) cmdHelp(ctx context.Context, msg *TelegramMessage) "/antishare on play=3 login=3 warn=2 — 防共享策略(管理员)\n" + "/cleanup on|off|run — 保号规则开关/巡检(管理员)\n" + "/cleanup_mode any|all|count 2 — 保号模式(管理员)\n" + - "/cleanup_rule list|add|edit|修改|del|enable|disable — Sakura 保号规则(管理员)\n" + + "/cleanup_rule list|add|edit|修改|del|enable|disable — Mgo 保号规则(管理员)\n" + "/ban 用户名 / /unban 用户名 — 禁用/解禁用户(管理员)\n" + "/hideadult on|off — 隐藏/显示当前绑定账号的成人目录\n" + "/status — 系统运行状态\n" + diff --git a/internal/service/telegram_commands.go b/internal/service/telegram_commands.go index 7481d18..fb328d4 100644 --- a/internal/service/telegram_commands.go +++ b/internal/service/telegram_commands.go @@ -135,7 +135,7 @@ func (s *TelegramBotService) telegramCommandDefinitions(ctx context.Context, cha return s.cmdSakuraProtectedUser(ctx, args, false), nil }}, {Aliases: []string{"/restart", "/update_bot", "/paolu", "/bindall_id", "/sync_favorites", "/coins", "/score", "/coinsall", "/coinsclear", "/red", "/srank", "/white_channel", "/rev_white_channel", "/unban_channel", "/config"}, AdminOnly: true, AdminOnlyText: adminOnly, Handle: func(args []string) (telegramCommandReply, error) { - return s.cmdSakuraUnsupported("Sakura 专属命令", "这些命令涉及外部 Bot 自身运维/积分红包/皮套人管理,已在 MediaStationGo 中由权限、通知渠道、设备策略替代。"), nil + return s.cmdSakuraUnsupported("Mgo 兼容命令", "这些命令涉及外部 Bot 自身运维/积分红包/皮套人管理,已在 MediaStationGo 中由权限、通知渠道、设备策略替代。"), nil }}, } } @@ -254,8 +254,9 @@ func telegramAdminBotCommandMenu() []telegramBotCommand { telegramBotCommand{Command: "downloads", Description: "下载列表(管理员)"}, telegramBotCommand{Command: "stats", Description: "媒体库统计(管理员)"}, telegramBotCommand{Command: "users", Description: "用户管理(管理员)"}, - telegramBotCommand{Command: "cleanup", Description: "保号规则开关/巡检(管理员)"}, - telegramBotCommand{Command: "cleanup_rule", Description: "Sakura保号规则管理(管理员)"}, + telegramBotCommand{Command: "cleanup", Description: "开启关闭或执行保号巡检(管理员)"}, + telegramBotCommand{Command: "cleanup_mode", Description: "设置保号规则匹配模式(管理员)"}, + telegramBotCommand{Command: "cleanup_rule", Description: "Mgo保号规则管理(管理员)"}, ) return commands } diff --git a/internal/service/telegram_menu.go b/internal/service/telegram_menu.go index 18f5907..87682bc 100644 --- a/internal/service/telegram_menu.go +++ b/internal/service/telegram_menu.go @@ -1125,7 +1125,7 @@ func (s *TelegramBotService) protectReason(ctx context.Context, userID string) s func (s *TelegramBotService) replyDevicePolicy(ctx context.Context) telegramCommandReply { cfg := loadBotConfig(ctx, s.repo) text := fmt.Sprintf( - "设备策略\n\n① 防共享:%s\n 并发播放上限 %d / 登录客户端上限 %d;超限会禁用账号,管理员可解禁。\n 设备指纹异常警告 %d 次后禁用账号。\n\n② Sakura 保号规则:%s\n 保号模式:%s;需要满足 %d 条;启用规则 %d 条。\n\n命令:\n/antishare on play=3 login=3 warn=2\n/cleanup on|off|run\n/cleanup_mode any|all|count 2\n/cleanup_rule list|add|edit|修改|del|enable|disable\n\n策略默认关闭;清理前会先通过 Bot 通知用户;管理员/受保护账号永不自动处理。", + "设备策略\n\n① 防共享:%s\n 并发播放上限 %d / 登录客户端上限 %d;超限会禁用账号,管理员可解禁。\n 设备指纹异常警告 %d 次后禁用账号。\n\n② Mgo 保号规则:%s\n 保号模式:%s;需要满足 %d 条;启用规则 %d 条。\n\n命令:\n/antishare on play=3 login=3 warn=2\n/cleanup on|off|run\n/cleanup_mode any|all|count 2\n/cleanup_rule list|add|edit|修改|del|enable|disable\n\n策略默认关闭;清理前会先通过 Bot 通知用户;管理员/受保护账号永不自动处理。", onOff(cfg.AntiShareEnabled), cfg.MaxConcurrentPlay, cfg.MaxLoggedClients, cfg.WarnThreshold, onOff(cfg.AccountCleanupEnabled), cleanupModeLabel(cfg.AccountCleanupKeepMode), cfg.AccountCleanupRequiredCount, countEnabledCleanupRules(cfg.AccountCleanupRules)) return telegramCommandReply{ @@ -1233,14 +1233,16 @@ func (s *TelegramBotService) cmdCleanupMode(ctx context.Context, args []string) } func (s *TelegramBotService) cmdCleanupRule(ctx context.Context, args []string) telegramCommandReply { - if len(args) == 0 { - return telegramCommandReply{Text: cleanupRuleHelp()} - } rules := s.currentCleanupRules(ctx) + if len(args) == 0 { + return telegramCommandReply{Text: formatCleanupRules(rules)} + } action := strings.ToLower(strings.TrimSpace(args[0])) switch action { case "list", "ls", "status": return telegramCommandReply{Text: formatCleanupRules(rules)} + case "help", "?", "帮助": + return telegramCommandReply{Text: cleanupRuleHelp()} case "del", "delete", "rm": if len(args) < 2 { return telegramCommandReply{Text: "用法:/cleanup_rule del 规则ID"} @@ -1511,7 +1513,7 @@ func cleanupRuleTypeLabel(t string) string { } func cleanupRuleHelp() string { - return "Sakura 保号规则命令\n\n" + + return "Mgo 保号规则命令\n\n" + "/cleanup_rule list — 查看规则\n" + "/cleanup_rule add watch_hours watch_3_5d_6h 观看3到5天满6小时 3 5 6\n" + "/cleanup_rule add recent_login login_7d 七天内登录 7\n" +