AutoRpa/rpa_cart/main.py

252 lines
8.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""加购班与 1 号药城支付落表。默认支付;`cart` 子命令加购。"""
from __future__ import annotations
import argparse
import tempfile
from datetime import date
from pathlib import Path
import requests
from db import RepoUnavailable
from job import run_yaoex_pay
from parse_xls import parse_order_xls
from repo import EmptyPayRepo, OraclePayRepo
from yaoex_client import day_range, export_orders
from yaoex_login import (
BrowserRuntime,
load_cart_dotenv,
resolve_yaoex_auth,
resolve_ybm_cookies,
)
PROJECT_ROOT = Path(__file__).resolve().parent
YAOEX_PLATFORM_TYPE = 66
YBM_PLATFORM_TYPE = 48
def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
argv = list(argv) if argv is not None else None
if argv is None:
import sys
argv = sys.argv[1:]
command = "pay"
if argv and argv[0] in {"pay", "cart"}:
command = argv.pop(0)
if command == "cart":
args = _parse_cart_args(argv)
args.command = "cart"
return args
args = _parse_pay_args(argv)
args.command = "pay"
return args
def _parse_pay_args(argv: list[str]) -> argparse.Namespace:
parser = argparse.ArgumentParser(description="1 号药城支付落表")
parser.add_argument("--xls", type=Path, default=None, help="已导出的订单明细 xls,跳过商城导出")
parser.add_argument(
"--days",
type=int,
default=0,
help="导出日期跨度,0=仅当天。与 --xls 互斥时仍用于无 xls 的导出",
)
parser.add_argument("--day", type=str, default=None, help="结束日期 YYYY-MM-DD,默认今天")
parser.add_argument("--dry-run", action="store_true", help="解析但不写库")
parser.add_argument("--fresh-login", action="store_true", help="忽略登录缓存")
parser.add_argument("--secrets", type=Path, default=None)
parser.add_argument("--yaoex-auth", type=Path, default=None)
return parser.parse_args(argv)
def _parse_cart_args(argv: list[str]) -> argparse.Namespace:
parser = argparse.ArgumentParser(description="加购班:领表 2 选品成功行,按仓加进购物车")
parser.add_argument("--limit", type=int, default=None, help="本班最多领取 N 行")
parser.add_argument(
"--platform",
choices=["all", "yaoex", "ybm"],
default="all",
help="all=两平台都跑",
)
parser.add_argument("--fresh-login", action="store_true", help="忽略登录缓存")
parser.add_argument("--secrets", type=Path, default=None)
parser.add_argument("--yaoex-auth", type=Path, default=None)
parser.add_argument("--ybm-cookies", type=Path, default=None)
return parser.parse_args(argv)
def main(argv: list[str] | None = None, repo=None) -> None:
args = parse_args(argv)
if args.command == "cart":
main_cart(args, repo=repo)
return
main_pay(args, repo=repo)
def main_pay(args: argparse.Namespace, repo=None) -> None:
load_cart_dotenv()
xls_path = args.xls
tmp_xls: Path | None = None
if xls_path is None:
try:
auth = resolve_yaoex_auth(
secrets_path=args.secrets,
auth_path=args.yaoex_auth,
fresh=args.fresh_login,
)
token = auth.token
print("1号药城认证就绪。")
except SystemExit:
raise
except Exception as exc:
print(f"1号药城登录失败:{exc}")
raise SystemExit(2) from exc
end = date.fromisoformat(args.day) if args.day else date.today()
begin, end_ts = day_range(end, args.days)
print(f"导出 {begin} ~ {end_ts}")
content = export_orders(token, begin=begin, end=end_ts)
tmp_dir = Path(tempfile.mkdtemp(prefix="yaoex_pay_"))
tmp_xls = tmp_dir / "orders.xls"
tmp_xls.write_bytes(content)
xls_path = tmp_xls
print(f"导出文件 {xls_path} ({len(content)} bytes)")
lines = parse_order_xls(xls_path)
print(f"导出行 {len(lines)}")
if repo is None:
try:
repo = OraclePayRepo.from_env()
except RepoUnavailable as exc:
if not args.dry_run:
print(f"数据库不可用:{exc}")
raise SystemExit(2) from exc
print(f"无库,dry-run 只解析:{exc}")
repo = EmptyPayRepo()
summary = run_yaoex_pay(repo, lines, dry_run=args.dry_run)
print(
"落表 "
f"inserted={summary.inserted} "
f"skipped_status={summary.skipped_status} "
f"skipped_dup={summary.skipped_dup} "
f"unmatched={summary.unmatched} "
f"reasons={summary.unmatched_reasons}"
)
def main_cart(args: argparse.Namespace, repo=None) -> None:
from cart_job import run_cart_batch
from cart_repo import OracleCartRepo
from cart_search import search_yaoex_offers, search_ybm_offers
from cart_yaoex import add_yaoex_cart
from cart_ybm import add_ybm_cart
load_cart_dotenv()
if repo is None:
try:
repo = OracleCartRepo.from_env()
except RepoUnavailable as exc:
print(f"数据库不可用:{exc}")
raise SystemExit(2) from exc
want_yaoex = args.platform in {"all", "yaoex"}
want_ybm = args.platform in {"all", "ybm"}
login_errors: dict[int, str] = {}
searchers = {}
adders = {}
yaoex_auth = None
ybm_cookies = None
runtime = BrowserRuntime(keep=False)
yaoex_session = requests.Session()
ybm_session = requests.Session()
yaoex_cache: dict = {}
ybm_cache: dict = {}
try:
if want_yaoex:
try:
yaoex_auth = resolve_yaoex_auth(
secrets_path=args.secrets,
auth_path=args.yaoex_auth,
fresh=args.fresh_login,
runtime=runtime,
)
print("1号药城认证就绪。")
except SystemExit:
raise
except Exception as exc:
login_errors[YAOEX_PLATFORM_TYPE] = str(exc)
print(f"1号药城登录失败,本平台中止:{exc}")
if want_ybm:
try:
ybm_cookies = resolve_ybm_cookies(
secrets_path=args.secrets,
cookie_path=args.ybm_cookies,
fresh=args.fresh_login,
runtime=runtime,
)
print("药帮忙认证就绪。")
except SystemExit:
raise
except Exception as exc:
login_errors[YBM_PLATFORM_TYPE] = str(exc)
print(f"药帮忙登录失败,本平台中止:{exc}")
if ybm_cookies:
for name, value in ybm_cookies.items():
ybm_session.cookies.set(name, value)
if yaoex_auth is not None:
def search_yaoex(query_key: str):
return search_yaoex_offers(
yaoex_auth, query_key, session=yaoex_session, cache=yaoex_cache
)
def add_yaoex(offer, qty: int):
return add_yaoex_cart(yaoex_auth, offer, qty, session=yaoex_session)
searchers[YAOEX_PLATFORM_TYPE] = search_yaoex
adders[YAOEX_PLATFORM_TYPE] = add_yaoex
if ybm_cookies is not None:
def search_ybm(query_key: str):
return search_ybm_offers(
ybm_cookies, query_key, session=ybm_session, cache=ybm_cache
)
def add_ybm(offer, qty: int):
return add_ybm_cart(ybm_cookies, offer, qty, session=ybm_session)
searchers[YBM_PLATFORM_TYPE] = search_ybm
adders[YBM_PLATFORM_TYPE] = add_ybm
platform_types: list[int] = []
if want_yaoex:
platform_types.append(YAOEX_PLATFORM_TYPE)
if want_ybm:
platform_types.append(YBM_PLATFORM_TYPE)
summary = run_cart_batch(
repo,
searchers=searchers,
adders=adders,
login_errors=login_errors,
limit=args.limit,
platform_types=platform_types,
)
print(
f"领取={summary.claimed} 加购成功={summary.added} 失败={summary.failed}"
)
print("未推订单中心,未清空购物车。")
finally:
yaoex_session.close()
ybm_session.close()
runtime.close()
if __name__ == "__main__":
main()