feat: 继续完善代码仓库

This commit is contained in:
sunxiaolong
2024-08-17 10:20:41 +08:00
parent e95c25ee8b
commit a1b117e07b
12 changed files with 189 additions and 133 deletions

View File

@@ -8,11 +8,11 @@ server:
database:
schema: mysql
host: IP_ADDRESS
host: 127.0.0.1
port: 3306
user: USER
password: PASSWORD
database: DATABASE
user: root
password: 123456
database: itunes_kami
redis:
host: 127.0.0.1
@@ -21,4 +21,4 @@ redis:
db: 0
masterNode:
address: IP_ADDRESS
address: http://121.37.253.228:12310

12
main.py
View File

@@ -1,12 +1,4 @@
import json
import pickle
import redis
from src.database import redis_pool
from src.cmd.scripts import run
if __name__ == "__main__":
redis_conn = redis_pool.get_connection()
redis_client = redis.Redis(connection_pool=redis_conn)
redis_client.setex("test_count", 1000, pickle.dumps(json.dumps({"a": 1})))
print(pickle.loads(redis_client.get("test_count")))
run()

View File

@@ -1,8 +1,9 @@
import pickle
import time
from datetime import datetime, timedelta
from multiprocessing import Process
from datetime import timedelta, datetime
import redis
from loguru import logger
from src.database import redis_pool
from src.integrations.june.models.login import AppleAccountModel
@@ -15,30 +16,44 @@ from src.models.model import (
AppleAccountSchema,
LoginFailureResponse,
RedeemRequestModel,
LoginSuccessResponse,
)
from src.service.service import ItunesService
from src.service.itunes import ItunesService
def run_redeem_task(
master_order: RechargeQueryModel, master_node_service: MasterNodeService
master_order: RechargeQueryModel, master_node_service: MasterNodeService
):
itunes_service = ItunesService()
redis_conn = redis_pool.get_connection()
redis_client = redis.Redis(connection_pool=redis_conn)
response_schema = None
while True:
response_schema_from_itunes = redis_client.get(
f"apple_account_{master_order.account}"
)
if not response_schema_from_itunes:
break
# 如果不存在
if response_schema_from_itunes:
apple_account_schema = AppleAccountSchema.model_validate_json(
bytes(response_schema_from_itunes).decode()
)
apple_account_schema = AppleAccountSchema.model_validate(
pickle.loads(response_schema_from_itunes)
)
# 如果更新过账户密码
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}")
redis_client.delete(f"apple_account_{master_order.account}_count")
break
if apple_account_schema.status != 2:
response_schema = apple_account_schema.login_schema
if response_schema.status != 2:
break
time.sleep(2)
break
time.sleep(2)
# 设置登录标识
if not response_schema_from_itunes:
redis_client.setex(
f"apple_account_{master_order.account}",
@@ -49,7 +64,6 @@ def run_redeem_task(
status=2,
).model_dump_json(),
)
redis_client.set(f"apple_account_{master_order.account}_count", 1)
response_schema = itunes_service.login(
AppleAccountModel(
account=master_order.account, password=master_order.password
@@ -58,6 +72,21 @@ def run_redeem_task(
redis_client.incrby(f"apple_account_{master_order.account}_count", 1)
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,
@@ -65,60 +94,56 @@ def run_redeem_task(
remark=response_schema.message,
)
)
if not response_schema_from_itunes:
redis_client.setex(
f"apple_account_{master_order.account}",
time=timedelta(days=1),
value=AppleAccountSchema(
account=master_order.account,
password=master_order.password,
status=0,
login_schema=response_schema,
).model_dump_json(),
)
redis_client.decrby(f"apple_account_{master_order.account}_count", 1)
else:
redeem_result = itunes_service.redeem(
master_order.cardPass,
RedeemRequestModel.model_validate(
{
**response_schema.model_dump_json(),
"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}")
redis_client.decrby(f"apple_account_{master_order.account}_count", 1)
run_redeem_task(master_order, master_node_service)
return
# 兑换状态
master_node_service.update_order_status(
ItunesRedeemRequestModel(
order_no=master_order.orderNo,
status=redeem_result.status, # 这边的登录状态与apple_account_schema的status是一样的
remark="",
amount=redeem_result.amount,
account_amount=redeem_result.balance,
),
)
if not response_schema_from_itunes:
# 登录成功保存9分钟的登录信息
redis_client.setex(
f"apple_account_{master_order.account}",
time=timedelta(minutes=9),
value=AppleAccountSchema(
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_json(),
)
).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}")
redis_client.decrby(f"apple_account_{master_order.account}_count", 1)
return run_redeem_task(master_order, master_node_service)
if redeem_result.status == 40:
logger.warning("充值1分钟限制1分钟后重试")
redis_client.decrby(f"apple_account_{master_order.account}_count", 1)
time.sleep(60)
return run_redeem_task(master_order, master_node_service)
# 更新兑换状态
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,
),
)
redis_client.decrby(f"apple_account_{master_order.account}_count", 1)
def run_task():
@@ -127,20 +152,25 @@ def run_task():
:return:
"""
master_node_service = MasterNodeService()
master_order = master_node_service.query_order()
run_redeem_task(master_order, master_node_service)
while True:
master_node_service = MasterNodeService()
master_order = master_node_service.query_order()
if master_order.orderNo != "":
run_redeem_task(master_order, master_node_service)
print(f"{datetime.now().strftime("%Y-%m-%d %H:%M:%S")}\t暂时没有订单")
time.sleep(2)
def run():
# 定义一个进程池
proc = Process(target=run_task, daemon=True)
# 启动进程池
proc.start()
while True:
print(f"主进程执行:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
time.sleep(1)
if not proc.is_alive():
proc = Process(target=run_task, daemon=True)
proc.start()
run_task()
# # 定义一个进程池
# proc = Process(target=run_task, daemon=True)
# # 启动进程池
# proc.start()
#
# while True:
# # print(f"主进程执行:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
# time.sleep(1)
# if not proc.is_alive():
# proc = Process(target=run_task, daemon=True)
# proc.start()

View File

@@ -1 +1,2 @@
from .settings import setting
from .log import *

View File

@@ -1,9 +1,13 @@
# logger.add(
# f"{setting.server.logger.path}/{{time:YYYY-MM-DD}}.log",
# rotation="1 days", # 每天生成新文件
# retention="20 days", # 保留最近10天的日志文件
# compression="zip", # 压缩旧日志文件
# encoding="utf-8", # 文件编码
# level=setting.server.logger.level,
# enqueue=True, # 异步写入日志
# )
from loguru import logger
from src.initialization import setting
logger.add(
f"{setting.server.logger.path}/{{time:YYYY-MM-DD}}.log",
rotation="1 days", # 每天生成新文件
retention="20 days", # 保留最近10天的日志文件
compression="zip", # 压缩旧日志文件
encoding="utf-8", # 文件编码
level=setting.server.logger.level,
enqueue=True, # 异步写入日志
)

View File

@@ -13,7 +13,7 @@ class DataBaseSettings(BaseSettings):
host: str = Field(default="localhost", description="Host")
port: int = Field(default=5432, description="Port")
user: str = Field(default="postgres", description="User")
password: str = Field(default="", description="Password")
password: str | int = Field(default="", description="Password")
database: str = Field(default="postgres", description="Database")
model_config = SettingsConfigDict(extra="ignore")

View File

@@ -3,8 +3,8 @@ import pickle
import re
import requests
from loguru import logger
from src.initialization import logger
from src.integrations.itunes.models.login import (
ItunesLoginResponse,
ItunesFailLoginPlistData,
@@ -171,22 +171,30 @@ class AppleClient:
)
response.encoding = "utf-8"
try:
if not response.text.strip():
return RedeemFailResponseModel(
status=40,
errorMessageKey="",
errorMessage="兑换1分钟限制",
origin_log=response.text,
userPresentableErrorMessage="兑换1分钟限制",
)
if "xml" in response.text:
if "MZFinance.RedeemCodeSrvLoginRequired" in response.text:
return RedeemFailResponseModel(
status=0,
errorMessageKey="",
errorMessage="需要登录",
originLog=response.text,
origin_log=response.text,
userPresentableErrorMessage="需要登录",
)
else:
if response.json().get("status") == 0:
result = RedeemSuccessResponse.model_validate(response.json())
result.originLog = response.text
result.origin_log = response.text
return result
result = RedeemFailResponseModel.model_validate(response.json())
result.originLog = response.text
result.origin_log = response.text
if (
result.errorMessageKey
== "MZCommerce.GiftCertificateAlreadyRedeemed"
@@ -199,12 +207,12 @@ class AppleClient:
logger.warning("兑换状态未知:", response.text)
return result
except json.JSONDecodeError as e:
logger.error("json格式化失败", e)
logger.error(f"json格式化失败{e}\t返回值{response.text}")
return RedeemFailResponseModel(
status=30,
errorMessageKey="",
errorMessage="状态未知",
originLog=response.text,
origin_log=response.text,
userPresentableErrorMessage="状态未知",
)

View File

@@ -1,13 +1,15 @@
from pydantic import BaseModel, Field
from pydantic import BaseModel, Field, ConfigDict
class RedeemFailResponseModel(BaseModel):
model_config = ConfigDict(extra="ignore")
errorMessageKey: str = Field(default="", alias="errorMessageKey")
errorMessage: str = Field(default="", alias="errorMessage")
userPresentableErrorMessage: str = Field(
default="", alias="userPresentableErrorMessage"
)
origin_log: str = Field(default="", alias="originLog")
origin_log: str = Field(default="")
status: int = Field(..., alias="status", description="0.需要登录 1.正常")

View File

@@ -6,20 +6,20 @@ from src.integrations.june.models.login import ItunesLoginModel
class LoginSuccessResponse(BaseModel):
login_schema: ItunesLoginModel = Field(..., description="需要登录的信息")
cookies: bytes = Field(..., description="登录后的cookie")
apple_card_login_log_id = Field(..., description="apple_card_login_log_id")
apple_card_login_log_id: str = Field(..., description="apple_card_login_log_id")
class RedeemRequestModel(LoginSuccessResponse):
account_name: str = Field(..., description="账号")
order_no: str = Field(..., description="订单号")
apple_card_login_log_id = Field(..., description="apple_card_login_log_id")
apple_card_login_log_id: str = Field(..., description="apple_card_login_log_id")
class LoginFailureResponse(BaseModel):
message: str = Field(..., description="登录失败的信息")
failure_type: str = Field(..., description="登录失败的类型")
status: int = Field(..., description="登录失败的状态")
apple_card_login_log_id = Field(..., description="apple_card_login_log_id")
apple_card_login_log_id: str = Field(..., description="apple_card_login_log_id")
class AppleAccountSchema(BaseModel):
@@ -33,7 +33,8 @@ class AppleAccountSchema(BaseModel):
class AppleAccountRedeemResponse(BaseModel):
status: int = Field(default=30, description="充值状态20 充值成功")
status: int = Field(default=30, description="充值状态20 充值成功 0 需要登录")
balance: float = Field(default=0, description="充值后金额")
amount: float = Field(default=0, description="充值金额")
origin_text: str = Field(default="", description="原始信息")
remark: str = Field(default="", description="备注")

View File

@@ -10,9 +10,9 @@ Base = declarative_base()
class AppleCardLoginLogSchema(Base):
__tablename__ = "apple_card_login_log"
id = Column(UUID(), primary_key=True)
account_name = Column(String, comment="登录账户")
account_password = Column(String, comment="账户密码")
id = Column(String(64), primary_key=True)
account_name = Column(String(100), comment="登录账户")
account_password = Column(String(100), comment="账户密码")
origin_log = Column(Text, comment="原始日志内容")
status = Column(Integer, comment="登录状态")
created_at = Column(
@@ -23,16 +23,16 @@ class AppleCardLoginLogSchema(Base):
class AppleCardRedeemLogSchema(Base):
__tablename__ = "apple_card_redeem_log"
id = Column(Integer, primary_key=True, autoincrement=True, comment="自增ID")
apple_card_login_log_id = Column(UUID(), comment="登录日志内容")
order_no = Column(String, comment="订单号")
apple_card_login_log_id = Column(String(64), comment="登录日志内容")
order_no = Column(String(100), comment="订单号")
redeem_status = Column(Integer, comment="充值状态")
# 充值账户
account_name = Column(String, comment="充值账户")
account_name = Column(String(100), comment="充值账户")
amount = Column(Float, comment="充值金额")
account_balance = Column(Float, comment="充值后账户余额")
card_pass = Column(String, comment="充值卡密")
remark = Column(String, comment="备注")
card_pass = Column(String(64), comment="充值卡密")
remark = Column(Text, comment="备注")
# 原始日志内容
origin_log = Column(Text, comment="原始日志内容")
# 充值时间
@@ -42,7 +42,7 @@ class AppleCardRedeemLogSchema(Base):
# 创建表结构
# Base.metadata.create_all(engine)
Base.metadata.create_all(engine)
def get_session() -> sessionmaker[Session]:

View File

@@ -50,9 +50,10 @@ class ItunesService:
login_schema = self.apple_client_service.login(sign_sap_cert.Data)
session = get_session()()
db_id = uuid.uuid4()
db_id = uuid.uuid4().hex
if isinstance(login_schema.response, ItunesSuccessLoginPlistData):
# 登录成功
session.add(
AppleCardLoginLogSchema(
id=db_id,
@@ -73,6 +74,7 @@ class ItunesService:
apple_card_login_log_id=db_id,
)
else:
# 登录失败
session.add(
AppleCardLoginLogSchema(
id=db_id,
@@ -94,29 +96,30 @@ class ItunesService:
return response_result
def redeem(
self, code: str, schema: RedeemRequestModel, set_cookie: bool = False
self, code: str, item: RedeemRequestModel, set_cookie: bool = False
) -> AppleAccountRedeemResponse:
"""
兑换代码
:param set_cookie:
:param schema:
:param item:
:param code:
:return:
"""
if set_cookie:
self.apple_client_service.import_cookies(schema.cookies)
self.apple_client_service.import_cookies(item.cookies)
session = get_session()()
result = self.apple_client_service.redeem(
code,
ItunesLoginModel(
server_id=schema.login_schema.server_id,
guid=schema.login_schema.guid,
dsis=int(schema.login_schema.dsis),
passwordToken=schema.login_schema.password_token,
server_id=item.login_schema.server_id,
guid=item.login_schema.guid,
dsis=int(item.login_schema.dsis),
passwordToken=item.login_schema.password_token,
),
)
if isinstance(result, RedeemSuccessResponse):
# 充值成功
response_result = AppleAccountRedeemResponse(
status=20,
balance=result.totalCredit.moneyRaw,
@@ -124,18 +127,33 @@ class ItunesService:
)
session.add(
AppleCardRedeemLogSchema(
apple_card_login_log_id=schema.apple_card_login_log_id,
account_name=schema.account_name,
order_no=schema.order_no,
apple_card_login_log_id=item.apple_card_login_log_id,
account_name=item.account_name,
order_no=item.order_no,
redeem_status=response_result.status,
amount=result.redeemedCredit.moneyRaw,
account_balance=result.totalCredit.moneyRaw,
card_pass=code,
origin_log=response_result.origin_text,
origin_log=result.origin_log,
)
)
else:
# 充值失败
response_result = AppleAccountRedeemResponse(
status=result.status,
remark=result.errorMessage,
)
session.add(
AppleCardRedeemLogSchema(
apple_card_login_log_id=item.apple_card_login_log_id,
account_name=item.account_name,
order_no=item.order_no,
amount=0,
redeem_status=response_result.status,
account_balance=0,
card_pass=code,
origin_log=result.origin_log,
)
)
session.commit()
session.close()

View File

@@ -5,7 +5,7 @@ from loguru import logger
from src.integrations.june.models.login import AppleAccountModel
from src.models.model import LoginSuccessResponse
from src.service.service import ItunesService
from src.service.itunes import ItunesService
class TestItunesService(TestCase):
@@ -72,7 +72,7 @@ class TestItunesService(TestCase):
)
result_schema = service.login(account)
if isinstance(result_schema, LoginSuccessResponse):
result = service.redeem("X7ZWF6V4M626Z4MT", schema=result_schema)
result = service.redeem("X7ZWF6V4M626Z4MT", item=result_schema)
logger.info(result)
else:
logger.info(result_schema)