mirror of
https://git.oceanpay.cc/danial/kami_itunes_third_api.git
synced 2025-12-18 22:20:08 +00:00
- 修改 Docker Compose 配置,简化网络设置 - 新增 Docker 入口脚本,实现容器锁机制 - 更新 Dockerfile,使用新的入口脚本 - 添加 Makefile,简化部署流程 - 优化 Python 脚本,去除冗余的循环结构
215 lines
8.5 KiB
Python
215 lines
8.5 KiB
Python
import pickle
|
||
import time
|
||
import traceback
|
||
from datetime import timedelta, datetime
|
||
from multiprocessing import Process
|
||
|
||
import redis
|
||
from loguru import logger
|
||
|
||
from src.database import redis_pool
|
||
from src.integrations.june.models.login import AppleAccountModel
|
||
from src.integrations.master_node.api import MasterNodeService
|
||
from src.integrations.master_node.models import (
|
||
RechargeQueryModel,
|
||
ItunesRedeemRequestModel,
|
||
)
|
||
from src.models.model import (
|
||
AppleAccountSchema,
|
||
LoginFailureResponse,
|
||
RedeemRequestModel,
|
||
)
|
||
from src.service.itunes import ItunesService
|
||
|
||
|
||
def run_redeem_task(
|
||
master_order: RechargeQueryModel,
|
||
master_node_service: MasterNodeService,
|
||
reties=3,
|
||
):
|
||
redis_conn = redis_pool.get_connection()
|
||
redis_client = redis.Redis(connection_pool=redis_conn)
|
||
try:
|
||
if reties <= 0:
|
||
logger.error(f"调用次数已用完,请重新检查订单:{master_order}")
|
||
master_node_service.update_order_status(
|
||
ItunesRedeemRequestModel(
|
||
order_no=master_order.orderNo,
|
||
status=30, # 这边的登录状态与apple_account_schema的status是一样的
|
||
remark="调用次数已用完,需要手动检查订单",
|
||
amount=0,
|
||
account_amount=0,
|
||
),
|
||
)
|
||
return
|
||
response_schema = None
|
||
redis_client.incrby(f"apple_account_{master_order.account}_count", 1)
|
||
while True:
|
||
response_schema_from_itunes = redis_client.get(
|
||
f"apple_account_{master_order.account}"
|
||
)
|
||
if not response_schema_from_itunes:
|
||
break
|
||
# 如果不存在
|
||
apple_account_schema = AppleAccountSchema.model_validate(
|
||
pickle.loads(response_schema_from_itunes)
|
||
)
|
||
logger.info(f"查找已存在Cookie信息:{apple_account_schema.account}")
|
||
# 如果更新过账户密码
|
||
if (
|
||
apple_account_schema.account == master_order.account
|
||
and apple_account_schema.password != master_order.password
|
||
):
|
||
# 删除登录标识
|
||
redis_client.delete(f"apple_account_{master_order.account}")
|
||
break
|
||
if apple_account_schema.status != 2:
|
||
response_schema = apple_account_schema.login_schema
|
||
break
|
||
time.sleep(1)
|
||
itunes_service = ItunesService()
|
||
# 设置登录标识
|
||
if not response_schema_from_itunes:
|
||
redis_client.setex(
|
||
f"apple_account_{master_order.account}",
|
||
time=timedelta(seconds=30),
|
||
value=pickle.dumps(AppleAccountSchema(
|
||
account=master_order.account,
|
||
password=master_order.password,
|
||
status=2,
|
||
).model_dump()),
|
||
)
|
||
response_schema = itunes_service.login(
|
||
AppleAccountModel(
|
||
account=master_order.account, password=master_order.password
|
||
)
|
||
)
|
||
logger.info(f"登录完成:{master_order}")
|
||
if isinstance(response_schema, LoginFailureResponse):
|
||
# 如果登录失败,保存一天的登录信息
|
||
if not response_schema_from_itunes:
|
||
redis_client.setex(
|
||
f"apple_account_{master_order.account}",
|
||
time=timedelta(days=1),
|
||
value=pickle.dumps(AppleAccountSchema(
|
||
account=master_order.account,
|
||
password=master_order.password,
|
||
status=0,
|
||
login_schema=response_schema,
|
||
).model_dump()),
|
||
)
|
||
master_node_service.update_order_status(
|
||
ItunesRedeemRequestModel(
|
||
order_no=master_order.orderNo,
|
||
status=response_schema.status, # 这边的登录状态与apple_account_schema的status是一样的
|
||
remark=response_schema.message,
|
||
)
|
||
)
|
||
return
|
||
|
||
if not response_schema.login_schema.server_id:
|
||
return run_redeem_task(master_order, master_node_service, reties - 1)
|
||
|
||
if not response_schema_from_itunes:
|
||
# 登录成功,保存9分钟的登录信息
|
||
redis_client.setex(
|
||
f"apple_account_{master_order.account}",
|
||
time=timedelta(minutes=9),
|
||
value=pickle.dumps(AppleAccountSchema(
|
||
account=master_order.account,
|
||
password=master_order.password,
|
||
status=1,
|
||
login_schema=response_schema,
|
||
).model_dump())
|
||
)
|
||
redeem_result = itunes_service.redeem(
|
||
master_order.cardPass,
|
||
RedeemRequestModel.model_validate(
|
||
{
|
||
**response_schema.model_dump(),
|
||
"account_name": master_order.account,
|
||
"order_no": master_order.orderNo,
|
||
"apple_card_login_log_id": response_schema.apple_card_login_log_id,
|
||
}
|
||
),
|
||
response_schema_from_itunes is not None,
|
||
)
|
||
# 需要登录
|
||
if redeem_result.status == 0:
|
||
redis_client.delete(f"apple_account_{master_order.account}")
|
||
return run_redeem_task(master_order, master_node_service, reties - 1)
|
||
if redeem_result.status == 40:
|
||
logger.warning("充值1分钟限制,1分钟后重试")
|
||
time.sleep(60)
|
||
return run_redeem_task(master_order, master_node_service, reties - 1)
|
||
# 更新兑换状态
|
||
master_node_service.update_order_status(
|
||
ItunesRedeemRequestModel(
|
||
order_no=master_order.orderNo,
|
||
status=redeem_result.status, # 这边的登录状态与apple_account_schema的status是一样的
|
||
remark=redeem_result.remark,
|
||
amount=redeem_result.amount,
|
||
account_amount=redeem_result.balance,
|
||
),
|
||
)
|
||
except pickle.UnpicklingError as e:
|
||
logger.error(f"出现错误:{e},详细错误:\n{traceback.format_exc()}")
|
||
redis_client.delete(f"apple_account_{master_order.account}")
|
||
return run_redeem_task(master_order, master_node_service, reties - 1)
|
||
except Exception as e:
|
||
logger.error(f"出现错误:{e},详细错误:\n{traceback.format_exc()}")
|
||
master_node_service.update_order_status(
|
||
ItunesRedeemRequestModel(
|
||
order_no=master_order.orderNo,
|
||
status=30, # 这边的登录状态与apple_account_schema的status是一样的
|
||
remark="订单出错,请重新拉取",
|
||
amount=0,
|
||
account_amount=0,
|
||
),
|
||
)
|
||
finally:
|
||
redis_client.decrby(f"apple_account_{master_order.account}_count", 1)
|
||
# 如果程序正常结束,也需要执行清理操作
|
||
redis_client.close()
|
||
|
||
|
||
def run_task():
|
||
"""
|
||
执行任务
|
||
|
||
:return:
|
||
"""
|
||
# 注册信号处理程序
|
||
has_been_console = False
|
||
master_node_service = MasterNodeService()
|
||
# 1s获取两次订单
|
||
master_order = master_node_service.query_order()
|
||
if master_order.orderNo != "":
|
||
logger.info(f"当前订单:{master_order}")
|
||
run_redeem_task(master_order, master_node_service)
|
||
# 10分钟打印一次信息
|
||
if datetime.now().second % 10 == 0 and not has_been_console:
|
||
has_been_console = True
|
||
print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\t暂时没有订单")
|
||
if datetime.now().second % 10 != 0 and has_been_console:
|
||
has_been_console = False
|
||
|
||
def run():
|
||
# signal.signal(signal.SIGINT, signal_handler)
|
||
# signal.signal(signal.SIGTERM, signal_handler)
|
||
has_been_console = False
|
||
process = Process(target=run_task, args=(), daemon=True)
|
||
process.start()
|
||
while True:
|
||
# 10分钟打印一次信息
|
||
if datetime.now().minute % 2 == 0 and not has_been_console:
|
||
has_been_console = True
|
||
print(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\t心跳正常 鲜橙状态:{process.is_alive()}",
|
||
flush=True, )
|
||
if datetime.now().minute % 2 != 0 and has_been_console:
|
||
has_been_console = False
|
||
if not process.is_alive():
|
||
process.close()
|
||
process = Process(target=run_task, args=(), daemon=True)
|
||
process.start()
|