虎牙自动注册持久化成功流水与批次,支持失败续跑与随时导出

将注册批次/条目/成功记录落库,成功一个写入一条流水;服务中断可恢复并续跑失败项,换电脑也能导出 txt。同时修复 pending 被误判为运行中导致页面卡住的问题。
This commit is contained in:
yml2213
2026-07-12 20:05:04 +08:00
parent c3044dbf69
commit e18b2c6e0c
9 changed files with 1423 additions and 96 deletions
@@ -0,0 +1,134 @@
"""虎牙自动注册批次/条目/成功流水持久化
Revision ID: 20260712_0007
Revises: 20260705_0006
Create Date: 2026-07-12
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
revision: str = "20260712_0007"
down_revision: Union[str, None] = "20260705_0006"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def _has_table(bind, table_name: str) -> bool:
return sa.inspect(bind).has_table(table_name)
def _columns(bind, table_name: str) -> set[str]:
if not _has_table(bind, table_name):
return set()
return {column["name"] for column in sa.inspect(bind).get_columns(table_name)}
def upgrade() -> None:
bind = op.get_bind()
if "sms_url" not in _columns(bind, "huya_accounts"):
op.add_column("huya_accounts", sa.Column("sms_url", sa.Text(), nullable=True))
if not _has_table(bind, "huya_register_batches"):
op.create_table(
"huya_register_batches",
sa.Column("id", sa.Integer(), autoincrement=True, nullable=False),
sa.Column("batch_id", sa.String(length=64), nullable=False),
sa.Column("tag", sa.String(length=64), nullable=True),
sa.Column("created_by", sa.Integer(), nullable=False),
sa.Column("concurrency", sa.Integer(), nullable=True),
sa.Column("wait_seconds", sa.Integer(), nullable=True),
sa.Column("poll_interval", sa.Integer(), nullable=True),
sa.Column("password_prefix", sa.String(length=16), nullable=True),
sa.Column("fixed_password", sa.Text(), nullable=True),
sa.Column("use_proxy", sa.Boolean(), nullable=True),
sa.Column("status", sa.String(length=32), nullable=True),
sa.Column("message", sa.String(length=512), nullable=True),
sa.Column("total", sa.Integer(), nullable=True),
sa.Column("success_count", sa.Integer(), nullable=True),
sa.Column("failed_count", sa.Integer(), nullable=True),
sa.Column("stopped_count", sa.Integer(), nullable=True),
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("started_at", sa.DateTime(), nullable=True),
sa.Column("finished_at", sa.DateTime(), nullable=True),
sa.ForeignKeyConstraint(["created_by"], ["users.id"]),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("batch_id"),
)
op.create_index("ix_huya_register_batches_batch_id", "huya_register_batches", ["batch_id"])
op.create_index("ix_huya_register_batches_created_by", "huya_register_batches", ["created_by"])
op.create_index("ix_huya_register_batches_status", "huya_register_batches", ["status"])
if not _has_table(bind, "huya_register_items"):
op.create_table(
"huya_register_items",
sa.Column("id", sa.Integer(), autoincrement=True, nullable=False),
sa.Column("batch_db_id", sa.Integer(), nullable=False),
sa.Column("batch_id", sa.String(length=64), nullable=False),
sa.Column("line", sa.Integer(), nullable=False),
sa.Column("phone", sa.String(length=64), nullable=True),
sa.Column("provider", sa.String(length=32), nullable=True),
sa.Column("sms_url", sa.Text(), nullable=True),
sa.Column("status", sa.String(length=32), nullable=True),
sa.Column("message", sa.String(length=512), nullable=True),
sa.Column("code", sa.String(length=32), nullable=True),
sa.Column("change_code", sa.String(length=32), nullable=True),
sa.Column("attempts", sa.Integer(), nullable=True),
sa.Column("change_attempts", sa.Integer(), nullable=True),
sa.Column("account_id", sa.Integer(), nullable=True),
sa.Column("username", sa.String(length=128), nullable=True),
sa.Column("uid", sa.String(length=32), nullable=True),
sa.Column("password", sa.Text(), nullable=True),
sa.Column("password_changed", sa.Boolean(), nullable=True),
sa.Column("cookie", sa.Text(), nullable=True),
sa.Column("started_at", sa.DateTime(), nullable=True),
sa.Column("finished_at", sa.DateTime(), nullable=True),
sa.ForeignKeyConstraint(["account_id"], ["huya_accounts.id"]),
sa.ForeignKeyConstraint(["batch_db_id"], ["huya_register_batches.id"]),
sa.PrimaryKeyConstraint("id"),
)
op.create_index("ix_huya_register_items_batch_db_id", "huya_register_items", ["batch_db_id"])
op.create_index("ix_huya_register_items_batch_id", "huya_register_items", ["batch_id"])
op.create_index("ix_huya_register_items_phone", "huya_register_items", ["phone"])
op.create_index("ix_huya_register_items_status", "huya_register_items", ["status"])
if not _has_table(bind, "huya_register_success_logs"):
op.create_table(
"huya_register_success_logs",
sa.Column("id", sa.Integer(), autoincrement=True, nullable=False),
sa.Column("batch_id", sa.String(length=64), nullable=True),
sa.Column("item_id", sa.Integer(), nullable=True),
sa.Column("account_id", sa.Integer(), nullable=True),
sa.Column("phone", sa.String(length=64), nullable=True),
sa.Column("username", sa.String(length=128), nullable=True),
sa.Column("uid", sa.String(length=32), nullable=True),
sa.Column("password", sa.Text(), nullable=True),
sa.Column("sms_url", sa.Text(), nullable=True),
sa.Column("tag", sa.String(length=64), nullable=True),
sa.Column("provider", sa.String(length=32), nullable=True),
sa.Column("created_by", sa.Integer(), nullable=True),
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.ForeignKeyConstraint(["account_id"], ["huya_accounts.id"]),
sa.ForeignKeyConstraint(["created_by"], ["users.id"]),
sa.PrimaryKeyConstraint("id"),
)
op.create_index("ix_huya_register_success_logs_batch_id", "huya_register_success_logs", ["batch_id"])
op.create_index("ix_huya_register_success_logs_phone", "huya_register_success_logs", ["phone"])
op.create_index("ix_huya_register_success_logs_tag", "huya_register_success_logs", ["tag"])
op.create_index("ix_huya_register_success_logs_created_at", "huya_register_success_logs", ["created_at"])
def downgrade() -> None:
bind = op.get_bind()
if _has_table(bind, "huya_register_success_logs"):
op.drop_table("huya_register_success_logs")
if _has_table(bind, "huya_register_items"):
op.drop_table("huya_register_items")
if _has_table(bind, "huya_register_batches"):
op.drop_table("huya_register_batches")
if "sms_url" in _columns(bind, "huya_accounts"):
op.drop_column("huya_accounts", "sms_url")