feat(huya): 多选登录改单线程队列并拆分路由与工作台
默认同时只登一个号,失败两次跳下一个,号间留间隔,结束后可一键重试失败账号。 顺带拆分虎牙路由与斗鱼工作台页面,并补齐 raw_cookie 重建入口。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
"""斗鱼写路径契约:锁单/支付编排走 mock 客户端,不打真实兑换。"""
|
||||
|
||||
from unittest.mock import Mock
|
||||
|
||||
from sqlalchemy import create_engine, event
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from web.backend.database import Base
|
||||
from web.backend.models import Account, DouyuGoodsSnapshot, DouyuTask, User
|
||||
from web.backend.services.douyu_runner import DouyuBatchRunner
|
||||
|
||||
|
||||
class TestDouyuWritePathContracts:
|
||||
def setup_method(self):
|
||||
self.engine = create_engine("sqlite://")
|
||||
|
||||
@event.listens_for(self.engine, "connect")
|
||||
def enable_foreign_keys(connection, _):
|
||||
connection.execute("PRAGMA foreign_keys=ON")
|
||||
|
||||
Base.metadata.create_all(self.engine)
|
||||
self.session = sessionmaker(bind=self.engine)()
|
||||
self.user = User(username="operator", password_hash="hash", role="super_admin")
|
||||
self.account = Account(
|
||||
username="dyuser",
|
||||
password="pw",
|
||||
email="a@example.com",
|
||||
email_password="em",
|
||||
)
|
||||
self.session.add_all([self.user, self.account])
|
||||
self.session.commit()
|
||||
self.session.add(
|
||||
DouyuGoodsSnapshot(
|
||||
commodity_id="bag10",
|
||||
name="套装-兔兔白日梦",
|
||||
raw={"name": "套装-兔兔白日梦"},
|
||||
)
|
||||
)
|
||||
self.session.commit()
|
||||
|
||||
def teardown_method(self):
|
||||
self.session.close()
|
||||
Base.metadata.drop_all(self.engine)
|
||||
self.engine.dispose()
|
||||
|
||||
def _runner(self, task_type: str) -> DouyuBatchRunner:
|
||||
return DouyuBatchRunner(db=self.session, batch_id="batch1", task_type=task_type)
|
||||
|
||||
def _task(self, task_type: str, payload: dict) -> DouyuTask:
|
||||
task = DouyuTask(
|
||||
batch_id="batch1",
|
||||
account_id=self.account.id,
|
||||
task_type=task_type,
|
||||
handbook_scope="elite",
|
||||
status="running",
|
||||
result={"payload": payload},
|
||||
created_by=self.user.id,
|
||||
)
|
||||
self.session.add(task)
|
||||
self.session.commit()
|
||||
return task
|
||||
|
||||
def test_lock_goods_records_order_without_paying(self):
|
||||
task = self._task("lock_goods", {"commodity_id": "bag10", "num": 1})
|
||||
runner = self._runner("lock_goods")
|
||||
client = Mock()
|
||||
client.create_exchange_order.return_value = {
|
||||
"order_id": "5874",
|
||||
"expire_seconds": "300",
|
||||
}
|
||||
runner._client = Mock(return_value=client)
|
||||
|
||||
runner._execute_lock_goods(
|
||||
self.session,
|
||||
task,
|
||||
self.account,
|
||||
"acf_uid=100",
|
||||
{"manual_id": "G4KA4Qnz4LDp7", "rid": "9263298"},
|
||||
)
|
||||
|
||||
self.session.refresh(task)
|
||||
self.session.refresh(self.account)
|
||||
assert task.status == "success"
|
||||
assert task.result["order_id"] == "5874"
|
||||
assert self.account.bind_status == "goods_locked"
|
||||
client.create_exchange_order.assert_called_once()
|
||||
client.pay_exchange_order.assert_not_called()
|
||||
|
||||
def test_pay_locked_order_uses_existing_order_id(self):
|
||||
task = self._task(
|
||||
"pay_locked_order",
|
||||
{"order_id": "5874", "commodity_id": "bag10"},
|
||||
)
|
||||
runner = self._runner("pay_locked_order")
|
||||
client = Mock()
|
||||
client.pay_exchange_order.return_value = {
|
||||
"exchange_id": "11098933",
|
||||
"commodity_image": "https://example.test/item.png",
|
||||
"exchange_num": 1,
|
||||
}
|
||||
runner._client = Mock(return_value=client)
|
||||
runner._refresh_account_points = Mock(return_value={"points": 1280})
|
||||
|
||||
runner._execute_pay_locked_order(
|
||||
self.session,
|
||||
task,
|
||||
self.account,
|
||||
"acf_uid=100",
|
||||
{"manual_id": "G4KA4Qnz4LDp7", "rid": "9263298"},
|
||||
)
|
||||
|
||||
self.session.refresh(task)
|
||||
assert task.status == "success"
|
||||
assert task.result["exchange_id"] == "11098933"
|
||||
client.pay_exchange_order.assert_called_once()
|
||||
client.create_exchange_order.assert_not_called()
|
||||
Reference in New Issue
Block a user