feat(email_domains): Add domain validation and improve domain management

- Add validate_domain_format() function with comprehensive domain format validation
* Validates domain structure (must contain dot, valid characters, proper TLD length)
* Normalizes domain format (adds @ prefix, removes quotes/special chars)
* Returns validation status with detailed error messages
- Update add_email_domains() to use new validation function
* Track invalid domains separately in return tuple
* Return (added, skipped, invalid, total) instead of (added, skipped, total)
* Improve error handling and domain normalization
- Add get_file_domains_count() function to retrieve txt file domain count
- Update clear_email_domains() to return count of cleared domains
- Enhance telegram_bot.py command menu organization
* Add s2a command handler and callback for S2A service management panel
* Reorganize bot commands with category comments (基础信息, 任务控制, 配置管理, etc.)
* Add missing commands: clean_errors, clean_teams, iban_list, iban_add, iban_clear, domain_list, domain_add, domain_del, domain_clear, team_fingerprint, team_register, s2a
- Update domain_add command help text with format requirements
- Improve code documentation and consistency across both files
This commit is contained in:
2026-01-24 07:52:10 +08:00
parent 6b914bad41
commit effc1add37
2 changed files with 1122 additions and 61 deletions

View File

@@ -315,40 +315,103 @@ def get_email_domains():
all_domains = file_domains | config_domains all_domains = file_domains | config_domains
return sorted(all_domains) if all_domains else [] return sorted(all_domains) if all_domains else []
def validate_domain_format(domain: str) -> tuple:
"""验证域名格式是否正确
Args:
domain: 要验证的域名 (带或不带@前缀)
Returns:
tuple: (是否有效, 标准化的域名或错误信息)
"""
domain = domain.strip().lower()
# 移除开头的引号和尾部特殊字符
domain = domain.strip('"\'')
# 确保以 @ 开头
if not domain.startswith("@"):
domain = "@" + domain
# 移除尾部可能的引号或逗号
domain = domain.rstrip('",\'')
# 基本长度检查 (至少 @x.y)
if len(domain) < 4:
return False, "域名太短"
# 提取 @ 后面的部分进行验证
domain_part = domain[1:] # 去掉 @
# 检查是否包含至少一个点
if "." not in domain_part:
return False, "域名缺少点号"
# 检查点的位置 (不能在开头或结尾)
if domain_part.startswith(".") or domain_part.endswith("."):
return False, "点号位置不正确"
# 检查不能有连续的点
if ".." in domain_part:
return False, "不能有连续的点号"
# 检查每个部分是否有效
parts = domain_part.split(".")
for part in parts:
if not part:
return False, "域名部分为空"
# 检查是否只包含有效字符 (字母、数字、连字符)
if not all(c.isalnum() or c == "-" for c in part):
return False, f"域名包含无效字符"
# 不能以连字符开头或结尾
if part.startswith("-") or part.endswith("-"):
return False, "域名部分不能以连字符开头或结尾"
# 顶级域名至少2个字符
if len(parts[-1]) < 2:
return False, "顶级域名太短"
return True, domain
def add_email_domains(new_domains: list) -> tuple: def add_email_domains(new_domains: list) -> tuple:
"""添加域名到列表 """添加域名到列表
Args: Args:
new_domains: 新的域名列表 new_domains: 新的域名列表
Returns: Returns:
tuple: (添加数量, 跳过数量, 当前总数) tuple: (添加数量, 跳过数量, 无效数量, 当前总数)
""" """
# 获取当前所有域名(文件 + 配置) # 获取当前所有域名(文件 + 配置)
current = set(load_domains_from_file()) current = set(load_domains_from_file())
config_domains = set(EMAIL_DOMAINS) if EMAIL_DOMAINS else set() config_domains = set(EMAIL_DOMAINS) if EMAIL_DOMAINS else set()
all_existing = current | config_domains all_existing = current | config_domains
added = 0 added = 0
skipped = 0 skipped = 0
invalid = 0
for domain in new_domains: for domain in new_domains:
domain = domain.strip().lower() # 验证域名格式
# 确保以 @ 开头 is_valid, result = validate_domain_format(domain)
if not domain.startswith("@"):
domain = "@" + domain if not is_valid:
if not domain or len(domain) < 4: # 至少 @x.y invalid += 1
continue continue
domain = result # 使用标准化后的域名
if domain in all_existing: if domain in all_existing:
skipped += 1 skipped += 1
else: else:
current.add(domain) current.add(domain)
all_existing.add(domain) all_existing.add(domain)
added += 1 added += 1
# 只保存通过 Bot 添加的域名到文件 # 只保存通过 Bot 添加的域名到文件
save_domains_to_file(sorted(current)) save_domains_to_file(sorted(current))
return added, skipped, len(all_existing) return added, skipped, invalid, len(all_existing)
def remove_email_domain(domain: str) -> bool: def remove_email_domain(domain: str) -> bool:
"""删除指定域名 (只能删除通过 Bot 添加的域名) """删除指定域名 (只能删除通过 Bot 添加的域名)
@@ -371,11 +434,21 @@ def remove_email_domain(domain: str) -> bool:
return True return True
return False return False
def clear_email_domains(): def get_file_domains_count() -> int:
"""清空域名列表""" """获取txt文件中的域名数量 (不包含config配置的)"""
return len(load_domains_from_file())
def clear_email_domains() -> int:
"""清空域名列表 (只清空txt文件保留config配置)
Returns:
int: 被清空的域名数量
"""
count = len(load_domains_from_file())
if DOMAIN_FILE.exists(): if DOMAIN_FILE.exists():
DOMAIN_FILE.unlink() DOMAIN_FILE.unlink()
return True return count
# ================= 固定配置 ================= # ================= 固定配置 =================
TARGET_URL = "https://chatgpt.com" TARGET_URL = "https://chatgpt.com"

File diff suppressed because it is too large Load Diff