mirror of
https://git.oceanpay.cc/danial/kami_itunes_third_api.git
synced 2025-12-18 11:06:33 +00:00
feat(service): 添加代理服务并更新相关功能
- 新增 ProxyService 类,用于管理代理服务器 - 在 iTunes 服务中集成代理服务 - 更新 .gitignore 文件,添加新忽略项 - 在配置文件中添加代理服务器地址 - 更新相关模块以支持代理服务
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,3 +1,6 @@
|
||||
/.idea/
|
||||
/data/
|
||||
/venv/
|
||||
/.ipynb_checkpoints/
|
||||
*.pyc
|
||||
*.log
|
||||
@@ -21,4 +21,10 @@ redis:
|
||||
db: 0
|
||||
|
||||
masterNode:
|
||||
address: http://121.37.253.228:12310
|
||||
address: http://121.37.253.228:12310
|
||||
|
||||
proxies:
|
||||
address:
|
||||
- http://fga3568:fga3568@219.152.50.19:6588
|
||||
- http://fga3568:fga3568@125.74.88.251:6588
|
||||
- http://fga3568:fga3568@36.111.202.63:6588
|
||||
|
||||
@@ -42,11 +42,16 @@ class MasterNodeSettings(BaseSettings):
|
||||
address: str = Field(default="127.0.0.1", description="Address")
|
||||
|
||||
|
||||
class ProxySettings(BaseSettings):
|
||||
address: list[str] = Field(default=[], description="Address")
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
server: ServerSettings = Field(default_factory=ServerSettings)
|
||||
redis: RedisSettings = Field(default_factory=RedisSettings)
|
||||
database: DataBaseSettings = Field(default_factory=DataBaseSettings)
|
||||
masterNode: MasterNodeSettings = Field(default_factory=MasterNodeSettings)
|
||||
proxies: ProxySettings = Field(default_factory=ProxySettings)
|
||||
model_config = SettingsConfigDict(yaml_file="./config/config.yml", extra="ignore")
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -18,14 +18,17 @@ from src.integrations.itunes.models.redeem import (
|
||||
from src.integrations.itunes.utils import parse_xml
|
||||
from src.integrations.june.models.login import LoginSignatureModel, ItunesLoginModel
|
||||
from src.integrations.june.models.redeem import AuthenticateModel, ItunesRedeemModel
|
||||
from src.service.proxy import ProxyService
|
||||
|
||||
|
||||
class AppleClient:
|
||||
def __init__(self):
|
||||
self.__session = requests.Session()
|
||||
self.__session.adapters.update({
|
||||
"DEFAULT_RETRIES": 5,
|
||||
})
|
||||
self.__session.adapters.update(
|
||||
{
|
||||
"DEFAULT_RETRIES": 5,
|
||||
}
|
||||
)
|
||||
|
||||
def query_sign_sap_setup(self, signature: LoginSignatureModel, retries=3) -> str:
|
||||
if retries <= 0:
|
||||
@@ -63,7 +66,7 @@ class AppleClient:
|
||||
return response.text
|
||||
|
||||
def login(
|
||||
self, sign_map: AuthenticateModel, server_id: str = "", retries: int = 5
|
||||
self, sign_map: AuthenticateModel, server_id: str = "", retries: int = 5
|
||||
) -> ItunesLoginResponse:
|
||||
headers = {
|
||||
"X-Apple-ActionSignature": sign_map.signature,
|
||||
@@ -90,9 +93,9 @@ class AppleClient:
|
||||
params = {}
|
||||
if server_id != "":
|
||||
url = (
|
||||
"https://p"
|
||||
+ server_id
|
||||
+ "-buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/authenticate"
|
||||
"https://p"
|
||||
+ server_id
|
||||
+ "-buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/authenticate"
|
||||
)
|
||||
params = {"Pod": server_id, "PRH": server_id}
|
||||
else:
|
||||
@@ -118,14 +121,14 @@ class AppleClient:
|
||||
status = 31
|
||||
# 账户被禁用
|
||||
if (
|
||||
response_dict_data.get("metrics", {}).get("dialogId")
|
||||
== "MZFinance.AccountDisabled"
|
||||
response_dict_data.get("metrics", {}).get("dialogId")
|
||||
== "MZFinance.AccountDisabled"
|
||||
):
|
||||
status = 14
|
||||
# 账户被锁定
|
||||
if (
|
||||
response_dict_data.get("metrics", {}).get("dialogId")
|
||||
== "MZFinance.DisabledAndFraudLocked"
|
||||
response_dict_data.get("metrics", {}).get("dialogId")
|
||||
== "MZFinance.DisabledAndFraudLocked"
|
||||
):
|
||||
status = 14
|
||||
# 密码错误
|
||||
@@ -143,10 +146,10 @@ class AppleClient:
|
||||
)
|
||||
|
||||
def redeem(
|
||||
self,
|
||||
code: str,
|
||||
itunes: ItunesLoginModel,
|
||||
reties=5,
|
||||
self,
|
||||
code: str,
|
||||
itunes: ItunesLoginModel,
|
||||
reties=5,
|
||||
) -> RedeemSuccessResponse | RedeemFailResponseModel:
|
||||
if reties <= 0:
|
||||
logger.error("兑换失败,兑换重试次数已用完")
|
||||
@@ -173,7 +176,7 @@ class AppleClient:
|
||||
"Content-Type": "application/x-apple-plist; Charset=UTF-8",
|
||||
"User-Agent": "MacAppStore/2.0 (Macintosh; OS X 12.10) AppleWebKit/600.1.3.41",
|
||||
"Referer": f"https://p{itunes.server_id}-buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/com.apple"
|
||||
f".jingle.app.finance.DirectAction/redeemCode?cl=iTunes&pg=Music",
|
||||
f".jingle.app.finance.DirectAction/redeemCode?cl=iTunes&pg=Music",
|
||||
}
|
||||
try:
|
||||
response = self.__session.post(
|
||||
@@ -190,6 +193,7 @@ class AppleClient:
|
||||
has_4gb_limit=False,
|
||||
).to_xml(),
|
||||
headers=headers,
|
||||
proxies=ProxyService().get_wrap_proxy(itunes.account_name),
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(f"兑换连接错误,重试:{e}\t{traceback.format_exc()}")
|
||||
@@ -233,22 +237,31 @@ class AppleClient:
|
||||
result = RedeemFailResponseModel.model_validate(response.json())
|
||||
result.origin_log = response.text
|
||||
if (
|
||||
result.errorMessageKey
|
||||
== "MZCommerce.GiftCertificateAlreadyRedeemed"
|
||||
result.errorMessageKey
|
||||
== "MZCommerce.GiftCertificateAlreadyRedeemed"
|
||||
):
|
||||
# 已经被兑换
|
||||
result.status = 12
|
||||
elif result.errorMessageKey == "MZFreeProductCode.NoSuch":
|
||||
# 没有这个卡密
|
||||
result.status = 11
|
||||
elif result.errorMessageKey == "MZCommerce.NatIdYearlyCapExceededException":
|
||||
elif (
|
||||
result.errorMessageKey
|
||||
== "MZCommerce.NatIdYearlyCapExceededException"
|
||||
):
|
||||
# 年限额
|
||||
result.status = 31
|
||||
elif result.errorMessageKey == "MZCommerce.NatIdDailyCapExceededException":
|
||||
elif (
|
||||
result.errorMessageKey
|
||||
== "MZCommerce.NatIdDailyCapExceededException"
|
||||
):
|
||||
# 日限额
|
||||
result.status = 31
|
||||
# 国籍问题
|
||||
elif result.errorMessageKey == "MZCommerce.GiftCertRedeemStoreFrontMismatch":
|
||||
elif (
|
||||
result.errorMessageKey
|
||||
== "MZCommerce.GiftCertRedeemStoreFrontMismatch"
|
||||
):
|
||||
result.status = 15
|
||||
else:
|
||||
logger.error(f"失败状态未知:{response.json()}")
|
||||
|
||||
@@ -74,6 +74,7 @@ class AppleAccountModel(BaseModel):
|
||||
|
||||
|
||||
class ItunesLoginModel(BaseModel):
|
||||
account_name: str = Field(default="")
|
||||
server_id: str = Field(default="")
|
||||
dsis: int = Field(default=0)
|
||||
guid: str = Field(default="")
|
||||
|
||||
@@ -121,6 +121,7 @@ class ItunesService:
|
||||
result = self.apple_client_service.redeem(
|
||||
code,
|
||||
ItunesLoginModel(
|
||||
account_name=item.account_name,
|
||||
server_id=item.login_schema.server_id,
|
||||
guid=item.login_schema.guid,
|
||||
dsis=int(item.login_schema.dsis),
|
||||
|
||||
36
src/service/proxy.py
Normal file
36
src/service/proxy.py
Normal file
@@ -0,0 +1,36 @@
|
||||
import copy
|
||||
from time import time
|
||||
from src.initialization import setting
|
||||
import random
|
||||
|
||||
# 账户列表
|
||||
account_list = {}
|
||||
|
||||
|
||||
class ProxyService:
|
||||
def get_wrap_proxy(self, account_name: str):
|
||||
proxy = self.get_proxy(account_name)
|
||||
return {
|
||||
"http": proxy,
|
||||
"https": proxy,
|
||||
}
|
||||
|
||||
def get_proxy(self, account_name: str):
|
||||
self.set_expire_strategy()
|
||||
if account_name in account_list:
|
||||
return account_list[account_name].address
|
||||
return self.set_proxy(account_name)
|
||||
|
||||
def set_proxy(self, account_name: str):
|
||||
proxy = random.choice(setting.proxies.address)
|
||||
account_list[account_name] = {
|
||||
"address": proxy,
|
||||
"timeout": time.time() + 60 * 60 * 24,
|
||||
}
|
||||
return proxy
|
||||
|
||||
# 设置触发账号过期策略
|
||||
def set_expire_strategy(self):
|
||||
for key, value in copy.deepcopy(account_list).items():
|
||||
if value.get("timeout") > time.time():
|
||||
account_list.pop(key)
|
||||
Reference in New Issue
Block a user