chore: auto release commit (2026-04-06 10:37:07)
All checks were successful
技能自动化发布 / release (push) Successful in 34s
All checks were successful
技能自动化发布 / release (push) Successful in 34s
This commit is contained in:
136
scripts/am_db.py
Normal file
136
scripts/am_db.py
Normal file
@@ -0,0 +1,136 @@
|
||||
"""SQLite 账号库:建表、读写、登录态字段。"""
|
||||
import json
|
||||
import sqlite3
|
||||
import time
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from am_platforms import PLATFORM_URLS, _PLATFORM_NAME_CN
|
||||
from am_runtime_paths import get_db_path
|
||||
|
||||
|
||||
# SQLite 无独立 DATETIME 类型:时间统一存 INTEGER Unix 秒(UTC),查询/JSON 再转 ISO8601。
|
||||
# 下列 DDL 含注释,会原样写入 sqlite_master,便于 Navicat / DBeaver 等查看建表语句。
|
||||
ACCOUNTS_TABLE_SQL = """
|
||||
/* 多平台账号表:与本地 Chromium/Edge 用户数据目录(profile)绑定,供发布类技能读取登录态 */
|
||||
CREATE TABLE accounts (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT, -- 账号主键(自增)
|
||||
name TEXT NOT NULL, -- 展示名称,如「搜狐1号」
|
||||
platform TEXT NOT NULL, -- 平台标识,与内置 PLATFORMS 键一致,如 sohu
|
||||
phone TEXT, -- 可选绑定手机号
|
||||
profile_dir TEXT, -- Playwright 用户数据目录(绝对路径);默认可读结构 profiles/<平台展示名>/<手机号>/
|
||||
url TEXT, -- 平台入口或登录页 URL
|
||||
login_status INTEGER NOT NULL DEFAULT 0, -- 是否已登录:0 否 1 是(由脚本校验后写入)
|
||||
last_login_at INTEGER, -- 最近一次登录成功时间,Unix 秒 UTC;未登录过为 NULL
|
||||
extra_json TEXT, -- 扩展字段 JSON
|
||||
created_at INTEGER NOT NULL, -- 记录创建时间,Unix 秒 UTC
|
||||
updated_at INTEGER NOT NULL -- 记录最后更新时间,Unix 秒 UTC
|
||||
);
|
||||
"""
|
||||
|
||||
|
||||
def _now_unix() -> int:
|
||||
return int(time.time())
|
||||
|
||||
|
||||
def _unix_to_iso_local(ts: Optional[int]) -> Optional[str]:
|
||||
"""对外 JSON:本地时区 ISO8601 字符串,便于人读。"""
|
||||
if ts is None:
|
||||
return None
|
||||
try:
|
||||
return datetime.fromtimestamp(int(ts)).isoformat(timespec="seconds")
|
||||
except (ValueError, OSError, OverflowError):
|
||||
return None
|
||||
|
||||
|
||||
def get_conn():
|
||||
return sqlite3.connect(get_db_path())
|
||||
|
||||
|
||||
def init_db():
|
||||
conn = get_conn()
|
||||
try:
|
||||
cur = conn.cursor()
|
||||
cur.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='accounts'")
|
||||
if not cur.fetchone():
|
||||
cur.executescript(ACCOUNTS_TABLE_SQL)
|
||||
conn.commit()
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def _normalize_account_id(account_id):
|
||||
if account_id is None:
|
||||
return None
|
||||
s = str(account_id).strip()
|
||||
if s.isdigit():
|
||||
return int(s)
|
||||
return s
|
||||
|
||||
|
||||
def get_account_by_id(account_id):
|
||||
init_db()
|
||||
aid = _normalize_account_id(account_id)
|
||||
conn = get_conn()
|
||||
try:
|
||||
cur = conn.cursor()
|
||||
cur.execute(
|
||||
"""
|
||||
SELECT id, name, platform, phone, profile_dir, url, login_status, last_login_at, extra_json,
|
||||
created_at, updated_at
|
||||
FROM accounts WHERE id = ?
|
||||
""",
|
||||
(aid,),
|
||||
)
|
||||
row = cur.fetchone()
|
||||
if not row:
|
||||
return None
|
||||
acc = {
|
||||
"id": row[0],
|
||||
"name": row[1],
|
||||
"platform": row[2],
|
||||
"phone": row[3] or "",
|
||||
"profile_dir": (row[4] or "").strip(),
|
||||
"url": row[5] or PLATFORM_URLS.get(row[2], ""),
|
||||
"login_status": int(row[6] or 0),
|
||||
"last_login_at": _unix_to_iso_local(row[7]),
|
||||
"created_at": _unix_to_iso_local(row[9]),
|
||||
"updated_at": _unix_to_iso_local(row[10]),
|
||||
}
|
||||
if row[8]:
|
||||
try:
|
||||
extra = json.loads(row[8])
|
||||
if isinstance(extra, dict):
|
||||
acc.update(extra)
|
||||
except Exception:
|
||||
pass
|
||||
return acc
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def _default_name_for_platform(platform: str, index: int) -> str:
|
||||
cn = _PLATFORM_NAME_CN.get(platform)
|
||||
if cn:
|
||||
return f"{cn}{index}号"
|
||||
return f"{platform}_{index}"
|
||||
|
||||
|
||||
def _mark_login_status(account_id, success: bool):
|
||||
now = _now_unix()
|
||||
conn = get_conn()
|
||||
try:
|
||||
cur = conn.cursor()
|
||||
if success:
|
||||
cur.execute(
|
||||
"UPDATE accounts SET login_status = 1, last_login_at = ?, updated_at = ? WHERE id = ?",
|
||||
(now, now, account_id),
|
||||
)
|
||||
else:
|
||||
cur.execute(
|
||||
"UPDATE accounts SET login_status = 0, updated_at = ? WHERE id = ?",
|
||||
(now, account_id),
|
||||
)
|
||||
conn.commit()
|
||||
finally:
|
||||
conn.close()
|
||||
Reference in New Issue
Block a user