- hexi core: message handling, rate limiting, cooldown, plugin manager - Custom plugins: BF stats, daily check-in, quotes, persona cards, etc. - Community plugins vendored under hexi/plugins with local fixes - Web admin frontends (learning-chat, persona-admin), unified hexi/web - Tests for rate_limit/cooldown/memes/persona; poetry.lock Co-Authored-By: Claude <noreply@anthropic.com>
38 lines
854 B
Python
38 lines
854 B
Python
import unicodedata
|
|
|
|
|
|
def parse_seconds(s: str) -> int | None:
|
|
"""解析 '30' 或 '3*60' 形式的时长秒数,非法输入返回 None"""
|
|
s = s.strip()
|
|
if not s or not all(c.isdigit() or c == "*" for c in s):
|
|
return None
|
|
try:
|
|
result = 1
|
|
for part in s.split("*"):
|
|
result *= int(part)
|
|
return result
|
|
except ValueError:
|
|
return None
|
|
|
|
|
|
def strip_prefix(text: str, prefixes) -> str:
|
|
"""依次移除前缀后去空白"""
|
|
for p in prefixes:
|
|
text = text.removeprefix(p)
|
|
return text.strip()
|
|
|
|
|
|
def is_number(s) -> bool:
|
|
"""判断字符串是否可视为数字"""
|
|
try:
|
|
float(s)
|
|
return True
|
|
except ValueError:
|
|
pass
|
|
try:
|
|
unicodedata.numeric(s)
|
|
return True
|
|
except (TypeError, ValueError):
|
|
pass
|
|
return False
|