mirror of
https://github.com/baiqwerdvd/ArknightsUID.git
synced 2025-05-04 11:07:35 +08:00
✨ 完成 skd bind
This commit is contained in:
parent
78c2d97165
commit
bc4c1983ec
6
ArknightsUID/arknightsuid_config/ark_config.py
Normal file
6
ArknightsUID/arknightsuid_config/ark_config.py
Normal file
@ -0,0 +1,6 @@
|
||||
from gsuid_core.utils.plugins_config.gs_config import StringConfig
|
||||
|
||||
from ..utils.resource.RESOURCE_PATH import CONFIG_PATH
|
||||
from .config_default import CONIFG_DEFAULT
|
||||
|
||||
arkconfig = StringConfig('ArknightsUID', CONFIG_PATH, CONIFG_DEFAULT)
|
13
ArknightsUID/arknightsuid_config/config_default.py
Normal file
13
ArknightsUID/arknightsuid_config/config_default.py
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
from gsuid_core.utils.plugins_config.models import (
|
||||
GSC,
|
||||
GsStrConfig,
|
||||
)
|
||||
|
||||
CONIFG_DEFAULT: dict[str, GSC] = {
|
||||
'ArknightsPrefix': GsStrConfig(
|
||||
'插件命令前缀(确认无冲突再修改)',
|
||||
'用于本插件的前缀设定',
|
||||
'ark',
|
||||
),
|
||||
}
|
20
ArknightsUID/arknightsuid_resource/__init__.py
Normal file
20
ArknightsUID/arknightsuid_resource/__init__.py
Normal file
@ -0,0 +1,20 @@
|
||||
# from gsuid_core.bot import Bot
|
||||
# from gsuid_core.logger import logger
|
||||
# from gsuid_core.models import Event
|
||||
# from gsuid_core.sv import SV
|
||||
|
||||
# from ..utils.resource.download_all_resource import download_all_resource
|
||||
|
||||
# sv_download_config = SV('下载资源', pm=2)
|
||||
|
||||
|
||||
# @sv_download_config.on_fullmatch(('下载全部资源'))
|
||||
# async def send_download_resource_msg(bot: Bot, ev: Event):
|
||||
# await bot.send('正在开始下载~可能需要较久的时间!')
|
||||
# im = await download_all_resource()
|
||||
# await bot.send(im)
|
||||
|
||||
|
||||
# async def startup():
|
||||
# logger.info('[资源文件下载] 正在检查与下载缺失的资源文件,可能需要较长时间,请稍等')
|
||||
# logger.info(f'[资源文件下载] {await download_all_resource()}')
|
13
ArknightsUID/arknightsuid_start/__init__.py
Normal file
13
ArknightsUID/arknightsuid_start/__init__.py
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
|
||||
# from ..arknightsuid_resource import startup
|
||||
|
||||
|
||||
# async def all_start():
|
||||
# try:
|
||||
# await startup()
|
||||
# except Exception as e:
|
||||
# logger.exception(e)
|
||||
|
||||
|
||||
# threading.Thread(target=lambda: asyncio.run(all_start()), daemon=True).start()
|
73
ArknightsUID/arknightsuid_user/__init__.py
Normal file
73
ArknightsUID/arknightsuid_user/__init__.py
Normal file
@ -0,0 +1,73 @@
|
||||
|
||||
from gsuid_core.bot import Bot
|
||||
from gsuid_core.models import Event
|
||||
from gsuid_core.sv import SV
|
||||
|
||||
from ..utils.ark_prefix import PREFIX
|
||||
from ..utils.database.models import ArknightsBind
|
||||
from ..utils.message import send_diff_msg
|
||||
from .deal_skd_cred import deal_skd_cred
|
||||
|
||||
# from .draw_user_card import get_user_card
|
||||
|
||||
sv_user_config = SV('ark用户管理', pm=2)
|
||||
sv_user_add = SV('ark用户添加')
|
||||
sv_user_info = SV('ark用户信息')
|
||||
ark_skd_cred_add = SV('森空岛cred绑定')
|
||||
# sv_user_help = SV('ark绑定帮助')
|
||||
|
||||
|
||||
# @sv_user_info.on_fullmatch((f'{PREFIX}绑定信息'))
|
||||
# async def send_bind_card(bot: Bot, ev: Event):
|
||||
# await bot.logger.info('ark开始执行[查询用户绑定状态]')
|
||||
# uid_list = await get_user_card(ev.bot_id, ev.user_id)
|
||||
# await bot.logger.info('ark[查询用户绑定状态]完成!等待图片发送中...')
|
||||
# await bot.send(uid_list)
|
||||
|
||||
|
||||
@sv_user_info.on_command(
|
||||
(f'{PREFIX}绑定uid', f'{PREFIX}切换uid', f'{PREFIX}删除uid', f'{PREFIX}解绑uid')
|
||||
)
|
||||
async def send_link_uid_msg(bot: Bot, ev: Event):
|
||||
await bot.logger.info("开始执行[绑定/解绑用户信息]")
|
||||
qid = ev.user_id
|
||||
await bot.logger.info(f"[绑定/解绑]UserID: {qid}")
|
||||
|
||||
ark_uid = ev.text.strip()
|
||||
if ark_uid and not ark_uid.isdigit():
|
||||
return await bot.send("你输入了错误的格式!")
|
||||
|
||||
if '绑定' in ev.command:
|
||||
data = await ArknightsBind.insert_uid(qid, ev.bot_id, ark_uid, ev.group_id)
|
||||
return await send_diff_msg(
|
||||
bot,
|
||||
data,
|
||||
{
|
||||
0: f'绑定ARK_UID{ark_uid}成功!',
|
||||
-1: f'ARK_UID{ark_uid}的位数不正确!',
|
||||
-2: f'ARK_UID{ark_uid}已经绑定过了!',
|
||||
-3: '你输入了错误的格式!',
|
||||
},
|
||||
)
|
||||
elif '切换' in ev.command:
|
||||
data = await ArknightsBind.switch_uid_by_game(qid, ev.bot_id, ark_uid)
|
||||
if isinstance(data, list):
|
||||
return await bot.send(f'切换ARK_UID{ark_uid}成功!')
|
||||
else:
|
||||
return await bot.send(f'尚未绑定该ARK_UID{ark_uid}')
|
||||
else:
|
||||
data = await ArknightsBind.delete_uid(qid, ev.bot_id, ark_uid)
|
||||
return await send_diff_msg(
|
||||
bot,
|
||||
data,
|
||||
{
|
||||
0: f'删除ARK_UID{ark_uid}成功!',
|
||||
-1: f'该ARK_UID{ark_uid}不在已绑定列表中!',
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@ark_skd_cred_add.on_prefix(("skd添加cred", "森空岛添加CRED"))
|
||||
async def send_ark_skd_add_cred_msg(bot: Bot, ev: Event):
|
||||
im = await deal_skd_cred(ev.bot_id, ev.text, ev.user_id)
|
||||
await bot.send(im)
|
21
ArknightsUID/arknightsuid_user/deal_skd_cred.py
Normal file
21
ArknightsUID/arknightsuid_user/deal_skd_cred.py
Normal file
@ -0,0 +1,21 @@
|
||||
from ..utils.ark_api import ark_skd_api
|
||||
from ..utils.database.models import ArknightsUser
|
||||
|
||||
ERROR_HINT = '添加失败,格式为:用户ID - Cred\n \
|
||||
例如:1810461245 - VropL583Sb1hClS5buQ4nSASkDlL8tMT'
|
||||
|
||||
|
||||
async def deal_skd_cred(bot_id: str, cred: str, user_id: str) -> str:
|
||||
if '-' not in cred:
|
||||
return ERROR_HINT
|
||||
_ck = cred.replace(' ', '').split('-')
|
||||
if len(_ck) != 2 or not _ck[0] or not _ck[0].isdigit() or not _ck[1]:
|
||||
return ERROR_HINT
|
||||
|
||||
check_cred = await ark_skd_api.check_cred_valid(_ck[1])
|
||||
if check_cred:
|
||||
return 'Cred无效!'
|
||||
uid, cred = _ck[0], _ck[1]
|
||||
await ArknightsUser.insert_data(user_id, bot_id,
|
||||
Cred=cred, uid=uid, skd_uid=check_cred)
|
||||
return '添加成功!'
|
@ -0,0 +1 @@
|
||||
ARK_USER_ME = 'https://zonai.skland.com/api/v1/user/me'
|
86
ArknightsUID/utils/api/skd/request.py
Normal file
86
ArknightsUID/utils/api/skd/request.py
Normal file
@ -0,0 +1,86 @@
|
||||
from copy import deepcopy
|
||||
from typing import Any, Literal
|
||||
|
||||
from aiohttp import ClientSession, ContentTypeError, TCPConnector
|
||||
from gsuid_core.logger import logger
|
||||
|
||||
from ...database.models import ArknightsUser
|
||||
from ...models.skland.models import ArknightsUserMeModel
|
||||
from .api import ARK_USER_ME
|
||||
|
||||
|
||||
class BaseArkApi:
|
||||
ssl_verify = True
|
||||
_HEADER = {
|
||||
"Host": "zonai.skland.com",
|
||||
"Origin": "https://www.skland.com",
|
||||
"Referer": "https://www.skland.com/",
|
||||
"content-type": "application/json; charset=UTF-8",
|
||||
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) \
|
||||
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36",
|
||||
}
|
||||
|
||||
async def check_cred_valid(self, Cred: str) -> bool | str:
|
||||
header = deepcopy(self._HEADER)
|
||||
header['Cred'] = Cred
|
||||
raw_data = await self._ark_request(ARK_USER_ME, header=header)
|
||||
unpack_data = self.unpack(raw_data)
|
||||
if isinstance(unpack_data, int):
|
||||
return False
|
||||
else:
|
||||
return ArknightsUserMeModel(**unpack_data).user.id_
|
||||
|
||||
def unpack(self, raw_data: dict | int) -> dict | int:
|
||||
if isinstance(raw_data, dict):
|
||||
return raw_data["data"]
|
||||
else:
|
||||
return raw_data
|
||||
|
||||
async def _ark_request(
|
||||
self,
|
||||
url: str,
|
||||
method: Literal["GET", "POST"] = "GET",
|
||||
header: dict[str, Any] = _HEADER,
|
||||
params: dict[str, Any] | None = None,
|
||||
data: dict[str, Any] | None = None,
|
||||
) -> dict | int:
|
||||
if "Cred" not in header:
|
||||
target_user_id = (
|
||||
data["friendUserId"]
|
||||
if data and "friendUserId" in data
|
||||
else None
|
||||
)
|
||||
Cred: str | None = await ArknightsUser.get_random_cookie(
|
||||
target_user_id if target_user_id else "18888888"
|
||||
)
|
||||
if Cred is None:
|
||||
return -61
|
||||
arkUser = await ArknightsUser.base_select_data(ArknightsUser, Cred=Cred)
|
||||
if arkUser is None:
|
||||
return -61
|
||||
header["Cred"] = Cred
|
||||
|
||||
async with ClientSession(
|
||||
connector=TCPConnector(verify_ssl=self.ssl_verify)
|
||||
) as client:
|
||||
async with client.request(
|
||||
method,
|
||||
url=url,
|
||||
headers=header,
|
||||
params=params,
|
||||
json=data,
|
||||
timeout=300,
|
||||
) as resp:
|
||||
try:
|
||||
raw_data = await resp.json()
|
||||
except ContentTypeError:
|
||||
_raw_data = await resp.text()
|
||||
raw_data = {"code": -999, "data": _raw_data}
|
||||
if (
|
||||
raw_data
|
||||
and 'code' in raw_data
|
||||
and raw_data['code'] != 0
|
||||
):
|
||||
return raw_data['code']
|
||||
logger.debug(raw_data)
|
||||
return raw_data
|
3
ArknightsUID/utils/ark_api.py
Normal file
3
ArknightsUID/utils/ark_api.py
Normal file
@ -0,0 +1,3 @@
|
||||
from .api.skd.request import BaseArkApi
|
||||
|
||||
ark_skd_api = BaseArkApi()
|
3
ArknightsUID/utils/ark_prefix.py
Normal file
3
ArknightsUID/utils/ark_prefix.py
Normal file
@ -0,0 +1,3 @@
|
||||
from ..arknightsuid_config.ark_config import arkconfig
|
||||
|
||||
PREFIX = arkconfig.get_config('ArknightsPrefix').data
|
34
ArknightsUID/utils/database/models.py
Normal file
34
ArknightsUID/utils/database/models.py
Normal file
@ -0,0 +1,34 @@
|
||||
from gsuid_core.utils.database.base_models import (
|
||||
Bind,
|
||||
User,
|
||||
)
|
||||
from gsuid_core.webconsole.mount_app import GsAdminModel, PageSchema, site
|
||||
from sqlmodel import Field
|
||||
|
||||
|
||||
class ArknightsBind(Bind, table=True):
|
||||
uid: str | None = Field(default=None, title='明日方舟UID')
|
||||
|
||||
|
||||
class ArknightsUser(User, table=True):
|
||||
uid: str | None = Field(default=None, title='明日方舟UID')
|
||||
skd_uid: str | None = Field(default=None, title='SKD用户ID')
|
||||
cred: str | None = Field(default=None, title='SKD凭证')
|
||||
|
||||
|
||||
@site.register_admin
|
||||
class ArknightsBindadmin(GsAdminModel):
|
||||
pk_name = 'id'
|
||||
page_schema = PageSchema(label='方舟绑定管理', icon='fa fa-users') # type: ignore
|
||||
|
||||
# 配置管理模型
|
||||
model = ArknightsBind
|
||||
|
||||
|
||||
@site.register_admin
|
||||
class ArknightsUseradmin(GsAdminModel):
|
||||
pk_name = 'id'
|
||||
page_schema = PageSchema(label='方舟SKD CRED管理', icon='fa fa-database') # type: ignore
|
||||
|
||||
# 配置管理模型
|
||||
model = ArknightsUser
|
22
ArknightsUID/utils/download.py
Normal file
22
ArknightsUID/utils/download.py
Normal file
@ -0,0 +1,22 @@
|
||||
from pathlib import Path
|
||||
|
||||
import aiofiles
|
||||
from aiohttp.client import ClientSession
|
||||
from aiohttp.client_exceptions import ClientConnectorError
|
||||
from gsuid_core.logger import logger
|
||||
|
||||
|
||||
async def download_file(
|
||||
url: str,
|
||||
path: Path,
|
||||
name: str,
|
||||
):
|
||||
sess = ClientSession()
|
||||
try:
|
||||
async with sess.get(url) as res:
|
||||
content = await res.read()
|
||||
except ClientConnectorError:
|
||||
logger.warning(f"[wzry]{name}下载失败")
|
||||
return url, path, name
|
||||
async with aiofiles.open(path / name, "wb") as f:
|
||||
await f.write(content)
|
16
ArknightsUID/utils/message.py
Normal file
16
ArknightsUID/utils/message.py
Normal file
@ -0,0 +1,16 @@
|
||||
from typing import Any
|
||||
|
||||
from gsuid_core.bot import Bot
|
||||
|
||||
|
||||
async def send_diff_msg(bot: Bot, code: Any, data: dict | None = None):
|
||||
if data is None:
|
||||
data = {
|
||||
0: '绑定UID成功!',
|
||||
-1: 'UID的位数不正确!',
|
||||
-2: 'UID已经绑定过了!',
|
||||
-3: '你输入了错误的格式!',
|
||||
}
|
||||
for retcode in data:
|
||||
if code == retcode:
|
||||
return await bot.send(data[retcode])
|
@ -1,5 +1,100 @@
|
||||
from msgspec import Struct, field
|
||||
|
||||
################
|
||||
# ArknightsUserMeModel Start
|
||||
################
|
||||
|
||||
class UserMeInfoApply(Struct):
|
||||
nickname: str
|
||||
profile: str
|
||||
|
||||
|
||||
class UserMeModerator(Struct):
|
||||
isModerator: bool
|
||||
|
||||
|
||||
class UserGameStatusAp(Struct):
|
||||
current: int
|
||||
max_: int = field(name='max')
|
||||
lastApAddTime: int
|
||||
completeRecoveryTime: int
|
||||
|
||||
|
||||
class UserGameStatusSecretary(Struct):
|
||||
charId: str
|
||||
skinId: str
|
||||
|
||||
|
||||
class UserGameStatusAvatar(Struct):
|
||||
type_: str = field(name='type')
|
||||
id_: str = field(name='id')
|
||||
|
||||
|
||||
class UserGameStatus(Struct):
|
||||
uid: str
|
||||
name: str
|
||||
level: int
|
||||
avatar: UserGameStatusAvatar
|
||||
registerTs: int
|
||||
mainStageProgress: str
|
||||
secretary: UserGameStatusSecretary
|
||||
resume: str
|
||||
subscriptionEnd: int
|
||||
ap: UserGameStatusAp
|
||||
storeTs: int
|
||||
lastOnlineTs: int
|
||||
charCnt: int
|
||||
furnitureCnt: int
|
||||
skinCnt: int
|
||||
|
||||
|
||||
class UserMeInfoRts(Struct):
|
||||
liked: str
|
||||
collect: str
|
||||
comment: str
|
||||
follow: str
|
||||
fans: str
|
||||
black: str
|
||||
pub: str
|
||||
|
||||
|
||||
class UserMeInfo(Struct):
|
||||
id_: str = field(name='id')
|
||||
nickname: str
|
||||
profile: str
|
||||
avatarCode: int
|
||||
avatar: str
|
||||
backgroundCode: int
|
||||
isCreator: bool
|
||||
creatorIdentifiers: list[str]
|
||||
status: int
|
||||
operationStatus: int
|
||||
identity: int
|
||||
kind: int
|
||||
latestIpLocation: str
|
||||
moderatorStatus: int
|
||||
moderatorChangeTime: int
|
||||
gender: int
|
||||
birthday: str
|
||||
|
||||
|
||||
class ArknightsUserMeModel(Struct):
|
||||
user: UserMeInfo
|
||||
userRts: UserMeInfoRts
|
||||
userSanctionList: list[str]
|
||||
gameStatus: UserGameStatus
|
||||
moderator: UserMeModerator
|
||||
userInfoApply: UserMeInfoApply
|
||||
|
||||
################
|
||||
# ArknightsUserMeModel End
|
||||
################
|
||||
|
||||
|
||||
|
||||
################
|
||||
# ArknightsPlayerInfoModel Start
|
||||
################
|
||||
|
||||
class PlayerSkinAsset(Struct):
|
||||
pass
|
||||
@ -480,3 +575,8 @@ class ArknightsPlayerInfoModel(Struct, omit_defaults=True, gc=False):
|
||||
manufactureFormulaInfoMap: dict[str, PlayerManufactureFormulaInfo]
|
||||
charAssets: list[PlayerCharAsset]
|
||||
skinAssets: list[PlayerSkinAsset]
|
||||
|
||||
|
||||
################
|
||||
# ArknightsPlayerInfoModel End
|
||||
################
|
||||
|
23
ArknightsUID/utils/resource/RESOURCE_PATH.py
Normal file
23
ArknightsUID/utils/resource/RESOURCE_PATH.py
Normal file
@ -0,0 +1,23 @@
|
||||
import sys
|
||||
|
||||
from gsuid_core.data_store import get_res_path
|
||||
|
||||
MAIN_PATH = get_res_path() / 'ArknightsUID'
|
||||
sys.path.append(str(MAIN_PATH))
|
||||
|
||||
CU_BG_PATH = MAIN_PATH / 'bg'
|
||||
CONFIG_PATH = MAIN_PATH / 'config.json'
|
||||
PLAYER_PATH = MAIN_PATH / 'players'
|
||||
RESOURCE_PATH = MAIN_PATH / 'resource'
|
||||
|
||||
def init_dir():
|
||||
for i in [
|
||||
MAIN_PATH,
|
||||
CU_BG_PATH,
|
||||
PLAYER_PATH,
|
||||
RESOURCE_PATH,
|
||||
]:
|
||||
i.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
init_dir()
|
11
ArknightsUID/utils/resource/download_all_resource.py
Normal file
11
ArknightsUID/utils/resource/download_all_resource.py
Normal file
@ -0,0 +1,11 @@
|
||||
import asyncio
|
||||
|
||||
from .download_from_cos import download_all_file_from_cos
|
||||
|
||||
|
||||
async def download_all_resource():
|
||||
ret = await asyncio.gather(download_all_file_from_cos())
|
||||
ret = [str(x) for x in ret if x]
|
||||
if ret:
|
||||
return '\n'.join(ret)
|
||||
return 'sr全部资源下载完成!'
|
101
ArknightsUID/utils/resource/download_from_cos.py
Normal file
101
ArknightsUID/utils/resource/download_from_cos.py
Normal file
@ -0,0 +1,101 @@
|
||||
import asyncio
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from aiohttp.client import ClientSession
|
||||
from gsuid_core.logger import logger
|
||||
from msgspec import json as msgjson
|
||||
|
||||
from .download_url import download_file
|
||||
from .RESOURCE_PATH import RESOURCE_PATH
|
||||
|
||||
with open(
|
||||
Path(__file__).parent / 'resource_map.json', encoding='UTF-8'
|
||||
) as f:
|
||||
resource_map = msgjson.decode(
|
||||
f.read(),
|
||||
type=dict[str, dict[str, dict[str, dict[str, int | str]]]],
|
||||
)
|
||||
|
||||
|
||||
async def download_all_file_from_cos():
|
||||
async def _download(tasks: list[asyncio.Task]):
|
||||
failed_list.extend(
|
||||
list(filter(lambda x: x is not None, await asyncio.gather(*tasks)))
|
||||
)
|
||||
tasks.clear()
|
||||
logger.info('[cos]下载完成!')
|
||||
|
||||
failed_list: list[tuple[str, str, str, str]] = []
|
||||
TASKS = []
|
||||
async with ClientSession() as sess:
|
||||
for res_type in ['resource']:
|
||||
logger.info('[cos]开始下载资源文件...')
|
||||
resource_type_list = [
|
||||
'character',
|
||||
'character_portrait',
|
||||
'character_preview',
|
||||
'consumable',
|
||||
'element',
|
||||
'light_cone',
|
||||
'relic',
|
||||
'skill',
|
||||
]
|
||||
for resource_type in resource_type_list:
|
||||
file_dict = resource_map[res_type][resource_type]
|
||||
logger.info(
|
||||
f'[cos]数据库[{resource_type}]中存在{len(file_dict)}个内容!'
|
||||
)
|
||||
temp_num = 0
|
||||
for file_name, file_info in file_dict.items():
|
||||
name = file_name
|
||||
size = file_info['size']
|
||||
url = file_info['url']
|
||||
if isinstance(url, int):
|
||||
continue
|
||||
path = Path(RESOURCE_PATH / resource_type / name)
|
||||
if path.exists():
|
||||
is_diff = size == os.stat(path).st_size
|
||||
else:
|
||||
is_diff = True
|
||||
if (
|
||||
not path.exists()
|
||||
or not os.stat(path).st_size
|
||||
or not is_diff
|
||||
):
|
||||
logger.info(f'[cos]开始下载[{resource_type}]_[{name}]...')
|
||||
temp_num += 1
|
||||
TASKS.append(
|
||||
asyncio.wait_for(
|
||||
download_file(
|
||||
url, res_type, resource_type, name, sess
|
||||
),
|
||||
timeout=60,
|
||||
)
|
||||
)
|
||||
# await download_file(url, FILE_TO_PATH[file], name)
|
||||
if len(TASKS) >= 10:
|
||||
await _download(TASKS)
|
||||
else:
|
||||
await _download(TASKS)
|
||||
if temp_num == 0:
|
||||
im = f'[cos]数据库[{resource_type}]无需下载!'
|
||||
else:
|
||||
im = f'[cos]数据库[{resource_type}]已下载{temp_num}个内容!'
|
||||
temp_num = 0
|
||||
logger.info(im)
|
||||
if failed_list:
|
||||
logger.info(f'[cos]开始重新下载失败的{len(failed_list)}个文件...')
|
||||
for url, res_type, resource_type, name in failed_list:
|
||||
TASKS.append(
|
||||
asyncio.wait_for(
|
||||
download_file(url, res_type, resource_type, name, sess),
|
||||
timeout=60,
|
||||
)
|
||||
)
|
||||
if len(TASKS) >= 10:
|
||||
await _download(TASKS)
|
||||
else:
|
||||
await _download(TASKS)
|
||||
if count := len(failed_list):
|
||||
logger.error(f'[cos]仍有{count}个文件未下载,请使用命令 `下载全部资源` 重新下载')
|
59
ArknightsUID/utils/resource/download_url.py
Normal file
59
ArknightsUID/utils/resource/download_url.py
Normal file
@ -0,0 +1,59 @@
|
||||
|
||||
import aiofiles
|
||||
from aiohttp.client import ClientSession
|
||||
from aiohttp.client_exceptions import ClientConnectorError
|
||||
from gsuid_core.logger import logger
|
||||
|
||||
from .RESOURCE_PATH import RESOURCE_PATH
|
||||
|
||||
PATHDICT = {
|
||||
'resource': RESOURCE_PATH,
|
||||
}
|
||||
|
||||
|
||||
async def download(
|
||||
url: str,
|
||||
res_type: str,
|
||||
resource_type: str,
|
||||
name: str,
|
||||
) -> tuple[str, str, str] | None:
|
||||
"""
|
||||
:说明:
|
||||
下载URL保存入目录
|
||||
:参数:
|
||||
* url: `str`
|
||||
资源下载地址。
|
||||
* res_type: `str`
|
||||
资源类型,`resource`或`wiki`。
|
||||
* resource_type: `str`
|
||||
资源文件夹名
|
||||
* name: `str`
|
||||
资源保存名称
|
||||
:返回(失败才会有返回值):
|
||||
url: `str`
|
||||
resource_type: `str`
|
||||
name: `str`
|
||||
"""
|
||||
async with ClientSession() as sess:
|
||||
return await download_file(url, res_type, resource_type, name, sess)
|
||||
|
||||
|
||||
async def download_file(
|
||||
url: str,
|
||||
res_type: str,
|
||||
resource_type: str,
|
||||
name: str,
|
||||
sess: ClientSession | None = None,
|
||||
) -> tuple[str, str, str] | None:
|
||||
if sess is None:
|
||||
sess = ClientSession()
|
||||
try:
|
||||
async with sess.get(url) as res:
|
||||
content = await res.read()
|
||||
except ClientConnectorError:
|
||||
logger.warning(f"[cos]{name}下载失败")
|
||||
return url, resource_type, name
|
||||
async with aiofiles.open(
|
||||
PATHDICT[res_type] / resource_type / name, "wb"
|
||||
) as f:
|
||||
await f.write(content)
|
0
__nest__.py
Normal file
0
__nest__.py
Normal file
Loading…
x
Reference in New Issue
Block a user