mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-10 23:36:37 +08:00
Clarify cleanup rule bot commands
This commit is contained in:
@@ -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) {
|
func TestBotCleanupRulesCanBeDeletedUntilEmpty(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
repos, bot := newBotTestService(t)
|
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"}`}
|
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"}}
|
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")
|
reply, err := bot.executeCommand(ctx, channel, msg, "/cleanup_rule del watch_3_5d_6h")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
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"}`}
|
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"}}
|
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 {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
for _, bad := range []string{"login_7d</code> · login_7d", "new_7d</code> · new_7d", "5 天内登录", "新号宽限 1 天"} {
|
for _, bad := range []string{"login_7d</code> · login_7d", "new_7d</code> · new_7d", "5 天内登录", "新号宽限 1 天", "add watch_hours", "Mgo 保号规则命令"} {
|
||||||
if strings.Contains(reply.Text, bad) {
|
if strings.Contains(reply.Text, bad) {
|
||||||
t.Fatalf("rule list still contains bad fragment %q: %s", bad, reply.Text)
|
t.Fatalf("rule list still contains bad fragment %q: %s", bad, reply.Text)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,13 +35,13 @@ const (
|
|||||||
SettingPlayWindowSeconds = "device.play_window_seconds" // 并发播放判定窗口(秒)
|
SettingPlayWindowSeconds = "device.play_window_seconds" // 并发播放判定窗口(秒)
|
||||||
SettingClientActiveDays = "device.client_active_days" // 登录设备活跃天数窗口
|
SettingClientActiveDays = "device.client_active_days" // 登录设备活跃天数窗口
|
||||||
|
|
||||||
// Sakura 风格保号规则。规则默认关闭;开启后按 KeepMode 计算用户
|
// Mgo 保号规则。规则默认关闭;开启后按 KeepMode 计算用户
|
||||||
// 是否满足足够的保号条件,未满足才会被清理。
|
// 是否满足足够的保号条件,未满足才会被清理。
|
||||||
SettingAccountCleanupEnabled = "device.account_cleanup_enabled"
|
SettingAccountCleanupEnabled = "device.account_cleanup_enabled"
|
||||||
SettingAccountCleanupKeepMode = "device.account_cleanup_keep_mode" // any / all / count
|
SettingAccountCleanupKeepMode = "device.account_cleanup_keep_mode" // any / all / count
|
||||||
SettingAccountCleanupRequiredCount = "device.account_cleanup_required_count" // keep_mode=count 时需要满足几条
|
SettingAccountCleanupRequiredCount = "device.account_cleanup_required_count" // keep_mode=count 时需要满足几条
|
||||||
SettingAccountCleanupRules = "device.account_cleanup_rules" // JSON []accountCleanupRule
|
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 是设备管控的已解析配置(含默认值)。
|
// botConfig 是设备管控的已解析配置(含默认值)。
|
||||||
@@ -92,17 +92,7 @@ func defaultBotConfig() botConfig {
|
|||||||
AccountCleanupEnabled: false,
|
AccountCleanupEnabled: false,
|
||||||
AccountCleanupKeepMode: "any",
|
AccountCleanupKeepMode: "any",
|
||||||
AccountCleanupRequiredCount: 1,
|
AccountCleanupRequiredCount: 1,
|
||||||
AccountCleanupRules: []accountCleanupRule{
|
AccountCleanupRules: nil,
|
||||||
{
|
|
||||||
ID: "watch_3_5d_6h",
|
|
||||||
Name: "3~5 天观看满 6 小时",
|
|
||||||
Type: "watch_hours",
|
|
||||||
Enabled: true,
|
|
||||||
WindowDaysMin: 3,
|
|
||||||
WindowDaysMax: 5,
|
|
||||||
MinHours: 6,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,7 +128,7 @@ func loadBotConfig(ctx context.Context, repo *repository.Container) botConfig {
|
|||||||
return cfg
|
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.
|
// Admins and the default admin are protected separately by UserIsProtectedAccount.
|
||||||
func ProtectedUserIDSet(ctx context.Context, repo *repository.Container) map[string]struct{} {
|
func ProtectedUserIDSet(ctx context.Context, repo *repository.Container) map[string]struct{} {
|
||||||
out := make(map[string]struct{})
|
out := make(map[string]struct{})
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import (
|
|||||||
// ① 防共享: too many concurrent playbacks / logged-in clients disables the
|
// ① 防共享: too many concurrent playbacks / logged-in clients disables the
|
||||||
// account immediately; fingerprint mismatch is warning-based and disables
|
// account immediately; fingerprint mismatch is warning-based and disables
|
||||||
// the account after the configured warning threshold.
|
// 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.
|
// accounts that do not satisfy the configured any/all/count rule set.
|
||||||
//
|
//
|
||||||
// Safeguards: admin / protected accounts are never auto disabled or deleted;
|
// Safeguards: admin / protected accounts are never auto disabled or deleted;
|
||||||
|
|||||||
@@ -283,7 +283,7 @@ func (c *Container) Boot() {
|
|||||||
// 自动扫描云盘媒体库,使内容对所有用户立即可见
|
// 自动扫描云盘媒体库,使内容对所有用户立即可见
|
||||||
c.BootCloudLibraries(c.stopCtx)
|
c.BootCloudLibraries(c.stopCtx)
|
||||||
|
|
||||||
// Sakura 保号规则巡检:默认关闭,由管理员通过 Telegram Bot 命令开启。
|
// Mgo 保号规则巡检:默认关闭,由管理员通过 Telegram Bot 命令开启。
|
||||||
// 每天触发一次评估;规则里的窗口可随机,不固定。
|
// 每天触发一次评估;规则里的窗口可随机,不固定。
|
||||||
if c.Device != nil {
|
if c.Device != nil {
|
||||||
go c.runInactivitySweeper(c.stopCtx)
|
go c.runInactivitySweeper(c.stopCtx)
|
||||||
|
|||||||
@@ -171,8 +171,9 @@ func TestTelegramCommandMenusSeparateGroupAndAdminCommands(t *testing.T) {
|
|||||||
t.Fatalf("group menu should include %s", required)
|
t.Fatalf("group menu should include %s", required)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
adminNames := telegramCommandNames(telegramAdminBotCommandMenu())
|
adminCommands := telegramAdminBotCommandMenu()
|
||||||
for _, required := range []string{"users", "status", "cleanup_rule"} {
|
adminNames := telegramCommandNames(adminCommands)
|
||||||
|
for _, required := range []string{"users", "status", "cleanup_mode", "cleanup_rule"} {
|
||||||
if !adminNames[required] {
|
if !adminNames[required] {
|
||||||
t.Fatalf("admin menu should include %s", 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)
|
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 {
|
func telegramCommandNames(commands []telegramBotCommand) map[string]bool {
|
||||||
|
|||||||
@@ -525,7 +525,7 @@ func (s *TelegramBotService) cmdHelp(ctx context.Context, msg *TelegramMessage)
|
|||||||
"<b>/antishare on play=3 login=3 warn=2</b> — 防共享策略(管理员)\n" +
|
"<b>/antishare on play=3 login=3 warn=2</b> — 防共享策略(管理员)\n" +
|
||||||
"<b>/cleanup on|off|run</b> — 保号规则开关/巡检(管理员)\n" +
|
"<b>/cleanup on|off|run</b> — 保号规则开关/巡检(管理员)\n" +
|
||||||
"<b>/cleanup_mode any|all|count 2</b> — 保号模式(管理员)\n" +
|
"<b>/cleanup_mode any|all|count 2</b> — 保号模式(管理员)\n" +
|
||||||
"<b>/cleanup_rule list|add|edit|修改|del|enable|disable</b> — Sakura 保号规则(管理员)\n" +
|
"<b>/cleanup_rule list|add|edit|修改|del|enable|disable</b> — Mgo 保号规则(管理员)\n" +
|
||||||
"<b>/ban 用户名</b> / <b>/unban 用户名</b> — 禁用/解禁用户(管理员)\n" +
|
"<b>/ban 用户名</b> / <b>/unban 用户名</b> — 禁用/解禁用户(管理员)\n" +
|
||||||
"<b>/hideadult on|off</b> — 隐藏/显示当前绑定账号的成人目录\n" +
|
"<b>/hideadult on|off</b> — 隐藏/显示当前绑定账号的成人目录\n" +
|
||||||
"<b>/status</b> — 系统运行状态\n" +
|
"<b>/status</b> — 系统运行状态\n" +
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ func (s *TelegramBotService) telegramCommandDefinitions(ctx context.Context, cha
|
|||||||
return s.cmdSakuraProtectedUser(ctx, args, false), nil
|
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) {
|
{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: "downloads", Description: "下载列表(管理员)"},
|
||||||
telegramBotCommand{Command: "stats", Description: "媒体库统计(管理员)"},
|
telegramBotCommand{Command: "stats", Description: "媒体库统计(管理员)"},
|
||||||
telegramBotCommand{Command: "users", Description: "用户管理(管理员)"},
|
telegramBotCommand{Command: "users", Description: "用户管理(管理员)"},
|
||||||
telegramBotCommand{Command: "cleanup", Description: "保号规则开关/巡检(管理员)"},
|
telegramBotCommand{Command: "cleanup", Description: "开启关闭或执行保号巡检(管理员)"},
|
||||||
telegramBotCommand{Command: "cleanup_rule", Description: "Sakura保号规则管理(管理员)"},
|
telegramBotCommand{Command: "cleanup_mode", Description: "设置保号规则匹配模式(管理员)"},
|
||||||
|
telegramBotCommand{Command: "cleanup_rule", Description: "Mgo保号规则管理(管理员)"},
|
||||||
)
|
)
|
||||||
return commands
|
return commands
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1125,7 +1125,7 @@ func (s *TelegramBotService) protectReason(ctx context.Context, userID string) s
|
|||||||
func (s *TelegramBotService) replyDevicePolicy(ctx context.Context) telegramCommandReply {
|
func (s *TelegramBotService) replyDevicePolicy(ctx context.Context) telegramCommandReply {
|
||||||
cfg := loadBotConfig(ctx, s.repo)
|
cfg := loadBotConfig(ctx, s.repo)
|
||||||
text := fmt.Sprintf(
|
text := fmt.Sprintf(
|
||||||
"<b>设备策略</b>\n\n① 防共享:<b>%s</b>\n 并发播放上限 %d / 登录客户端上限 %d;超限会禁用账号,管理员可解禁。\n 设备指纹异常警告 %d 次后禁用账号。\n\n② Sakura 保号规则:<b>%s</b>\n 保号模式:%s;需要满足 %d 条;启用规则 %d 条。\n\n<b>命令:</b>\n<code>/antishare on play=3 login=3 warn=2</code>\n<code>/cleanup on|off|run</code>\n<code>/cleanup_mode any|all|count 2</code>\n<code>/cleanup_rule list|add|edit|修改|del|enable|disable</code>\n\n策略默认关闭;清理前会先通过 Bot 通知用户;管理员/受保护账号永不自动处理。",
|
"<b>设备策略</b>\n\n① 防共享:<b>%s</b>\n 并发播放上限 %d / 登录客户端上限 %d;超限会禁用账号,管理员可解禁。\n 设备指纹异常警告 %d 次后禁用账号。\n\n② Mgo 保号规则:<b>%s</b>\n 保号模式:%s;需要满足 %d 条;启用规则 %d 条。\n\n<b>命令:</b>\n<code>/antishare on play=3 login=3 warn=2</code>\n<code>/cleanup on|off|run</code>\n<code>/cleanup_mode any|all|count 2</code>\n<code>/cleanup_rule list|add|edit|修改|del|enable|disable</code>\n\n策略默认关闭;清理前会先通过 Bot 通知用户;管理员/受保护账号永不自动处理。",
|
||||||
onOff(cfg.AntiShareEnabled), cfg.MaxConcurrentPlay, cfg.MaxLoggedClients, cfg.WarnThreshold,
|
onOff(cfg.AntiShareEnabled), cfg.MaxConcurrentPlay, cfg.MaxLoggedClients, cfg.WarnThreshold,
|
||||||
onOff(cfg.AccountCleanupEnabled), cleanupModeLabel(cfg.AccountCleanupKeepMode), cfg.AccountCleanupRequiredCount, countEnabledCleanupRules(cfg.AccountCleanupRules))
|
onOff(cfg.AccountCleanupEnabled), cleanupModeLabel(cfg.AccountCleanupKeepMode), cfg.AccountCleanupRequiredCount, countEnabledCleanupRules(cfg.AccountCleanupRules))
|
||||||
return telegramCommandReply{
|
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 {
|
func (s *TelegramBotService) cmdCleanupRule(ctx context.Context, args []string) telegramCommandReply {
|
||||||
if len(args) == 0 {
|
|
||||||
return telegramCommandReply{Text: cleanupRuleHelp()}
|
|
||||||
}
|
|
||||||
rules := s.currentCleanupRules(ctx)
|
rules := s.currentCleanupRules(ctx)
|
||||||
|
if len(args) == 0 {
|
||||||
|
return telegramCommandReply{Text: formatCleanupRules(rules)}
|
||||||
|
}
|
||||||
action := strings.ToLower(strings.TrimSpace(args[0]))
|
action := strings.ToLower(strings.TrimSpace(args[0]))
|
||||||
switch action {
|
switch action {
|
||||||
case "list", "ls", "status":
|
case "list", "ls", "status":
|
||||||
return telegramCommandReply{Text: formatCleanupRules(rules)}
|
return telegramCommandReply{Text: formatCleanupRules(rules)}
|
||||||
|
case "help", "?", "帮助":
|
||||||
|
return telegramCommandReply{Text: cleanupRuleHelp()}
|
||||||
case "del", "delete", "rm":
|
case "del", "delete", "rm":
|
||||||
if len(args) < 2 {
|
if len(args) < 2 {
|
||||||
return telegramCommandReply{Text: "用法:<code>/cleanup_rule del 规则ID</code>"}
|
return telegramCommandReply{Text: "用法:<code>/cleanup_rule del 规则ID</code>"}
|
||||||
@@ -1511,7 +1513,7 @@ func cleanupRuleTypeLabel(t string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func cleanupRuleHelp() string {
|
func cleanupRuleHelp() string {
|
||||||
return "<b>Sakura 保号规则命令</b>\n\n" +
|
return "<b>Mgo 保号规则命令</b>\n\n" +
|
||||||
"<code>/cleanup_rule list</code> — 查看规则\n" +
|
"<code>/cleanup_rule list</code> — 查看规则\n" +
|
||||||
"<code>/cleanup_rule add watch_hours watch_3_5d_6h 观看3到5天满6小时 3 5 6</code>\n" +
|
"<code>/cleanup_rule add watch_hours watch_3_5d_6h 观看3到5天满6小时 3 5 6</code>\n" +
|
||||||
"<code>/cleanup_rule add recent_login login_7d 七天内登录 7</code>\n" +
|
"<code>/cleanup_rule add recent_login login_7d 七天内登录 7</code>\n" +
|
||||||
|
|||||||
Reference in New Issue
Block a user