From c27a1c4fb8240250df1d5d899bbda34436fe956c Mon Sep 17 00:00:00 2001 From: hibiki <775757368@qq.com> Date: Wed, 26 May 2021 20:08:13 +0800 Subject: [PATCH] update --- plugins/__init__.py | 0 plugins/draw_card/__init__.py | 176 ++++-- plugins/draw_card/announcement.py | 13 +- plugins/draw_card/config.py | 253 ++++++-- plugins/draw_card/genshin_handle.py | 69 +-- plugins/draw_card/guardian_handle.py | 118 ++++ plugins/draw_card/init_card_pool.py | 11 + plugins/draw_card/pcr_handle.py | 91 +++ plugins/draw_card/pretty_handle.py | 71 +-- plugins/draw_card/prts_handle.py | 63 +- plugins/draw_card/rule.py | 36 ++ plugins/draw_card/update_game_info.py | 164 +++-- plugins/draw_card/util.py | 101 +++- .../query_resource_points/icon/111.png | Bin 23956 -> 0 bytes .../query_resource_points/icon/112.png | Bin 23177 -> 0 bytes .../query_resource_points/icon/114.png | Bin 20161 -> 0 bytes .../query_resource_points/icon/115.png | Bin 21839 -> 0 bytes .../query_resource_points/icon/116.png | Bin 23377 -> 0 bytes .../query_resource_points/icon/121.png | Bin 20203 -> 0 bytes .../query_resource_points/icon/122.png | Bin 21611 -> 0 bytes .../query_resource_points/icon/123.png | Bin 17510 -> 0 bytes .../query_resource_points/icon/124.png | Bin 21453 -> 0 bytes .../query_resource_points/icon/125.png | Bin 24226 -> 0 bytes .../query_resource_points/icon/126.png | Bin 22339 -> 0 bytes .../query_resource_points/icon/127.png | Bin 27100 -> 0 bytes .../query_resource_points/icon/128.png | Bin 27525 -> 0 bytes .../query_resource_points/icon/129.png | Bin 21473 -> 0 bytes .../query_resource_points/icon/130.png | Bin 17607 -> 0 bytes .../query_resource_points/icon/132.png | Bin 29366 -> 0 bytes .../query_resource_points/icon/133.png | Bin 26618 -> 0 bytes .../query_resource_points/icon/134.png | Bin 26676 -> 0 bytes .../query_resource_points/icon/135.png | Bin 31469 -> 0 bytes .../query_resource_points/icon/136.png | Bin 26483 -> 0 bytes .../query_resource_points/icon/137.png | Bin 25549 -> 0 bytes .../query_resource_points/icon/138.png | Bin 29812 -> 0 bytes .../query_resource_points/icon/139.png | Bin 20793 -> 0 bytes .../query_resource_points/icon/140.png | Bin 18752 -> 0 bytes .../query_resource_points/icon/142.png | Bin 23647 -> 0 bytes .../query_resource_points/icon/144.png | Bin 19866 -> 0 bytes .../query_resource_points/icon/146.png | Bin 21231 -> 0 bytes .../query_resource_points/icon/147.png | Bin 19475 -> 0 bytes .../query_resource_points/icon/148.png | Bin 21400 -> 0 bytes .../query_resource_points/icon/149.png | Bin 28009 -> 0 bytes .../genshin/query_resource_points/icon/15.png | Bin 24723 -> 0 bytes .../query_resource_points/icon/150.png | Bin 27860 -> 0 bytes .../query_resource_points/icon/151.png | Bin 25315 -> 0 bytes .../query_resource_points/icon/152.png | Bin 32068 -> 0 bytes .../query_resource_points/icon/153.png | Bin 23067 -> 0 bytes .../query_resource_points/icon/154.png | Bin 21943 -> 0 bytes .../query_resource_points/icon/155.png | Bin 28887 -> 0 bytes .../query_resource_points/icon/156.png | Bin 24912 -> 0 bytes .../query_resource_points/icon/157.png | Bin 31483 -> 0 bytes .../query_resource_points/icon/158.png | Bin 19410 -> 0 bytes .../query_resource_points/icon/159.png | Bin 24680 -> 0 bytes .../genshin/query_resource_points/icon/16.png | Bin 20382 -> 0 bytes .../query_resource_points/icon/160.png | Bin 21116 -> 0 bytes .../query_resource_points/icon/161.png | Bin 21170 -> 0 bytes .../query_resource_points/icon/162.png | Bin 25431 -> 0 bytes .../query_resource_points/icon/163.png | Bin 21500 -> 0 bytes .../query_resource_points/icon/164.png | Bin 21708 -> 0 bytes .../query_resource_points/icon/165.png | Bin 20070 -> 0 bytes .../query_resource_points/icon/166.png | Bin 22441 -> 0 bytes .../query_resource_points/icon/167.png | Bin 16488 -> 0 bytes .../query_resource_points/icon/168.png | Bin 17853 -> 0 bytes .../query_resource_points/icon/169.png | Bin 29410 -> 0 bytes .../genshin/query_resource_points/icon/17.png | Bin 26568 -> 0 bytes .../query_resource_points/icon/171.png | Bin 23311 -> 0 bytes .../query_resource_points/icon/172.png | Bin 19944 -> 0 bytes .../query_resource_points/icon/174.png | Bin 28702 -> 0 bytes .../query_resource_points/icon/175.png | Bin 24278 -> 0 bytes .../query_resource_points/icon/176.png | Bin 24961 -> 0 bytes .../query_resource_points/icon/177.png | Bin 27997 -> 0 bytes .../query_resource_points/icon/178.png | Bin 24200 -> 0 bytes .../query_resource_points/icon/179.png | Bin 26600 -> 0 bytes .../genshin/query_resource_points/icon/18.png | Bin 21841 -> 0 bytes .../query_resource_points/icon/180.png | Bin 27666 -> 0 bytes .../query_resource_points/icon/181.png | Bin 26594 -> 0 bytes .../genshin/query_resource_points/icon/19.png | Bin 28009 -> 0 bytes .../genshin/query_resource_points/icon/2.png | Bin 24617 -> 0 bytes .../genshin/query_resource_points/icon/20.png | Bin 28009 -> 0 bytes .../genshin/query_resource_points/icon/21.png | Bin 28009 -> 0 bytes .../genshin/query_resource_points/icon/22.png | Bin 17140 -> 0 bytes .../genshin/query_resource_points/icon/23.png | Bin 17058 -> 0 bytes .../genshin/query_resource_points/icon/24.png | Bin 17619 -> 0 bytes .../genshin/query_resource_points/icon/25.png | Bin 25571 -> 0 bytes .../genshin/query_resource_points/icon/26.png | Bin 31093 -> 0 bytes .../genshin/query_resource_points/icon/27.png | Bin 27860 -> 0 bytes .../genshin/query_resource_points/icon/28.png | Bin 27284 -> 0 bytes .../genshin/query_resource_points/icon/29.png | Bin 20917 -> 0 bytes .../genshin/query_resource_points/icon/3.png | Bin 23164 -> 0 bytes .../genshin/query_resource_points/icon/30.png | Bin 18306 -> 0 bytes .../genshin/query_resource_points/icon/31.png | Bin 21995 -> 0 bytes .../genshin/query_resource_points/icon/32.png | Bin 21764 -> 0 bytes .../genshin/query_resource_points/icon/33.png | Bin 20329 -> 0 bytes .../genshin/query_resource_points/icon/34.png | Bin 19727 -> 0 bytes .../genshin/query_resource_points/icon/35.png | Bin 18412 -> 0 bytes .../genshin/query_resource_points/icon/36.png | Bin 25846 -> 0 bytes .../genshin/query_resource_points/icon/37.png | Bin 21969 -> 0 bytes .../genshin/query_resource_points/icon/38.png | Bin 21577 -> 0 bytes .../genshin/query_resource_points/icon/39.png | Bin 23830 -> 0 bytes .../genshin/query_resource_points/icon/40.png | Bin 22449 -> 0 bytes .../genshin/query_resource_points/icon/41.png | Bin 23785 -> 0 bytes .../genshin/query_resource_points/icon/42.png | Bin 24142 -> 0 bytes .../genshin/query_resource_points/icon/43.png | Bin 19372 -> 0 bytes .../genshin/query_resource_points/icon/44.png | Bin 27154 -> 0 bytes .../genshin/query_resource_points/icon/45.png | Bin 25293 -> 0 bytes .../genshin/query_resource_points/icon/46.png | Bin 27547 -> 0 bytes .../genshin/query_resource_points/icon/47.png | Bin 22056 -> 0 bytes .../genshin/query_resource_points/icon/48.png | Bin 18656 -> 0 bytes .../genshin/query_resource_points/icon/49.png | Bin 23691 -> 0 bytes .../genshin/query_resource_points/icon/5.png | Bin 26439 -> 0 bytes .../genshin/query_resource_points/icon/52.png | Bin 18334 -> 0 bytes .../genshin/query_resource_points/icon/53.png | Bin 26636 -> 0 bytes .../genshin/query_resource_points/icon/54.png | Bin 24864 -> 0 bytes .../genshin/query_resource_points/icon/55.png | Bin 24046 -> 0 bytes .../genshin/query_resource_points/icon/56.png | Bin 25086 -> 0 bytes .../genshin/query_resource_points/icon/57.png | Bin 26095 -> 0 bytes .../genshin/query_resource_points/icon/58.png | Bin 22834 -> 0 bytes .../genshin/query_resource_points/icon/59.png | Bin 17348 -> 0 bytes .../genshin/query_resource_points/icon/6.png | Bin 32429 -> 0 bytes .../genshin/query_resource_points/icon/61.png | Bin 25371 -> 0 bytes .../genshin/query_resource_points/icon/62.png | Bin 24351 -> 0 bytes .../genshin/query_resource_points/icon/63.png | Bin 17806 -> 0 bytes .../genshin/query_resource_points/icon/64.png | Bin 12631 -> 0 bytes .../genshin/query_resource_points/icon/65.png | Bin 23227 -> 0 bytes .../genshin/query_resource_points/icon/66.png | Bin 20373 -> 0 bytes .../genshin/query_resource_points/icon/67.png | Bin 31717 -> 0 bytes .../genshin/query_resource_points/icon/68.png | Bin 24192 -> 0 bytes .../genshin/query_resource_points/icon/69.png | Bin 26568 -> 0 bytes .../genshin/query_resource_points/icon/70.png | Bin 23948 -> 0 bytes .../genshin/query_resource_points/icon/71.png | Bin 16268 -> 0 bytes .../genshin/query_resource_points/icon/72.png | Bin 26041 -> 0 bytes .../genshin/query_resource_points/icon/73.png | Bin 21085 -> 0 bytes .../genshin/query_resource_points/icon/74.png | Bin 15245 -> 0 bytes .../genshin/query_resource_points/icon/75.png | Bin 24965 -> 0 bytes .../genshin/query_resource_points/icon/76.png | Bin 24074 -> 0 bytes .../genshin/query_resource_points/icon/77.png | Bin 19900 -> 0 bytes .../genshin/query_resource_points/icon/78.png | Bin 23893 -> 0 bytes .../genshin/query_resource_points/icon/79.png | Bin 24046 -> 0 bytes .../genshin/query_resource_points/icon/8.png | Bin 21410 -> 0 bytes .../genshin/query_resource_points/icon/80.png | Bin 22303 -> 0 bytes .../genshin/query_resource_points/icon/81.png | Bin 21792 -> 0 bytes .../genshin/query_resource_points/icon/82.png | Bin 22714 -> 0 bytes .../genshin/query_resource_points/icon/83.png | Bin 15245 -> 0 bytes .../genshin/query_resource_points/icon/85.png | Bin 16872 -> 0 bytes .../genshin/query_resource_points/icon/87.png | Bin 27304 -> 0 bytes .../genshin/query_resource_points/icon/9.png | Bin 21371 -> 0 bytes .../genshin/query_resource_points/icon/90.png | Bin 22314 -> 0 bytes .../genshin/query_resource_points/icon/91.png | Bin 23939 -> 0 bytes .../genshin/query_resource_points/icon/92.png | Bin 21856 -> 0 bytes .../genshin/query_resource_points/icon/93.png | Bin 18326 -> 0 bytes .../genshin/query_resource_points/icon/94.png | Bin 22855 -> 0 bytes plugins/help/config.py | 8 +- plugins/help/data_source.py | 21 +- plugins/open_cases/utils.py | 3 +- plugins/quotations.py | 19 +- plugins/send_setu/data_source.py | 2 +- plugins/server_ip.py | 22 +- plugins/shop/__init__.py | 1 - plugins/test.py | 36 ++ resources/txt/yulu.txt | 563 ------------------ util/utils.py | 13 - 162 files changed, 922 insertions(+), 932 deletions(-) create mode 100644 plugins/__init__.py create mode 100644 plugins/draw_card/guardian_handle.py create mode 100644 plugins/draw_card/pcr_handle.py create mode 100644 plugins/draw_card/rule.py create mode 100644 plugins/test.py delete mode 100644 resources/txt/yulu.txt diff --git a/plugins/__init__.py b/plugins/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/plugins/draw_card/__init__.py b/plugins/draw_card/__init__.py index 4d8d95c7..52fa2299 100644 --- a/plugins/draw_card/__init__.py +++ b/plugins/draw_card/__init__.py @@ -2,26 +2,45 @@ from nonebot import on_regex, on_keyword from nonebot.adapters.cqhttp import Bot, MessageEvent from nonebot.permission import SUPERUSER from nonebot.typing import T_State +from services.log import logger +from util.utils import scheduler +import re from .genshin_handle import genshin_draw, update_genshin_info, reset_count from .prts_handle import update_prts_info, prts_draw, reload_pool from .pretty_handle import update_pretty_info, pretty_draw +from .guardian_handle import update_guardian_info, guardian_draw +from .pcr_handle import update_pcr_info, pcr_draw from .update_game_info import update_info -from util.utils import is_number, scheduler -from services.log import logger -import re +from .util import check_num +from .rule import is_switch +from .config import PRTS_FLAG, PRETTY_FLAG, GUARDIAN_FLAG, GENSHIN_FLAG, PCR_FLAG -prts = on_regex(r'.*?方舟[1-9|一][0-9]{0,2}[抽|井]', priority=5, block=True) + +prts = on_regex(r'.*?方舟[1-9|一][0-9]{0,2}[抽|井]', rule=is_switch('prts'), priority=5, block=True) prts_update = on_keyword({'更新方舟信息', '更新明日方舟信息'}, permission=SUPERUSER, priority=1, block=True) prts_reload = on_keyword({'重载方舟卡池'}, priority=1, block=True) -genshin = on_regex('.*?原神[1-9|一][0-9]{0,2}[抽|井]', priority=5, block=True) +genshin = on_regex('.*?原神[1-9|一][0-9]{0,2}[抽|井]', rule=is_switch('genshin'), priority=5, block=True) genshin_reset = on_keyword({'重置原神抽卡'}, priority=1, block=True) genshin_update = on_keyword({'更新原神信息'}, permission=SUPERUSER, priority=1, block=True) -pretty = on_regex('.*?马娘卡?[1-9|一][0-9]{0,2}[抽|井]', priority=5, block=True) +pretty = on_regex('.*?马娘卡?[1-9|一][0-9]{0,2}[抽|井]', rule=is_switch('pretty'), priority=5, block=True) pretty_update = on_keyword({'更新马娘信息', '更新赛马娘信息'}, permission=SUPERUSER, priority=1, block=True) +guardian = on_regex('.*?坎公骑冠剑武?器?[1-9|一][0-9]{0,2}[抽|井]', rule=is_switch('guardian'), priority=5, block=True) +guardian_update = on_keyword({'更新坎公骑冠剑信息'}, permission=SUPERUSER, priority=1, block=True) + +pcr = on_regex('.*?(pcr|公主连结|公主连接|公主链接)[1-9|一][0-9]{0,2}[抽|井]', rule=is_switch('pcr'), priority=5, block=True) +pcr_update = on_keyword({'更新pcr信息', '更新公主连结信息'}, permission=SUPERUSER, priority=1, block=True) + +test = on_keyword({'test'}, permission=SUPERUSER, priority=1, block=True) + + +@test.handle() +async def _(bot: Bot, event: MessageEvent, state: T_State): + await update_pcr_info() + @prts.handle() async def _(bot: Bot, event: MessageEvent, state: T_State): @@ -30,22 +49,13 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): num = 300 else: rmsg = re.search(r'.*?方舟(.*)抽', msg) - if rmsg and is_number(rmsg.group(1)): - try: - num = int(rmsg.group(1)) - except ValueError: - await prts.finish('必!须!是!数!字!', at_sender=True) - if num > 300: - await prts.finish('一井都满不足不了你嘛!快爬开!', at_sender=True) - if num < 1: - await prts.finish('虚空抽卡???', at_sender=True) + if rmsg: + num, flag = check_num(rmsg.group(1), 300) + if not flag: + await prts.finish(num, at_sender=True) else: return - # print(num) - await prts.send(await prts_draw(num), at_sender=True) - logger.info( - f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'})" - f" 方舟{num}抽") + await prts.send(await prts_draw(int(num)), at_sender=True) @prts_reload.handle() @@ -61,21 +71,13 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): num = 180 else: rmsg = re.search(r'.*?原神(.*)抽', msg) - if rmsg and is_number(rmsg.group(1)): - try: - num = int(rmsg.group(1)) - except ValueError: - await genshin.finish('必!须!是!数!字!', at_sender=True) - if num > 300: - await genshin.finish('一井都满不足不了你嘛!快爬开!', at_sender=True) - if num < 1: - await genshin.finish('虚空抽卡???', at_sender=True) + if rmsg: + num, flag = check_num(rmsg.group(1), 180) + if not flag: + await genshin.finish(num, at_sender=True) else: return - await genshin.send(await genshin_draw(event.user_id, num), at_sender=True) - logger.info( - f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'})" - f" 原神{num}抽") + await genshin.send(await genshin_draw(event.user_id, int(num)), at_sender=True) @genshin_reset.handle() @@ -87,7 +89,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): @pretty.handle() async def _(bot: Bot, event: MessageEvent, state: T_State): msg = str(event.get_message()).strip() - if msg in ['赛马娘一井', '赛马娘1井', '马娘一井', '马娘1井', '赛马娘卡一井', '赛马娘卡1井', '马娘卡一井', '马娘卡1井']: + if msg.find('1井') != -1 or msg.find('一井') != -1: num = 200 if msg.find("卡") == -1: pool_name = 'horse' @@ -102,21 +104,51 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): pool_name = 'card' else: pool_name = 'horse' - if is_number(num): - try: - num = int(num) - except ValueError: - await genshin.finish('必!须!是!数!字!', at_sender=True) - if num > 200: - await genshin.finish('一井都满不足不了你嘛!快爬开!', at_sender=True) - if num < 1: - await genshin.finish('虚空抽卡???', at_sender=True) - else: - return - await pretty.send(await pretty_draw(num, pool_name), at_sender=True) - logger.info( - f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'})" - f" 赛马娘{num}抽") + num, flag = check_num(num, 200) + if not flag: + await pretty.finish(num, at_sender=True) + else: + return + await pretty.send(await pretty_draw(int(num), pool_name), at_sender=True) + + +@guardian.handle() +async def _(bot: Bot, event: MessageEvent, state: T_State): + msg = str(event.get_message()).strip() + pool_name = 'char' + if msg.find('1井') != -1 or msg.find('一井') != -1: + num = 300 + if msg.find('武器') != -1: + pool_name = 'arms' + else: + rmsg = re.search(r'.*?坎公骑冠剑(.*)抽', msg) + if rmsg: + num = rmsg.group(1) + if num.find('武器') != -1: + pool_name = 'arms' + num = num.replace('武器', '') + num, flag = check_num(num, 300) + if not flag: + await guardian.finish(num, at_sender=True) + else: + return + await guardian.send(await guardian_draw(int(num), pool_name), at_sender=True) + + +@pcr.handle() +async def _(bot: Bot, event: MessageEvent, state: T_State): + msg = str(event.get_message()).strip() + if msg.find('1井') != -1 or msg.find('一井') != -1: + num = 300 + else: + rmsg = re.search(r'.*?(pcr|公主连结)(.*)[抽|井]', msg) + if rmsg: + num, flag = check_num(rmsg.group(2), 300) + if not flag: + await pcr.finish(num, at_sender=True) + else: + return + await pcr.send(await pcr_draw(int(num)), at_sender=True) @prts_update.handle() @@ -138,6 +170,18 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): await genshin_update.finish('更新完成!') +@guardian_update.handle() +async def _(bot: Bot, event: MessageEvent, state: T_State): + await update_guardian_info() + await genshin_update.finish('更新完成!') + + +@pcr_update.handle() +async def _(bot: Bot, event: MessageEvent, state: T_State): + await update_pcr_info() + await genshin_update.finish('更新完成!') + + # 更新资源 @scheduler.scheduled_job( 'cron', @@ -146,20 +190,30 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): ) async def _(): try: - await update_prts_info() - logger.info('自动更新明日方舟信息') + if PRTS_FLAG: + await update_prts_info() except Exception as e: - logger.error(f'自动更新明日方舟信息出错 e:{e}') + logger.error(f'draw_card: 更新 明日方舟 失败 e:{e}') try: - await update_genshin_info() - logger.info('自动更新原神信息') + if GENSHIN_FLAG: + await update_genshin_info() except Exception as e: - logger.error(f'自动更新原神信息出错 e:{e}') + logger.error(f'draw_card: 更新 原神 失败 e:{e}') try: - await update_pretty_info() - logger.info('自动更新赛马娘信息') + if PRETTY_FLAG: + await update_pretty_info() except Exception as e: - logger.error(f'自动更新赛马娘信息出错 e:{e}') + logger.error(f'draw_card: 更新 赛马娘 失败 e:{e}') + try: + if GUARDIAN_FLAG: + await update_guardian_info() + except Exception as e: + logger.error(f'draw_card: 更新 坎公骑冠剑 失败 e:{e}') + try: + if PCR_FLAG: + await update_pcr_info() + except Exception as e: + logger.error(f'draw_card: 更新 公主连结 失败 e:{e}') # 每天四点重载up卡池 @@ -169,6 +223,6 @@ async def _(): minute=1, ) async def _(): - await reload_pool() - - + if PRTS_FLAG: + await reload_pool() + logger.info(f'draw_card: 04: 01 重载方舟卡池') diff --git a/plugins/draw_card/announcement.py b/plugins/draw_card/announcement.py index 734a58a9..41ab5082 100644 --- a/plugins/draw_card/announcement.py +++ b/plugins/draw_card/announcement.py @@ -2,16 +2,17 @@ import aiohttp from bs4 import BeautifulSoup import re from datetime import datetime +from .config import DRAW_PATH +from util.utils import get_local_proxy from pathlib import Path -from configs.path_config import DRAW_PATH -from util.user_agent import get_user_agent - try: import ujson as json except ModuleNotFoundError: import json -up_char_file = Path(DRAW_PATH) / "draw_card_up" / "prts_up_char.json" +headers = {'User-Agent': '"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)"'} + +up_char_file = Path(DRAW_PATH + "/draw_card_up/prts_up_char.json") prts_url = "https://wiki.biligame.com/arknights/%E6%96%B0%E9%97%BB%E5%85%AC%E5%91%8A" @@ -29,7 +30,7 @@ class PrtsAnnouncement: @staticmethod async def get_announcement_text(): - async with aiohttp.ClientSession(headers=get_user_agent()) as session: + async with aiohttp.ClientSession(headers=headers) as session: async with session.get(prts_url, timeout=7) as res: soup = BeautifulSoup(await res.text(), 'lxml') trs = soup.find('table').find('tbody').find_all('tr') @@ -38,7 +39,7 @@ class PrtsAnnouncement: if a.text.find('寻访') != -1: url = a.get('href') break - async with session.get(f'https://wiki.biligame.com/{url}', timeout=7) as res: + async with session.get(f'https://wiki.biligame.com/{url}', proxy=get_local_proxy(), timeout=7) as res: return await res.text(), a.text[:-4] @staticmethod diff --git a/plugins/draw_card/config.py b/plugins/draw_card/config.py index 63fe0a85..619248e5 100644 --- a/plugins/draw_card/config.py +++ b/plugins/draw_card/config.py @@ -1,10 +1,23 @@ import nonebot from pathlib import Path +from configs.path_config import DRAW_PATH try: import ujson as json except ModuleNotFoundError: import json +DRAW_PATH = DRAW_PATH + +_draw_config = Path(rf"{DRAW_PATH}/draw_card_config/draw_card_config.json") + + +# 开关 +PRTS_FLAG = False if str(nonebot.get_driver().config.prts_flag).lower() == 'false' else True +GENSHIN_FLAG = False if str(nonebot.get_driver().config.genshin_flag).lower() == 'false' else True +PRETTY_FLAG = False if str(nonebot.get_driver().config.pretty_flag).lower() == 'false' else True +GUARDIAN_FLAG = False if str(nonebot.get_driver().config.guardian_flag).lower() == 'false' else True +PCR_FLAG = False if str(nonebot.get_driver().config.PCR_flag).lower() == 'false' else True + # 方舟概率 PRTS_SIX_P = 0.02 PRTS_FIVE_P = 0.08 @@ -15,88 +28,206 @@ PRTS_THREE_P = 0.42 GENSHIN_FIVE_P = 0.006 GENSHIN_FOUR_P = 0.051 GENSHIN_THREE_P = 0.43 -GENSHIN_G_FOUR_P = 0.13 +# 保底概率 GENSHIN_G_FIVE_P = 0.016 +GENSHIN_G_FOUR_P = 0.13 +# 72抽后增加的概率 I72_ADD = 0.0585 # 赛马娘概率 -PRETTY_THREE = 0.03 -PRETTY_TWO = 0.18 -PRETTY_ONE = 0.79 +PRETTY_THREE_P = 0.03 +PRETTY_TWO_P = 0.18 +PRETTY_ONE_P = 0.79 + +# 坎公骑冠剑 +# 角色概率 +GUARDIAN_THREE_CHAR_P = 0.0275 +GUARDIAN_TWO_CHAR_P = 0.19 +GUARDIAN_ONE_CHAR_P = 0.7825 +# UP角色 +GUARDIAN_THREE_CHAR_UP_P = 0.01375 +GUARDIAN_THREE_CHAR_OTHER_P = 0.01375 +# 武器概率 +GUARDIAN_EXCLUSIVE_ARMS_P = 0.03 +GUARDIAN_FIVE_ARMS_P = 0.03 +GUARDIAN_FOUR_ARMS_P = 0.09 +GUARDIAN_THREE_ARMS_P = 0.27 +GUARDIAN_TWO_ARMS_P = 0.58 +# UP武器 +GUARDIAN_EXCLUSIVE_ARMS_UP_P = 0.01 +GUARDIAN_EXCLUSIVE_ARMS_OTHER_P = 0.02 + +# PCR +PCR_THREE_P = 0.025 +PCR_TWO_P = 0.18 +PCR_ONE_P = 0.795 +# 保底 +PCR_G_THREE_P = 0.025 +PCR_G_TWO_P = 0.975 path_dict = { 'genshin': '原神', 'prts': '明日方舟', 'pretty': '赛马娘', + 'guardian': '坎公骑冠剑', + 'pcr': '公主连结', } - -_draw_config = Path() / "data" / "draw_card" / "draw_card_config" / "draw_card_config.json" - - driver: nonebot.Driver = nonebot.get_driver() +config_default_data = { + + 'path_dict': { + 'genshin': '原神', + 'prts': '明日方舟', + 'pretty': '赛马娘', + 'guardian': '坎公骑冠剑', + 'PCR': '公主连结', + }, + + 'prts': { + 'PRTS_SIX_P': 0.02, + 'PRTS_FIVE_P': 0.08, + 'PRTS_FOUR_P': 0.48, + 'PRTS_THREE_P': 0.42, + }, + + 'genshin': { + 'GENSHIN_FIVE_P': 0.006, + 'GENSHIN_FOUR_P': 0.051, + 'GENSHIN_THREE_P': 0.43, + 'GENSHIN_G_FIVE_P': 0.13, + 'GENSHIN_G_FOUR_P': 0.016, + 'I72_ADD': 0.0585, + }, + + 'pretty': { + 'PRETTY_THREE_P': 0.03, + 'PRETTY_TWO_P': 0.18, + 'PRETTY_ONE_P': 0.79, + }, + + 'guardian': { + 'GUARDIAN_THREE_CHAR_P': 0.0275, + 'GUARDIAN_TWO_CHAR_P': 0.19, + 'GUARDIAN_ONE_CHAR_P': 0.7825, + + 'GUARDIAN_THREE_CHAR_UP_P': 0.01375, + 'GUARDIAN_THREE_CHAR_OTHER_P': 0.01375, + + 'GUARDIAN_EXCLUSIVE_ARMS_P': 0.03, + 'GUARDIAN_FIVE_ARMS_P': 0.03, + 'GUARDIAN_FOUR_ARMS_P': 0.09, + 'GUARDIAN_THREE_ARMS_P': 0.27, + 'GUARDIAN_TWO_ARMS_P': 0.58, + + 'GUARDIAN_EXCLUSIVE_ARMS_UP_P': 0.01, + 'GUARDIAN_EXCLUSIVE_ARMS_OTHER_P': 0.02, + }, + + 'pcr': { + 'PCR_THREE_P': 0.025, + 'PCR_TWO_P': 0.18, + 'PCR_ONE_P': 0.795, + }, +} + @driver.on_startup def check_config(): - global PRTS_SIX_P, PRTS_FOUR_P, PRTS_FIVE_P, PRTS_THREE_P, GENSHIN_G_FIVE_P, \ - GENSHIN_G_FOUR_P, GENSHIN_FOUR_P, GENSHIN_FIVE_P, I72_ADD, path_dict, PRETTY_THREE, \ - PRETTY_ONE, PRETTY_TWO, GENSHIN_THREE_P - if _draw_config.exists(): + global PRTS_SIX_P, PRTS_FOUR_P, PRTS_FIVE_P, PRTS_THREE_P, GENSHIN_G_FIVE_P, config_default_data, \ + GENSHIN_G_FOUR_P, GENSHIN_FOUR_P, GENSHIN_FIVE_P, I72_ADD, path_dict, PRETTY_THREE_P, \ + PRETTY_ONE_P, PRETTY_TWO_P, GENSHIN_THREE_P, GUARDIAN_THREE_CHAR_P, GUARDIAN_TWO_CHAR_P, GUARDIAN_ONE_CHAR_P, \ + GUARDIAN_THREE_CHAR_UP_P, GUARDIAN_THREE_CHAR_OTHER_P, GUARDIAN_EXCLUSIVE_ARMS_P, GUARDIAN_FIVE_ARMS_P, \ + GUARDIAN_FOUR_ARMS_P, GUARDIAN_THREE_ARMS_P, GUARDIAN_TWO_ARMS_P, GENSHIN_FLAG, PRTS_FLAG, \ + PRETTY_FLAG, GUARDIAN_FLAG, GUARDIAN_EXCLUSIVE_ARMS_UP_P, GUARDIAN_EXCLUSIVE_ARMS_OTHER_P, DRAW_PATH, \ + PCR_THREE_P, PCR_TWO_P, PCR_ONE_P + _draw_config.parent.mkdir(parents=True, exist_ok=True) + try: data = json.load(open(_draw_config, 'r', encoding='utf8')) - PRTS_SIX_P = float(data['prts']['six']) - PRTS_FIVE_P = float(data['prts']['five']) - PRTS_FOUR_P = float(data['prts']['four']) - PRTS_THREE_P = float(data['prts']['three']) - - GENSHIN_FIVE_P = float(data['genshin']['five_char']) - GENSHIN_FOUR_P = float(data['genshin']['four_char']) - GENSHIN_THREE_P = float(data['genshin']['three_char']) - GENSHIN_G_FIVE_P = float(data['genshin']['five_weapon']) - GENSHIN_G_FOUR_P = float(data['genshin']['four_weapon']) - I72_ADD = float(data['genshin']['72_add']) - - PRETTY_THREE = float(data['pretty']['three']) - PRETTY_TWO = float(data['pretty']['two']) - PRETTY_ONE = float(data['pretty']['one']) - - path_dict = data['path_dict'] - else: + except (FileNotFoundError, ValueError): _draw_config.parent.mkdir(parents=True, exist_ok=True) - config_dict = { - 'path_dict': { - 'genshin': '原神', - 'prts': '明日方舟', - 'pretty': '赛马娘', - }, - - 'prts': { - 'six': 0.02, - 'five': 0.08, - 'four': 0.48, - 'three': 0.42, - }, - - 'genshin': { - 'five_char': 0.006, - 'four_char': 0.051, - 'three_char': 0.43, - 'five_weapon': 0.13, - 'four_weapon': 0.016, - '72_add': 0.0585, - }, - - 'pretty': { - 'three': 0.03, - 'two': 0.18, - 'one': 0.79, - } - } - json.dump(config_dict, open(_draw_config, 'w', encoding='utf8'), indent=4, ensure_ascii=False) - + json.dump(config_default_data, open(_draw_config, 'w', encoding='utf8'), indent=4, ensure_ascii=False) + print('draw_card:配置文件不存在或格式错误,已重新生成配置文件.....') + else: + try: + PRTS_SIX_P = float(data['prts']['PRTS_SIX_P']) + PRTS_FIVE_P = float(data['prts']['PRTS_FIVE_P']) + PRTS_FOUR_P = float(data['prts']['PRTS_FOUR_P']) + PRTS_THREE_P = float(data['prts']['PRTS_THREE_P']) + except KeyError: + data['prts'] = {} + data['prts']['PRTS_SIX_P'] = config_default_data['prts']['PRTS_SIX_P'] + data['prts']['PRTS_FIVE_P'] = config_default_data['prts']['PRTS_FIVE_P'] + data['prts']['PRTS_FOUR_P'] = config_default_data['prts']['PRTS_FOUR_P'] + data['prts']['PRTS_THREE_P'] = config_default_data['prts']['PRTS_THREE_P'] + try: + GENSHIN_FIVE_P = float(data['genshin']['GENSHIN_FIVE_P']) + GENSHIN_FOUR_P = float(data['genshin']['GENSHIN_FOUR_P']) + GENSHIN_THREE_P = float(data['genshin']['GENSHIN_THREE_P']) + GENSHIN_G_FIVE_P = float(data['genshin']['GENSHIN_G_FIVE_P']) + GENSHIN_G_FOUR_P = float(data['genshin']['GENSHIN_G_FOUR_P']) + I72_ADD = float(data['genshin']['I72_ADD']) + except KeyError: + data['genshin'] = {} + data['genshin']['GENSHIN_FIVE_P'] = config_default_data['genshin']['GENSHIN_FIVE_P'] + data['genshin']['GENSHIN_FOUR_P'] = config_default_data['genshin']['GENSHIN_FOUR_P'] + data['genshin']['GENSHIN_THREE_P'] = config_default_data['genshin']['GENSHIN_THREE_P'] + data['genshin']['GENSHIN_G_FIVE_P'] = config_default_data['genshin']['GENSHIN_G_FIVE_P'] + data['genshin']['GENSHIN_G_FOUR_P'] = config_default_data['genshin']['GENSHIN_G_FOUR_P'] + data['genshin']['I72_ADD'] = config_default_data['genshin']['I72_ADD'] + try: + PRETTY_THREE_P = float(data['pretty']['PRETTY_THREE_P']) + PRETTY_TWO_P = float(data['pretty']['PRETTY_TWO_P']) + PRETTY_ONE_P = float(data['pretty']['PRETTY_ONE_P']) + except KeyError: + data['pretty'] = {} + data['pretty']['PRETTY_THREE_P'] = config_default_data['pretty']['PRETTY_THREE_P'] + data['pretty']['PRETTY_TWO_P'] = config_default_data['pretty']['PRETTY_TWO_P'] + data['pretty']['PRETTY_ONE_P'] = config_default_data['pretty']['PRETTY_ONE_P'] + + try: + GUARDIAN_THREE_CHAR_P = float(data['guardian']['GUARDIAN_THREE_CHAR_P']) + GUARDIAN_TWO_CHAR_P = float(data['guardian']['GUARDIAN_TWO_CHAR_P']) + GUARDIAN_ONE_CHAR_P = float(data['guardian']['GUARDIAN_ONE_CHAR_P']) + GUARDIAN_THREE_CHAR_UP_P = float(data['guardian']['GUARDIAN_THREE_CHAR_UP_P']) + GUARDIAN_THREE_CHAR_OTHER_P = float(data['guardian']['GUARDIAN_THREE_CHAR_OTHER_P']) + GUARDIAN_EXCLUSIVE_ARMS_P = float(data['guardian']['GUARDIAN_EXCLUSIVE_ARMS_P']) + GUARDIAN_FIVE_ARMS_P = float(data['guardian']['GUARDIAN_FIVE_ARMS_P']) + GUARDIAN_FOUR_ARMS_P = float(data['guardian']['GUARDIAN_FOUR_ARMS_P']) + GUARDIAN_THREE_ARMS_P = float(data['guardian']['GUARDIAN_THREE_ARMS_P']) + GUARDIAN_TWO_ARMS_P = float(data['guardian']['GUARDIAN_TWO_ARMS_P']) + GUARDIAN_EXCLUSIVE_ARMS_UP_P = float(data['guardian']['GUARDIAN_EXCLUSIVE_ARMS_UP_P']) + GUARDIAN_EXCLUSIVE_ARMS_OTHER_P = float(data['guardian']['GUARDIAN_EXCLUSIVE_ARMS_OTHER_P']) + except KeyError: + data['guardian'] = {} + data['guardian']['GUARDIAN_THREE_CHAR_P'] = config_default_data['guardian']['GUARDIAN_THREE_CHAR_P'] + data['guardian']['GUARDIAN_TWO_CHAR_P'] = config_default_data['guardian']['GUARDIAN_TWO_CHAR_P'] + data['guardian']['GUARDIAN_ONE_CHAR_P'] = config_default_data['guardian']['GUARDIAN_ONE_CHAR_P'] + data['guardian']['GUARDIAN_THREE_CHAR_UP_P'] = config_default_data['guardian']['GUARDIAN_THREE_CHAR_UP_P'] + data['guardian']['GUARDIAN_THREE_CHAR_OTHER_P'] = config_default_data['guardian']['GUARDIAN_THREE_CHAR_OTHER_P'] + data['guardian']['GUARDIAN_EXCLUSIVE_ARMS_P'] = config_default_data['guardian']['GUARDIAN_EXCLUSIVE_ARMS_P'] + data['guardian']['GUARDIAN_FIVE_ARMS_P'] = config_default_data['guardian']['GUARDIAN_FIVE_ARMS_P'] + data['guardian']['GUARDIAN_FOUR_ARMS_P'] = config_default_data['guardian']['GUARDIAN_FOUR_ARMS_P'] + data['guardian']['GUARDIAN_THREE_ARMS_P'] = config_default_data['guardian']['GUARDIAN_THREE_ARMS_P'] + data['guardian']['GUARDIAN_TWO_ARMS_P'] = config_default_data['guardian']['GUARDIAN_TWO_ARMS_P'] + data['guardian']['GUARDIAN_EXCLUSIVE_ARMS_UP_P'] = config_default_data['guardian']['GUARDIAN_EXCLUSIVE_ARMS_UP_P'] + data['guardian']['GUARDIAN_EXCLUSIVE_ARMS_OTHER_P'] = config_default_data['guardian']['GUARDIAN_EXCLUSIVE_ARMS_OTHER_P'] + + try: + PCR_THREE_P = float(data['pcr']['PCR_THREE_P']) + PCR_TWO_P = float(data['pcr']['PCR_TWO_P']) + PCR_ONE_P = float(data['pcr']['PCR_ONE_P']) + except KeyError: + data['pcr'] = {} + data['pcr']['PCR_THREE_P'] = config_default_data['pcr']['PCR_THREE_P'] + data['pcr']['PCR_TWO_P'] = config_default_data['pcr']['PCR_TWO_P'] + data['pcr']['PCR_ONE_P'] = config_default_data['pcr']['PCR_ONE_P'] + + json.dump(data, open(_draw_config, 'w', encoding='utf8'), indent=4, ensure_ascii=False) diff --git a/plugins/draw_card/genshin_handle.py b/plugins/draw_card/genshin_handle.py index 07954ad9..fe6b8735 100644 --- a/plugins/draw_card/genshin_handle.py +++ b/plugins/draw_card/genshin_handle.py @@ -1,14 +1,14 @@ import os +from util.init_result import image import nonebot import random from .update_game_info import update_info -from .util import generate_img, init_star_rst, BaseData, set_list -from .config import GENSHIN_FIVE_P, GENSHIN_FOUR_P, GENSHIN_G_FIVE_P, GENSHIN_THREE_P, I72_ADD +from .util import generate_img, init_star_rst, BaseData, set_list, get_star +from .config import GENSHIN_FIVE_P, GENSHIN_FOUR_P, GENSHIN_G_FIVE_P, GENSHIN_G_FOUR_P, GENSHIN_THREE_P, I72_ADD, \ + DRAW_PATH, GENSHIN_FLAG from dataclasses import dataclass from .init_card_pool import init_game_pool -from configs.path_config import DRAW_PATH -from util.init_result import image try: import ujson as json except ModuleNotFoundError: @@ -21,7 +21,7 @@ genshin_count = {} genshin_pl_count = {} ALL_CHAR = [] -ALL_ARM = [] +ALL_ARMS = [] @dataclass @@ -32,28 +32,28 @@ class GenshinChar(BaseData): async def genshin_draw(user_id: int, count: int): # 0 1 2 cnlist = ['★★★★★', '★★★★', '★★★'] - genshin_list, five_list, five_olist, five_dict, star_list = _format_card_information(count, user_id) - rst = init_star_rst(star_list, cnlist, five_list, five_olist) - print(five_list) + char_list, five_list, five_index_list, char_dict, star_list = _format_card_information(count, user_id) + rst = init_star_rst(star_list, cnlist, five_list, five_index_list) temp = '' if count > 90: - genshin_list = set_list(genshin_list) - return image(b64=await generate_img(genshin_list, 'genshin', star_list)) + '\n' + rst[:-1] + \ + char_list = set_list(char_list) + return image(b64=await generate_img(char_list, 'genshin', star_list)) + '\n' + rst[:-1] + \ temp[:-1] + f'\n距离保底发还剩 {90 - genshin_count[user_id] if genshin_count.get(user_id) else "^"} 抽' \ + "\n【五星:0.6%,四星:5.1%\n第72抽开始五星概率每抽加0.585%】" async def update_genshin_info(): - global ALL_CHAR, ALL_ARM + global ALL_CHAR, ALL_ARMS url = 'https://wiki.biligame.com/ys/角色筛选' data, code = await update_info(url, 'genshin') if code == 200: ALL_CHAR = init_game_pool('genshin', data, GenshinChar) url = 'https://wiki.biligame.com/ys/武器图鉴' - data, code = await update_info(url, 'genshin_arm', ['头像', '名称', '类型', '稀有度.alt', '初始基础属性1', - '初始基础属性2', '攻击力(MAX)', '副属性(MAX)', '技能']) + data, code = await update_info(url, 'genshin_arms', ['头像', '名称', '类型', '稀有度.alt', + '获取途径', '初始基础属性1', '初始基础属性2', + '攻击力(MAX)', '副属性(MAX)', '技能']) if code == 200: - ALL_ARM = init_game_pool('genshin', data, GenshinChar) + ALL_ARMS = init_game_pool('genshin', data, GenshinChar) # asyncio.get_event_loop().run_until_complete(update_genshin_info()) @@ -61,39 +61,34 @@ async def update_genshin_info(): @driver.on_startup async def init_data(): - global ALL_CHAR, ALL_ARM - if not os.path.exists(DRAW_PATH + '/draw_card_config/genshin.json') or \ - not os.path.exists(DRAW_PATH + '/draw_card_config/genshin_arm.json'): - await update_genshin_info() - else: - with open(DRAW_PATH + '/draw_card_config/genshin.json', 'r', encoding='utf8') as f: - genshin_dict = json.load(f) - with open(DRAW_PATH + '/draw_card_config/genshin_arm.json', 'r', encoding='utf8') as f: - genshin_arm_dict = json.load(f) - ALL_CHAR = init_game_pool('genshin', genshin_dict, GenshinChar) - ALL_ARM = init_game_pool('genshin', genshin_arm_dict, GenshinChar) + global ALL_CHAR, ALL_ARMS + if GENSHIN_FLAG: + if not os.path.exists(DRAW_PATH + 'genshin.json') or not os.path.exists(DRAW_PATH + 'genshin_arms.json'): + await update_genshin_info() + else: + with open(DRAW_PATH + 'genshin.json', 'r', encoding='utf8') as f: + genshin_dict = json.load(f) + with open(DRAW_PATH + 'genshin_arms.json', 'r', encoding='utf8') as f: + genshin_ARMS_dict = json.load(f) + ALL_CHAR = init_game_pool('genshin', genshin_dict, GenshinChar) + ALL_ARMS = init_game_pool('genshin', genshin_ARMS_dict, GenshinChar) # 抽取卡池 def _get_genshin_card(mode: int = 1, add: float = 0.0): - global ALL_ARM, ALL_CHAR + global ALL_ARMS, ALL_CHAR if mode == 1: - star = random.sample([5, 4, 3], - counts=[int(GENSHIN_FIVE_P * 1000) + int(add * 1000), int(GENSHIN_FOUR_P * 1000), - int(GENSHIN_THREE_P * 1000)], - k=1)[0] + star = get_star([5, 4, 3], [GENSHIN_FIVE_P + add, GENSHIN_FOUR_P, GENSHIN_THREE_P]) elif mode == 2: - star = random.sample([5, 4], - counts=[int(GENSHIN_G_FIVE_P * 1000) + int(add * 1000), int(GENSHIN_FOUR_P * 1000)], - k=1)[0] + star = get_star([5, 4], [GENSHIN_G_FIVE_P + add, GENSHIN_G_FOUR_P]) else: star = 5 - chars = [x for x in (ALL_ARM if random.random() < 0.5 or star == 3 else ALL_CHAR) if x.star == star] + chars = [x for x in (ALL_ARMS if random.random() < 0.5 or star == 3 else ALL_CHAR) if x.star == star] return random.choice(chars), abs(star - 5) def _format_card_information(_count: int, user_id): - genshin_list = [] + char_list = [] star_list = [0, 0, 0] five_index_list = [] five_list = [] @@ -137,11 +132,11 @@ def _format_card_information(_count: int, user_id): five_dict[char.name] += 1 except KeyError: five_dict[char.name] = 1 - genshin_list.append(char) + char_list.append(char) if _count <= 90: genshin_count[user_id] = f_count genshin_pl_count[user_id] = count - return genshin_list, five_list, five_index_list, five_dict, star_list + return char_list, five_list, five_index_list, five_dict, star_list def reset_count(user_id: int): diff --git a/plugins/draw_card/guardian_handle.py b/plugins/draw_card/guardian_handle.py new file mode 100644 index 00000000..8838f059 --- /dev/null +++ b/plugins/draw_card/guardian_handle.py @@ -0,0 +1,118 @@ + +import os +import nonebot +from nonebot.adapters.cqhttp import MessageSegment +from util.init_result import image +from .update_game_info import update_info +from .util import init_star_rst, generate_img, max_card, BaseData,\ + set_list, get_star, format_card_information +import random +from .config import DRAW_PATH, GUARDIAN_ONE_CHAR_P, GUARDIAN_TWO_CHAR_P, GUARDIAN_THREE_CHAR_P, \ + GUARDIAN_THREE_CHAR_UP_P, GUARDIAN_TWO_ARMS_P, GUARDIAN_FIVE_ARMS_P, GUARDIAN_THREE_CHAR_OTHER_P, \ + GUARDIAN_FOUR_ARMS_P, GUARDIAN_THREE_ARMS_P, GUARDIAN_EXCLUSIVE_ARMS_P, GUARDIAN_EXCLUSIVE_ARMS_UP_P, \ + GUARDIAN_EXCLUSIVE_ARMS_OTHER_P, GUARDIAN_FLAG +from dataclasses import dataclass +from .init_card_pool import init_game_pool +try: + import ujson as json +except ModuleNotFoundError: + import json + +driver: nonebot.Driver = nonebot.get_driver() + +ALL_CHAR = [] +ALL_ARMS = [] + + +@dataclass +class GuardianChar(BaseData): + pass + + +@dataclass +class GuardianArms(BaseData): + pass + + +async def guardian_draw(count: int, pool_name): + if pool_name == 'arms': + cnlist = ['★★★★★', '★★★★', '★★★', '★★'] + star_list = [0, 0, 0, 0] + else: + cnlist = ['★★★', '★★', '★'] + star_list = [0, 0, 0] + obj_list, obj_dict, max_list, star_list, max_index_list = format_card_information(count, star_list, + _get_guardian_card, pool_name) + rst = init_star_rst(star_list, cnlist, max_list, max_index_list) + if count > 90: + obj_list = set_list(obj_list) + return image(b64=await generate_img(obj_list, 'guardian', star_list)) \ + + '\n' + rst[:-1] + '\n' + max_card(obj_dict) + + +async def update_guardian_info(): + global ALL_CHAR, ALL_ARMS + url = 'https://wiki.biligame.com/gt/英雄筛选表' + data, code = await update_info(url, 'guardian') + if code == 200: + ALL_CHAR = init_game_pool('guardian', data, GuardianChar) + url = 'https://wiki.biligame.com/gt/武器' + tmp, code_1 = await update_info(url, 'guardian_arms') + url = 'https://wiki.biligame.com/gt/盾牌' + data, code_2 = await update_info(url, 'guardian_arms') + if code_1 == 200 and code_2 == 200: + data.update(tmp) + ALL_ARMS = init_game_pool('guardian_arms', data, GuardianArms) + + +@driver.on_startup +async def init_data(): + global ALL_CHAR, ALL_ARMS + if GUARDIAN_FLAG: + if not os.path.exists(DRAW_PATH + 'guardian.json') or not os.path.exists(DRAW_PATH + 'guardian_arms.json'): + await update_guardian_info() + else: + with open(DRAW_PATH + 'guardian.json', 'r', encoding='utf8') as f: + guardian_char_dict = json.load(f) + with open(DRAW_PATH + 'guardian_arms.json', 'r', encoding='utf8') as f: + guardian_arms_dict = json.load(f) + ALL_CHAR = init_game_pool('guardian', guardian_char_dict, GuardianChar) + ALL_ARMS = init_game_pool('guardian_arms', guardian_arms_dict, GuardianArms) + + +# 抽取卡池 +def _get_guardian_card(itype): + global ALL_CHAR, ALL_ARMS + if itype != 'arms': + star = get_star([3, 2, 1], [GUARDIAN_THREE_CHAR_P, GUARDIAN_TWO_CHAR_P, GUARDIAN_ONE_CHAR_P]) + chars = [x for x in ALL_CHAR if x.star == star] + return random.choice(chars), abs(star - 3) + else: + star = get_star([5, 4, 3, 2], [GUARDIAN_FIVE_ARMS_P, GUARDIAN_FOUR_ARMS_P, + GUARDIAN_THREE_ARMS_P, GUARDIAN_TWO_ARMS_P]) + arms = [x for x in ALL_ARMS if x.star == star] + return random.choice(arms), abs(star - 5) + + +# 整理数据 +def _format_card_information(count: int, pool_name: str): + max_star_lst = [] + max_index_lst = [] + obj_list = [] + obj_dict = {} + if pool_name == 'arms': + star_list = [0, 0, 0, 0] + else: + star_list = [0, 0, 0] + for i in range(count): + obj, code = _get_guardian_card(pool_name) + star_list[code] += 1 + if code == 0: + max_star_lst.append(obj.name) + max_index_lst.append(i) + try: + obj_dict[obj.name] += 1 + except KeyError: + obj_dict[obj.name] = 1 + obj_list.append(obj) + return obj_list, obj_dict, max_star_lst, star_list, max_index_lst diff --git a/plugins/draw_card/init_card_pool.py b/plugins/draw_card/init_card_pool.py index ff2df043..36cbe146 100644 --- a/plugins/draw_card/init_card_pool.py +++ b/plugins/draw_card/init_card_pool.py @@ -14,6 +14,8 @@ def init_game_pool(game: str, data: dict, Operator: Any): recruit_only = True if '活动获取' in data[key]['获取途径']: event_only = True + if len(data[key]['获取途径']) == 1 and '凭证交易所' == data[key]['获取途径'][0]: + limited = True if key.find('阿米娅') != -1: continue tmp_lst.append(Operator(name=key, star=int(data[key]['星级']), @@ -29,5 +31,14 @@ def init_game_pool(game: str, data: dict, Operator: Any): if game == 'pretty_card': for key in data.keys(): tmp_lst.append(Operator(name=data[key]['中文名'], star=len(data[key]['稀有度']), limited=False)) + if game in ['guardian', 'guardian_arms']: + for key in data.keys(): + tmp_lst.append(Operator(name=data[key]['名称'], star=int(data[key]['星级']), limited=False)) + if game == 'pcr': + for key in data.keys(): + limited = False + if key.find('(') != -1: + limited = True + tmp_lst.append(Operator(name=data[key]['名称'], star=int(data[key]['星级']), limited=limited)) return tmp_lst diff --git a/plugins/draw_card/pcr_handle.py b/plugins/draw_card/pcr_handle.py new file mode 100644 index 00000000..2cd4e387 --- /dev/null +++ b/plugins/draw_card/pcr_handle.py @@ -0,0 +1,91 @@ +import ujson as json +import os +from util.init_result import image +import nonebot +import random +from .update_game_info import update_info +from .util import generate_img, init_star_rst, BaseData, set_list, get_star, max_card +from .config import PCR_TWO_P, PCR_THREE_P, PCR_ONE_P, DRAW_PATH, PCR_FLAG, PCR_G_TWO_P, PCR_G_THREE_P +from dataclasses import dataclass +from .init_card_pool import init_game_pool + +driver: nonebot.Driver = nonebot.get_driver() + +ALL_CHAR = [] + + +@dataclass +class PcrChar(BaseData): + pass + + +async def pcr_draw(count: int): + # 0 1 2 + cnlist = ['★★★', '★★', '★'] + char_list, three_list, three_index_list, char_dict, star_list = _format_card_information(count) + rst = init_star_rst(star_list, cnlist, three_list, three_index_list) + if count > 90: + char_list = set_list(char_list) + return image(b64=await generate_img(char_list, 'pcr', star_list)) \ + + '\n' + rst[:-1] + '\n' + max_card(char_dict) + + +async def update_pcr_info(): + global ALL_CHAR + url = 'https://wiki.biligame.com/pcr/角色筛选表' + data, code = await update_info(url, 'pcr') + if code == 200: + ALL_CHAR = init_game_pool('pcr', data, PcrChar) + + +@driver.on_startup +async def init_data(): + global ALL_CHAR + if PCR_FLAG: + if not os.path.exists(DRAW_PATH + 'pcr.json'): + await update_pcr_info() + else: + with open(DRAW_PATH + 'pcr.json', 'r', encoding='utf8') as f: + pcr_dict = json.load(f) + ALL_CHAR = init_game_pool('pcr', pcr_dict, PcrChar) + + +# 抽取卡池 +def _get_pcr_card(mode: int = 1): + global ALL_CHAR + if mode == 2: + star = get_star([3, 2], [PCR_G_THREE_P, PCR_G_TWO_P]) + else: + star = get_star([3, 2, 1], [PCR_THREE_P, PCR_TWO_P, PCR_ONE_P]) + chars = [x for x in ALL_CHAR if x.star == star and not x.limited] + return random.choice(chars), abs(star - 3) + + +def _format_card_information(_count: int): + char_list = [] + star_list = [0, 0, 0] + three_index_list = [] + three_list = [] + char_dict = {} + # 保底计算 + count = 0 + for i in range(_count): + count += 1 + # 十连保底 + if count == 10: + char, code = _get_pcr_card(2) + count = 0 + else: + char, code = _get_pcr_card() + if code == 1: + count = 0 + star_list[code] += 1 + if code == 0: + three_list.append(char.name) + three_index_list.append(i) + try: + char_dict[char.name] += 1 + except KeyError: + char_dict[char.name] = 1 + char_list.append(char) + return char_list, three_list, three_index_list, char_dict, star_list diff --git a/plugins/draw_card/pretty_handle.py b/plugins/draw_card/pretty_handle.py index afdec8d7..97331585 100644 --- a/plugins/draw_card/pretty_handle.py +++ b/plugins/draw_card/pretty_handle.py @@ -2,11 +2,11 @@ import os import nonebot from util.init_result import image -from configs.path_config import DRAW_PATH from .update_game_info import update_info -from .util import download_img, init_star_rst, generate_img, max_card, BaseData, set_list +from .util import download_img, init_star_rst, generate_img, max_card, BaseData, \ + set_list, get_star, format_card_information import random -from .config import PRETTY_THREE, PRETTY_TWO, PRETTY_ONE +from .config import PRETTY_THREE_P, PRETTY_TWO_P, DRAW_PATH, PRETTY_ONE_P, PRETTY_FLAG from dataclasses import dataclass from .init_card_pool import init_game_pool try: @@ -30,7 +30,9 @@ async def pretty_draw(count: int, pool_name): cnlist = ['SSR', 'SR', 'R'] else: cnlist = ['★★★', '★★', '★'] - obj_list, obj_dict, three_list, star_list, three_olist = _format_card_information(count, pool_name) + star_list = [0, 0, 0] + obj_list, obj_dict, three_list, star_list, three_olist = format_card_information(count, star_list, + _get_pretty_card, pool_name) rst = init_star_rst(star_list, cnlist, three_list, three_olist) if count > 90: obj_list = set_list(obj_list) @@ -53,53 +55,30 @@ async def update_pretty_info(): @driver.on_startup async def init_data(): global ALL_CHAR, ALL_CARD - if not os.path.exists(DRAW_PATH + '/draw_card_config/pretty.json') or\ - not os.path.exists(DRAW_PATH + '/draw_card_config/pretty_card.json'): - await update_pretty_info() - for icon_url in [ - 'https://patchwiki.biligame.com/images/umamusume/thumb/0/06/q23szwkbtd7pfkqrk3wcjlxxt9z595o.png' - '/40px-SSR.png', - 'https://patchwiki.biligame.com/images/umamusume/thumb/3/3b/d1jmpwrsk4irkes1gdvoos4ic6rmuht.png' - '/40px-SR.png', - 'https://patchwiki.biligame.com/images/umamusume/thumb/f/f7/afqs7h4snmvovsrlifq5ib8vlpu2wvk.png' - '/40px-R.png']: - await download_img(icon_url, 'pretty', icon_url.split('-')[-1][:-4]) - else: - with open(DRAW_PATH + '/draw_card_config/pretty.json', 'r', encoding='utf8') as f: - pretty_char_dict = json.load(f) - with open(DRAW_PATH + '/draw_card_config/pretty_card.json', 'r', encoding='utf8') as f: - pretty_card_dict = json.load(f) - ALL_CHAR = init_game_pool('pretty', pretty_char_dict, PrettyChar) - ALL_CARD = init_game_pool('pretty_card', pretty_card_dict, PrettyChar) + if PRETTY_FLAG: + if not os.path.exists(DRAW_PATH + 'pretty.json') or not os.path.exists(DRAW_PATH + 'pretty_card.json'): + await update_pretty_info() + for icon_url in [ + 'https://patchwiki.biligame.com/images/umamusume/thumb/0/06/q23szwkbtd7pfkqrk3wcjlxxt9z595o.png' + '/40px-SSR.png', + 'https://patchwiki.biligame.com/images/umamusume/thumb/3/3b/d1jmpwrsk4irkes1gdvoos4ic6rmuht.png' + '/40px-SR.png', + 'https://patchwiki.biligame.com/images/umamusume/thumb/f/f7/afqs7h4snmvovsrlifq5ib8vlpu2wvk.png' + '/40px-R.png']: + await download_img(icon_url, 'pretty', icon_url.split('-')[-1][:-4]) + else: + with open(DRAW_PATH + 'pretty.json', 'r', encoding='utf8') as f: + pretty_char_dict = json.load(f) + with open(DRAW_PATH + 'pretty_card.json', 'r', encoding='utf8') as f: + pretty_card_dict = json.load(f) + ALL_CHAR = init_game_pool('pretty', pretty_char_dict, PrettyChar) + ALL_CARD = init_game_pool('pretty_card', pretty_card_dict, PrettyChar) # 抽取卡池 def _get_pretty_card(itype): global ALL_CHAR, ALL_CARD - star = random.sample([3, 2, 1], - counts=[int(PRETTY_THREE * 100), int(PRETTY_TWO * 100), - int(PRETTY_ONE * 100)], - k=1)[0] + star = get_star([3, 2, 1], [PRETTY_THREE_P, PRETTY_TWO_P, PRETTY_ONE_P]) chars = [x for x in (ALL_CARD if itype == 'card' else ALL_CHAR) if x.star == star] return random.choice(chars), abs(star - 3) - -# 整理数据 -def _format_card_information(count: int, pool_name: str): - three_list = [] - three_olist = [] - obj_list = [] - obj_dict = {} - star_list = [0, 0, 0] - for i in range(count): - obj, code = _get_pretty_card(pool_name) - star_list[code] += 1 - if code == 0: - three_list.append(obj.name) - three_olist.append(i) - try: - obj_dict[obj.name] += 1 - except KeyError: - obj_dict[obj.name] = 1 - obj_list.append(obj) - return obj_list, obj_dict, three_list, star_list, three_olist diff --git a/plugins/draw_card/prts_handle.py b/plugins/draw_card/prts_handle.py index f1e841eb..8f90d683 100644 --- a/plugins/draw_card/prts_handle.py +++ b/plugins/draw_card/prts_handle.py @@ -1,17 +1,15 @@ import os +from util.init_result import image import nonebot import random -from .config import PRTS_FIVE_P, PRTS_FOUR_P, PRTS_SIX_P, PRTS_THREE_P +from .config import PRTS_FIVE_P, PRTS_FOUR_P, PRTS_SIX_P, PRTS_THREE_P, DRAW_PATH, PRTS_FLAG from .update_game_info import update_info -from .util import generate_img, init_star_rst, max_card, BaseData, UpEvent, set_list +from .util import generate_img, init_star_rst, max_card, BaseData, UpEvent, set_list, get_star, format_card_information from .init_card_pool import init_game_pool from pathlib import Path from .announcement import PrtsAnnouncement from dataclasses import dataclass -from util.init_result import image -from configs.path_config import DRAW_PATH -from services.log import logger try: import ujson as json except ModuleNotFoundError: @@ -36,13 +34,15 @@ class Operator(BaseData): async def prts_draw(count: int = 300): cnlist = ['★★★★★★', '★★★★★', '★★★★', '★★★'] - operator_list, operator_dict, six_list, star_list, six_olist = _format_card_information(count) + star_list = [0, 0, 0, 0] + operator_list, operator_dict, six_list, star_list, six_index_list = format_card_information(count, star_list, + _get_operator_card) up_list = [] if _CURRENT_POOL_TITLE: for x in UP_OPERATOR: for operator in x.operators: up_list.append(operator) - rst = init_star_rst(star_list, cnlist, six_list, six_olist, up_list) + rst = init_star_rst(star_list, cnlist, six_list, six_index_list, up_list) if count > 90: operator_list = set_list(operator_list) pool_info = "当前up池: " if _CURRENT_POOL_TITLE else "" @@ -63,22 +63,19 @@ async def update_prts_info(): @driver.on_startup async def init_data(): global prts_dict, ALL_OPERATOR - if not os.path.exists(DRAW_PATH + '/draw_card_config/prts.json'): - await update_prts_info() - else: - with open(DRAW_PATH + '/draw_card_config/prts.json', 'r', encoding='utf8') as f: - prts_dict = json.load(f) - ALL_OPERATOR = init_game_pool('prts', prts_dict, Operator) - await _init_up_char() - # print([x.operators for x in UP_OPERATOR if x.star == 5 and x.zoom > 1]) + if PRTS_FLAG: + if not os.path.exists(DRAW_PATH + 'prts.json'): + await update_prts_info() + else: + with open(DRAW_PATH + 'prts.json', 'r', encoding='utf8') as f: + prts_dict = json.load(f) + ALL_OPERATOR = init_game_pool('prts', prts_dict, Operator) + await _init_up_char() # 抽取干员 def _get_operator_card(): - star = random.sample([6, 5, 4, 3], - counts=[int(PRTS_SIX_P * 100), int(PRTS_FIVE_P * 100), - int(PRTS_FOUR_P * 100), int(PRTS_THREE_P * 100)], - k=1)[0] + star = get_star([6, 5, 4, 3], [PRTS_SIX_P, PRTS_FIVE_P, PRTS_FOUR_P, PRTS_THREE_P]) if _CURRENT_POOL_TITLE: zooms = [x.zoom for x in UP_OPERATOR if x.star == star] zoom = 0 @@ -108,39 +105,16 @@ def _get_operator_card(): else: acquire_operator = random.choice([x for x in ALL_OPERATOR if x.star == star and not any([x.limited, x.event_only, x.recruit_only])]) - # print(f'{acquire_operator}: {star}') return acquire_operator, abs(star - 6) -# 整理抽卡数据 -def _format_card_information(count: int): - operator_list = [] # 抽取的干员列表 - operator_dict = {} # 抽取各干员次数 - star_list = [0, 0, 0, 0] # 各个星级次数 - six_list = [] # 六星干员列表 - six_index_list = [] # 六星干员获取位置 - for i in range(count): - operator, code = _get_operator_card() - star_list[code] += 1 - if code == 0: - six_list.append(operator.name) - six_index_list.append(i) - try: - operator_dict[operator.name] += 1 - except KeyError: - operator_dict[operator.name] = 1 - operator_list.append(operator) - return operator_list, operator_dict, six_list, star_list, six_index_list - - # 获取up干员和概率 async def _init_up_char(): - global up_char_dict, _CURRENT_POOL_TITLE + global _CURRENT_POOL_TITLE up_char_dict = await PrtsAnnouncement.update_up_char() - # print(up_char_dict) _CURRENT_POOL_TITLE = up_char_dict['title'] up_char_dict = up_char_dict['up_char'] - logger.info(f'成功获取明日方舟当前up信息...当前up池: {_CURRENT_POOL_TITLE}') + print(f'成功获取明日方舟当前up信息...当前up池: {_CURRENT_POOL_TITLE}') average_dict = {'6': {}, '5': {}, '4': {}} for star in up_char_dict.keys(): for key in up_char_dict[star].keys(): @@ -148,7 +122,6 @@ async def _init_up_char(): average_dict[star][up_char_dict[star][key]].append(key) else: average_dict[star][up_char_dict[star][key]] = [key] - up_char_dict = {'6': {}, '5': {}, '4': {}} for star in average_dict.keys(): for str_zoom in average_dict[star].keys(): if str_zoom[0] == '权': diff --git a/plugins/draw_card/rule.py b/plugins/draw_card/rule.py new file mode 100644 index 00000000..f13b3729 --- /dev/null +++ b/plugins/draw_card/rule.py @@ -0,0 +1,36 @@ +from nonebot.rule import Rule +from nonebot.adapters.cqhttp import Bot, MessageEvent +from nonebot.typing import T_State +from .config import GENSHIN_FLAG, PRTS_FLAG, PRETTY_FLAG, GUARDIAN_FLAG, PCR_FLAG + + +def is_switch(game_name: str) -> Rule: + + async def _is_switch(bot: Bot, event: MessageEvent, state: T_State) -> bool: + if game_name == 'prts': + return PRTS_FLAG + if game_name == 'genshin': + return GENSHIN_FLAG + if game_name == 'pretty': + return PRETTY_FLAG + if game_name == 'guardian': + return GUARDIAN_FLAG + if game_name == 'pcr': + return PCR_FLAG + else: + return False + + return Rule(_is_switch) + + + + + + + + + + + + + diff --git a/plugins/draw_card/update_game_info.py b/plugins/draw_card/update_game_info.py index 7f9034a0..5acf086c 100644 --- a/plugins/draw_card/update_game_info.py +++ b/plugins/draw_card/update_game_info.py @@ -1,40 +1,38 @@ #coding:utf-8 import aiohttp -from configs.path_config import DRAW_PATH +from .config import DRAW_PATH from asyncio.exceptions import TimeoutError -from services.log import logger from bs4 import BeautifulSoup from .util import download_img from urllib.parse import unquote import bs4 -from util.user_agent import get_user_agent import re +from util.utils import get_local_proxy try: import ujson as json except ModuleNotFoundError: import json +headers = {'User-Agent': '"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)"'} + + async def update_info(url: str, game_name: str, info_list: list = None) -> 'dict, int': try: - with open(DRAW_PATH + f'/draw_card_config/{game_name}.json', 'r', encoding='utf8') as f: + with open(DRAW_PATH + f'{game_name}.json', 'r', encoding='utf8') as f: data = json.load(f) except (ValueError, FileNotFoundError): data = {} try: - async with aiohttp.ClientSession(headers=get_user_agent()) as session: - async with session.get(url, timeout=7) as response: + async with aiohttp.ClientSession(headers=headers) as session: + async with session.get(url, proxy=get_local_proxy(), timeout=7) as response: soup = BeautifulSoup(await response.text(), 'lxml') - max_count = 0 - _tbody = None - for tbody in soup.find_all('tbody'): - if len(tbody.find_all('tr')) > max_count: - _tbody = tbody - max_count = len(tbody.find_all('tr')) + _tbody = get_tbody(soup, game_name, url) trs = _tbody.find_all('tr') - att_dict = {'头像': 0, '名称': 1} - index = 2 - for th in trs[0].find_all('th')[2:]: + att_dict, start_index, index = init_attr(game_name) + if game_name == 'guardian': + start_index = 1 + for th in trs[0].find_all('th')[start_index:]: text = th.text if text[-1] == '\n': text = text[:-1] @@ -42,44 +40,30 @@ async def update_info(url: str, game_name: str, info_list: list = None) -> 'dict index += 1 for tr in trs[1:]: member_dict = {} - k_name = '' tds = tr.find_all('td') if not info_list: info_list = att_dict.keys() for key in info_list: - attr = '' - if key.find('.') != -1: - key = key.split('.') - attr = key[-1] - key = key[0] + key, attr = parse_key(key, game_name) td = tds[att_dict[key]] - last_tag = unquote(_find_last_tag(td, attr), 'utf-8') - if game_name.find('pretty') == -1 and last_tag.find('http') == -1: - last_tag = last_tag.split('.')[0] - if key == '名称': - k_name = last_tag + last_tag = unquote(_find_last_tag(td, attr, game_name), 'utf-8') member_dict[key] = last_tag - if game_name == 'pretty' and key == '初始星级': - member_dict['初始星级'] = len(td.find_all('img')) + member_dict = intermediate_check(member_dict, key, game_name, td) avatar_img = await _modify_avatar_url(session, game_name, member_dict["名称"]) - if avatar_img: - member_dict['头像'] = avatar_img - name = member_dict['名称'] - if game_name == 'pretty_card': - name = member_dict['中文名'] + member_dict['头像'] = avatar_img if avatar_img else member_dict['头像'] + name = replace_name(member_dict, game_name) await download_img(member_dict['头像'], game_name, name) - if k_name: - data[k_name] = member_dict - logger.info(f'{k_name} is update...') + data[name] = member_dict + print(f'{name} is update...') data = await _last_check(data, game_name, session) except TimeoutError: return {}, 999 - with open(DRAW_PATH + f'/draw_card_config/{game_name}.json', 'w', encoding='utf8') as wf: + with open(DRAW_PATH + f'{game_name}.json', 'w', encoding='utf8') as wf: wf.write(json.dumps(data, ensure_ascii=False, indent=4)) return data, 200 -def _find_last_tag(element: bs4.element.Tag, attr: str) -> str: +def _find_last_tag(element: bs4.element.Tag, attr: str, game_name: str) -> str: last_tag = [] for des in element.descendants: last_tag.append(des) @@ -100,13 +84,17 @@ def _find_last_tag(element: bs4.element.Tag, attr: str) -> str: last_tag = str(last_tag) if str(last_tag) and str(last_tag)[-1] == '\n': last_tag = str(last_tag)[:-1] + + if game_name not in ['pretty', 'pretty_card', 'guardian'] and last_tag.find('http') == -1: + last_tag = last_tag.split('.')[0] + return last_tag # 获取大图(小图快爬) async def _modify_avatar_url(session: aiohttp.ClientSession, game_name: str, char_name: str): if game_name == 'prts': - async with session.get(f'https://wiki.biligame.com/arknights/{char_name}', timeout=7) as res: + async with session.get(f'https://wiki.biligame.com/arknights/{char_name}', proxy=get_local_proxy(), timeout=7) as res: soup = BeautifulSoup(await res.text(), 'lxml') try: img_url = str(soup.find('img', {'class': 'img-bg'})['srcset']).split(' ')[-2] @@ -116,17 +104,31 @@ async def _modify_avatar_url(session: aiohttp.ClientSession, game_name: str, cha if game_name == 'genshin': return None if game_name == 'pretty_card': - async with session.get(f'https://wiki.biligame.com/umamusume/{char_name}', timeout=7) as res: + async with session.get(f'https://wiki.biligame.com/umamusume/{char_name}', proxy=get_local_proxy(), timeout=7) as res: soup = BeautifulSoup(await res.text(), 'lxml') img_url = soup.find('div', {'class': 'support_card-left'}).find('div').find('img').get('src') return img_url + if game_name == 'guardian': + # 未上传图片太多,换成像素图 + # async with session.get(f'https://wiki.biligame.com/gt/{char_name}', timeout=7) as res: + # soup = BeautifulSoup(await res.text(), 'lxml') + # soup = soup.find('table', {'class': 'wikitable'}).find('tbody').find('tr') + # try: + # img_url = str(soup.find('img', {'class': 'img-kk'})['srcset']).split(' ')[-2] + # except KeyError: + # img_url = str(soup.find('img', {'class': 'img-kk'})['src']) + # except TypeError: + # print(f'{char_name} 图片还未上传,跳过...') + # img_url = '' + # return img_url + return None -# 数据最后处理(是否需要额外数据) +# 数据最后处理(是否需要额外数据或处理数据) async def _last_check(data: dict, game_name: str, session: aiohttp.ClientSession): if game_name == 'prts': for key in data.keys(): - async with session.get(f'https://wiki.biligame.com/arknights/{key}', timeout=7) as res: + async with session.get(f'https://wiki.biligame.com/arknights/{key}', proxy=get_local_proxy(), timeout=7) as res: soup = BeautifulSoup(await res.text(), 'lxml') obtain = str(soup.find('table', {'class': 'wikitable'}).find('tbody').find_all('td')[-1]) obtain = re.search(r'
EVyLpg1WQzwsyV1afGMz__>y4s7#9wHH&3U z)2q}l``H2*J>LBm)2xA|gllSN8dIYK%`=2+=VNzS^Pxk1vDFRj@u8vex-}E3+9YvE zj$|+;$Yqk~c>Q^BqJ$M2FM}v6@P{kmFRKEz3<$CUuRj8BAOc1i3_SMh~f;4d)LLj=_(6uZ821Cn2viy)de(1Ue#u!|(_6@u7t!p26{xJAX)GJ fGenZ-q|}6E8mOpW0&ln$i~x!!SV*)8S1$ykd4umn5-yzZ zWnPqE=^7ZNFmf449zR4;g086mA=t8R>6H)EZTopg_u#JCxp^4W=-}a*MwQUa&-Pep zcEBP8yyC5%X;@2)^dDjCydtkzz;HGeg{5l{WErM5i>xQAOxDC`-3K$yb@7Qx`kT zf&)0%iK_sZX@OA-oFD)c$fm}jW|Bz7hLKIh;15?JSkZuBWxdUH2!SZdV3fi%b?~AL zQFhyvXea{;(G(1plN?*pV9W6k6*uw?n9N)jlG_K#?S<|v^SYJLg_~A=prd $|Hp`ve36MGI@ARa4$;9b?0)`!bhqt< ztwV9hrQ_&rdmZWcID+MM@P;ZND_(@F=ffYVfiF}A+3kny3BcnogQU18%|a)1`YA@> zBJrF56BQSTU>i&=(}1bvAh U%dsg z%Ub|Pq-H(>Wpz#&Nde5VD=!z~<{1UeCu7iJ|0TiX1dXYvpJJ47>N`lX8=9E{m>me{ zR@{(W9w+JnsE7m_&OKw {UTI1E`w#6i1xO^GITHo2!aS-xEc*h&H~R1j?(W!P^ot^cpRmk zS>Oc$j4?aSte^uHb4*qctrJFsDX+nlr&-` JL5f^6uLcsqE 07Ekzc|4spalCi3vH19D_WX{_WPD;^^q2yAC;%O{ z`N4SZQ2) cP9h8@c0>X^d(H1LE2-Jf0um5 zti<<{5}$z=MLRgrepR7ovmnF{v&kR7v9^5q#x;wtU;rb>8B#+nbH-;x2$^$G;T!_} zW|C9nSh#4hN}&TF2M+aib=Ft?YX7UR{kUQEI?fx3*h=msu2nh`k5LB2<-@WKm)P-4 zvKy CeWF&_4`6r#%mUCr3DTP+96&>$&ZXxVgLB$9WWv-V?KUvGUdlT#BDus=G{ zV|)2$O|#@!1dOqgQ#eAv3A}Kuh-a{^@g@NDMbq0yV~KcTXuy6rV3TZFGv6@^!f|kU z{g4$m>>?p{aS%!!2Qn?5g)vx+!m_B-hyW-cAP<%z7E~~d()@Q!l#>K2Oawp}2slJX z29Qq19A9L9KgAP_k~55=>$JBMWZBM~W`IR0v}_tg;2|lV!n?b4LEXmHOB&C&C^e6V zYjGSmqm__ROP#BZH7j5-M!_sAQ)-NGgmWt{xzyMZhytL7WvZ41RnO%LZ|(F06i=s$ z9}aam1f4vdcW$$MxojuHYSLYuSWwKF3QPz _0q;CQ=aD@O=_+1YD9Dodi9BZNC9c>zEY zMSdnfHls8 N1D)?^7_*xfaMoZ3N4p*D&YXZ@>+}!bRj-I1i}$CEM5(& z x`EJKIv@`C5>;w6eCc`n_u`Xf9? zc%CEtv2ZQL<5Mt$=rpqN(YYp6%#vd E zi_p`&9m&xFh>9EYR&7EyHj2^CmO?19Eh)LlL5&jwm?#=Ck*{cTEg7P$ARjQO=aS$A z0kYd$0Q_027hTa 5*!Eun=-DhxU3dBh+4m;kaYruR zwCY0~A>6T~ })XxMRb$qb*Xxkr+W^HazV*`V*-wqB_?n9ugb}`3sIF1=D1t2{5 z()Jda-|$&Y-}ViTkOo=c{0o;Zc5l4uYRDe1 -%Sp;-ef zJKj6Sz$gLXrk=hpQngH!Bxvd}2O%=pmU!jv=U;smz^-607}>P2adjq>`(f?E1(l07 zpJR7T1#=Wz2Vhfg-4y+*7)*q>D}OVK+KmKwVItjM;J_@3%*e2 MC-{C^E4T zcq7%|IUdvrwaF#oV3rBl<%8Sf#ex; 8Phc84v}_im zgMCOu$3e3xm`;+a%O8ZOc#um(q31GCoi=%jF91duz$iG5gQ&P+=o&yc=voevnuF-_ zfXk#nEeny5zxKQ{mtS|sqc47sBOGtB(sA*EC?ZtZa7Ir_eU+JNv~Rq`$Z^rEfu%)< zGR!ohM3kq6w~F4#Vt*jSkE(;m6NE+qXaGb2$#^`T-9PNJ&TJ~n5ho35x_xveW h?jT>mLAW=21_%u zgO5CkLytUx%z-wr0|zkn)N?p+`@QIY{&g4`y8uZcquMe-Eel?+50OYYg252H{s06) zfHzzQPcTww)Rgc1T1 0KeZ3xGMxA0>G3koZ?d`O?I2PU@(Z `;PV#&)y_dAoNb<96fo3`oj#^agw$NRW$nj&9(TmP{^^SRqUCEE69y@nuaJul z>@d~L+@^$>1F#sikRE7zzSP)wj$-NR4d>3aUyI2|M%Q$zt7_2 @Ms}*Hlny*_qQ0*P35nxn}+Hd6!Z)y dSaFCZ+(uH z4l6${np3rz_~Biz)o%G4I>Z%(TGq9E_|6UJ^lg4q7e? AKUY z%O*ky2+t$d+l!(7%}Dhe2Gk@tX4)l-oPfWaVPQ<8FmwVY$WS8Xa95VY^6(&v07;gi z1ieW14Pbmv8|085wHwxe5x`LGhU$i@!qij ;9dy*fj$HlUk}}Sr#>PaDo8SFzlgxq$p5u zk+6Kosr{o!aknF0J)sJW8m-`SIaF{ac-V#iL8uKXo&!;M2tF4$S%ym%kk&0w!vybi z7~^;zmSv&qm96M` GP_sHxi7q7e9z;eL;Hs;` zipwrS)#4@CedqxME9$^N;WB}`_3MyLrw|(*K`IeLCYgYq%YvFFJi&6i*#H39 X7)b{n>ww`wFq{H1QXni$!h9qT#u z75z*thh+Dj`$~; O;XAMAg;`^l?09ugUo5TPv2W{Ej2=D+UK9YrCPW@7R^2CN zfc6J-!dRS9YQi0ffPn*r1>3Vs?bSsN#KlAKD-eSoh(Qm)=L@;nGfhqqprzB;_wa-0 zefde$S5Z_}x?!ey#Ct86DhE!I0Akz9s2!mUjssjC0p*o4<}Gq#L6ZR5--Z2ud=%|Z zK7(jiH}q^0O2CJ)u3iuZ^zYe=j;Egk$r*@LRsmoz4Gp _wShsB6B}?YjoJAR<97lLw5U}OK%Rkf^D;?mQ=-PF!rOzn=x zCS1M6j$Odc`wKQT!PVG+Q4KH&1raD9!sb+d7sQ|!Qpg937tqrlhreMFM8yS85Re`j z#;$wrLF&*xG}X&+i6Roc1X_xRx55J@ z;4e==c6)L5$3KmYANe>cmaoOW$DhDp`(ZR~xBz|o_QNf?;1Ah(k-D0Np34^eii*cq zh>SH=6{fC1a(iKi!!byr=z7OFYd tD`^(2(`H%jQXh;8n1BEKd z_Px!A*iATaS;3hL6v}fu>rl%?^;xUnU$qv)hJv)g00|I$5~Pp^QrHJE;6{JjC@R)$ z#H#DA2H^!{qfs m{Eo1A2l-e^y z#jdSNncYH#;{}^*G5cK3TD9nkMUB;GSd>}kT=b6B2}7<_OHBGqHQ63JxU*!$%4}%P zz*6HwR=Q{3?@Eoe4r#djn)iQ2mX9~?uRs*GO-ttqm(?|WdMrFC`aOgFAz!0bODEw9 zg>lx6A40{JO&B%37>p8RG{67{!ve;7<48vhG;KKx952AqHMBqR7|i$}YN{njA_pzb zgBJmBEeG%nrfJ$B7kK2u#q$lv3mw2HMKZzA*H6&XOE5glV3`)Ep`rcRC$Z=LyRq-l z`(f$^n$Fyes->&2^0KQi(mw qS+kVVCfBUN%F`ftm&+ClC+-+=}eK zWb^8e$g<46 )4O_dKV-SFf|4vOW~rZKa+O0?ROAY8t3vTk1{Cgk_ijV~8gh#>RPw5<^8b4@t6 4G4Ev@G_wlvGN%T~fP>@1pMU7ZofI$z`<%V$a3 zeVr|cq69`QSegb`SqSxO)&d4Wb}R}(65+2bhdUeqvlvu0g}&EzA{^$SC 1}x2hMJ>C3p-EvG1{kHtsSME=K`_KnQR{-@m7QX?8nh&ZsoHsz z0j~tNn?vVF66xpw7H--MzMCOZTaQ#C?l|B{k%+giQ*wKtt2r>sf|1QacKaZEd@wW> zj4}8;uF!{W_|zwclJKUC>CeE(CiacByfEibnPNI2El+ZZ5jxuX;!mdyFknw#7F#ZQ z*G-M{7tXe5ss%u}{h93#HFpjE>yvlit99?)1) f|guRI*{qlD!9FoD2s07VD~ zOE+K|7L-r`WlQEGw6GDP-vdK80T7I}wL^;z!|N46nGF^qFz{}GS = G z;>jWOy!r~fZURAY0{l2Ya4~=~P{V?m(_w15tt&ZptGpPr%N_xi$-ol}evbu9H<1}l zA~_sIE}4Ouv$>qTK45Alz$jc2gRW(<` dm+-0rN=_V>>S?R%7{`kO&nhoaZgf+s9AABvD9caIE>T=a$ z*w>fEyRLr!H>+#wXQRb4Ohi3czk7Da&24?7zuWoL6SnOp->iw`19~T>`nDa*u|qj^ z;?+zV3=Hl-2p|OMR1|8));l-|$f^nK8+r+^Z+{T#=m`8ld+N>@1vn>q!eXG*f@zqx z2s8{EP);F{d}dI-rj}c_KurT`G6OB0h2^Yk89FS}p87Lti)zY%tO ~m@*UAISgafYDvG{Ke9qbt! zY(HQp6cketplsi5K77V*-Ih(op=L7(l~+Ud_+aWf;-iDersC*|H)C7xBRDv+3uebS zA^{PK%keilKmlxhE#I7gSrp84KAmhI>XeVngN2zUOx=W`YA|&Jre?s@bWp=86rEv| zf#V3qQwCJQi-nsmLd~+ZSas2rIQzXH! =a_N3=>p0K^;35wJ0ph zvdsmB@G(1v3zQ*a0mEsAs^#k;dIK2k?LvHb02Z}SR@aC{8@3=l9-9c$DUx1{+1JNA zG4Q5gKs9KOT(^2 8WTspfW62 zR#C<^Wlp3-!T)W8#G=qB!BCDMuy8dh7p|~tsdAiMW0ly(-I4A?wnLmFMcit_Ax}6S zvL^uNr^!{U=+l@IdATbyU1?{aeJ|Yc&w46;VwEe0PAISdU|`$*2ei??$EPkI%u(#` z$>8# JwOG7FZ#mI0!G^WAu^U!h@rdA7>;DoHeh4QU|Ez@#zC+E`{V-_t~->GTq zXw0Obx(Q}bXcjPP@$fe-#k@1O*v(e~1j;Jl3zvfzMf4tMMsLe5gzKxOajFU11B2vp zLzESeK=mGP-Rd*;_hrdowgk5t>wa`_#{&mu`5cZ)CmdLMI?lSDyY0)2(P>kV=MHCJ zLJ8jV^?&`D*Xx^Y6d(gYvZ^_*Y8urw%eFjEs*Nz^>!kV*42nMp+2cpwp%%Q>@dUDZ z5 x%Lb3-h&@{1V9a99IKWH_ zVp)Jw< 01E&Hw%y;J8fd$H>he*Q z;?=_`tXQ+*{eOGoXD*(lBF_L&Nfaq#l+#i%2!b%V`2R$RmR-@fs2gfNj?)t?gW&Ta zmKla5xKI|UflKy-QU;!IFw1yE0~~rf(y%NZJkLAD{3nuE^9nkpHlXrgvaF)tl-l9T z76qk%K?Gz4H)4t(QCA53{8d O6P}#H?zHm8AT}R7HPvez8{ucgl z5amq`PLhUw4W&@Q7^8gU^1Vu=Ve!txDU6ng6ixNF-afGXfsW(7`Nu uux6nv>yY8QR$1TW(r9+WgF%Q@oBuCk ez~igb!|v z;BedCKYix U^SL5-3*2GI|v4(d`%*?ExVi{C*!e@KD@-NTLEdtRmYs06Aen)-1r(!3hK$N5Bya z%rwBk&aBZb2HgS-Mxb##vcy6T2E4uqDk~QtSlfVbZ4>+zHIUt2h_VZ!B*V~DjP-S* z@4z069Bzkc =zeYWD-wV(;eH!v44EJL3C)>qc=9+ z`jy*GL|prk=%fJ)0Nmvb!iF#1`Meygm{h2q5a4~weAuwikB9I3{ojA*A3pyxLqD#- zMIL|z+t RIEG6g53>A|;faXRbT`^Z zwqrOt0 )_r(_je7WpL{X)WLCN6LDm$3`9YOLItR%4wW;Y@g^7t zP)4Cr4OAdlz2qXCx$H6o!_{zke1%%?xl9Vl;X#aawqc~R9qGgUDG-J9NAKAL|ryo2&JJLPp^sb}PNd*=F z)SvVIc}qX=uluI zV!W>tv4L)+V`DIN6{0M`6AHl-3PE(c0g!_3HVH_@V44IhW|_f-FL~#0I&Uaua5ry@ zVyd&5Q7hYe_qSK}zIa#XaXr9U(n$vvCrDUz!;k;2a@{+AHFa!pP{j3{B7m74`}*f^ zT=)Ewf9^X@aB 5CX@;rT9@*-iT;y7^C9@FmwZ^X+qaEc$5HgY7VJ%!m+s9W`^3D zrFi#+pGVkRjcjZTWBr{N>+eE*xF1?32~m;Yi$tLK1CTu~yQzUwY1uN(!t^sAhRpH2 zQ!;4^$Fl2oG0R>3ihI%d>s5<){bAcU+T&9~j~SyQd!GFK-rK(PD{7pOkoKd}Ne31H zxFWUu88`j*0e5-hl~czqXmH{3H6g@Chg<*8r?20#>(y6|N14xu`Q^bSE?ZDvcfq2% zhu?ke6-^s1xdeu$7jY|0DDjw>SDBifiR||J&^T`idPh3(Z0o&{T{6mo)yU*hNM~bq ziWz0FD1&Jkuxlu2FbxyBVZbshco4wmMehMk>lhpCv}?4B0$e^1+<^cTuMdK3Hyp^P z;Zr9_zR;m8Uxtz+unYrZJ)Q7|!%+OeBCETtFq(3BmuumL^O)ogKd~o e!3DDqcUFLZqT<>G%HY*1s%W zvD#B=A2U#~HQoSV3`IwiJTJs@nVjQ?D~^0%g>sI_Tj&{uD9P|gDxqdmNG7AGt!To6 ziZ!rIidbR<)G)y3-$9On;~89{8*amepc+D$FGsbz4vXX!SRgD$qQ4Wm8AIi~TFhU+ z2J_diMb)Ck@RwH ^u({OT>S1YZ$pv3 zWif__TGI%61T3s?+W3QC-Tv^GKKZv-9BMmoJo$)uM>QXdscDXo@k}CRM;dT&(({>< z6~^*j9;cFv{jda4f*>jw>^Y3`s(P$x*o^8xJt(uF2wwDzw;`quL*yj*#4tiqHF%Q) zr2xls;5iP27xDpL_N2i{bj{nd@-0v78e5#hm>6JL$R=U{0Yt?O0zgg1ksKXDq;4LT zY*`4GF92puh(b&Bw@CBP4~lMoW&1!D4 rfw>5jq=igAh>6$+fGSQMwwHWT*oxq1TaA;hx_`)Ck`i?*S<7Yl{bz4jGkvd#V zJA(74fpCMWrrQ29ptvq=Q7*NUI_5-}G63#C1nKB7`n%g93L*r-<}R9$M!jb#>ikPV zK)`_q7`59s6>MdW50O!)E29(h?wC08vD1X(z$is(Yy`Pv9E9T#8|XtOF$TpGKw0B_ z1gq*%yJ9UW7cPa%9|QoWCyy-#Eh(^9o_Btk;PKb?j%m1eZvwd~sA7zogWDgtq35aF zn%`(p0dFL*V0VsayYGAVD#5A+;iX%?Tb!C7(<$zHJ&q4=2w~pBC71s6*1Mnn`WJ4z ze9vp!6UU*@1Av*%sr_13g=N_i#zx#k606NANMW9ClP!+CkxD4u04!%l$?*a>UbG`O z^XXiyNH;1p8JGYNAq={vfpB~w;4hbq!7>dbM~0wgQb@ -YcZ@89vvV-NKlL%ckJ zZF<1<7jOK;s;0VMeBg^;grab;oW=nYMQR;lwldEqFF?WZQ;5Twu!q^pCwd#^nIW}I zr_47+_x|1JYu^vW?Ln}-3KfkDksKd}zpMhewB1owa=9TYF61*m3Jo_YMakm2ASU(H zY*(5#uH+ ij#tOgpP8;YC3>2Fx%*dt_XRC6a#EWF9Esi#<$Wrt@nPEh+b{in zX0T&g+SowW!X2;1Fp|&_DX&=iy`SB@>r-F+$4eB&bu7DP0Fcg_1DdKbT{Tc7ah=q$ z;t*z5NG_eQ5!v5u@Dzv4I9n7MTXi*uRD29A+n>Yk=O2TbNy0J=#D@D3D62%{@-?Vl zxD<-lhst@2AbWfWR@TB-RsqrFF4(Fp({P$SO_)Lof*lMDT$V+azU*3X&Y7I#4vr>t z-1%y>B&gCu9lvkB?eD*MDnSLDB47bPW~j&9bMqHIo*6!T_tdezjETE;#xR!Dp}0Na zPyPKrJ^J0B-Td{+>RRC_j%x;hs3sjYbuFDurtDsVMMR3%EM7ikzbp?j;;dY>J^_Jc z8rZ-6X>5D^UUawavb#tKB6vZ-%5yKp^0O~QxYq77ov#W*DJ>Lnv&&viIT2R$>41vz z$^citvDsC({#?R~%2-mzT{~mwE0N8d89sFP-dk?EF+1FI(k<&pqf-Vf07wrWGWOi^ z`44ADyC0l7)|)nQ_s$r`(*}5fmoB~H+VB7Bj)xxJeBQ+~_0r3m9>_>0IjU*;NG2Ww zFUdt=CboTuIMR+4bFSj&TX?{EbAa=#^P-VbaDsrv>$aeF{xZ}rS%al#oC8s^)4Dj0 z2c^``+9~Q{FiEsJ2g=VB^CFKHoaL~nyJDxb;38EnTd)Zn;iD-7ckhg$Cp{fE+0pI? z_uhKbN74faPmNMFg-$8303hApVeGx-3m;I&`~Ez2tSe>Wo>!xYrA>eU3l=ZC{6{zc zVc!@2@!MAff}v8Zivlp)yN6OHr31;a5paT2I0MBGw#a^zf2akq!wO@0k;e+U*aSep z7(BiZmYs1PmYsPXIG(e^j*DZo3V?FXF8_U!?pFNWc{_+S##OC;Sy_1Da^4eO006PH ziF y$7^Cw|wEfYPA1}sbhzeChp!j zj=016-5y`Xji39 79&I1coc*a?8#>lkR~hZn5;(? zi^%-L&X3cHtr-I>(}Zc+VKbEG^|Aae^6S~#(gMJWqv$6SBSd4~nr+g;ixX1Ks`Cgh zdH_2+`ktNRIFy_YDmB{w#NJzOdT+A#fOed-=aWjO1+V}h(Y;UId+QgkR^vm@P8~ax zFmdnBD3V$G#u7rfWvkY{|37cOqwU{+aobmyuU_YwQpZ(ioY0$$jl(i12rt@ViCVCz z6VX}x=Www?EW4w)vqHD8iJ~5$6N>#L(N>Un`DK^@vTdW70C6$M83SX)u;k!gQh)Y7 zWx;u8@}BTQINDt@YvR70Q5;N^09AbO*}b=Z@#;iZ^NFcFbOPzL0TuwnJNM-F-g?s& zT72Y%sblSN1NZKXB9WcA!LlU#FMap5Ke*-I#}575PyXj~E7q*{3WC4@u&kkVXOc-6 zstQ4N!!k`LveR-njA<*=4xsYZ@q8f 3@62cc)a58JZP;FD4$^i7l@C$oy{o)nz&ONiOn0Qj@l-RM3MxjL; zJgYzcvnOO<*`}%WO_zm4T(= TXe{}EfZoREh&^Ddb7`p4dU;3u( zuZUp0rxhGOxsOfp#TS>DEJP8oqDa&Nhk*l-Ja?MhJ&ZA{AU-F61si;M?#1yLs+8>` z;RT`)s9wSG; g1|BQp&>+k3F>u}s@G&ziL>mozL}UOUwOs=!FTly^QX zf-59iOsFT$7i#~LpAAk{=JN*93C;!B!F|OFc^-%yAs~daEKVM<+~u9{*H;PNvIQjH z&~OT+RSWm;jH0=#h%gWpfWPC-Oaas z`TVh#mri&}{E4R18dv~OzUsoz$`Aj?Gop8Li6j76S0Ul*brHCgqpOMxlv%2pGE<}7 z3Q@;-BjM+abRA)4fH5kPLJ$;+EZ+Hzi-Cj*klAC5<9UEFW>71a%UNSNlMGpMP?JJ+ zez-#8CR|k!6nTqb-$SM z3YT3^h*Hz;P+)T^!gB-wPZ;4D;rQvblV(Rb-NM7W;@CN)PE*v4Y@)U0_g_C}c+XSg zZx&DiZz5oU5LB(ZynNa9-+M`PO$HYMu%TMUm21OLj+b+tVp4UAM|MZCeQ-LbveZ<^ z{y%) yr_v5rWLVd(Y0jJDqOFXx$Rx^vPHfE`0R{<0?utwbrr)0H%X z;?H|x*fBU=r!uv4XUm=ca^BEue}2<}3V1UC%b~%Yj}Euq^PO|3mYrNPlQC=^(D3-) z_?rS;no05a-Z-`msFR#b0AOj^-qw4*bMD~IM^8xmkyAl$I$(h@3~YaJp!L4*o@42` z{;9(+_2uwHa~!&P`hrV0DW2F9$4mXwYl2#OuD|WR@18TT?ZG)W{63ZR<^vW0FowRZ z_w}^h``s;5!Np)_{yf Uu Lz~o5fq~(L9u-gTkHa{PIG15EJhMN6=X;v0}HUh_2Qj}I{x&Z=TSo&DITH#p6klunU=(90WQ;Gc%~(eXS+&)N*n2T z=tt-Gy?EE5Y28}ir1a(n763*mdY=DXd&fgRI-i {_Fy38u8*W%77<3 zvv{fX)PT#R3@;r>;EBW2>wq%Lh#&g%&oAzN`nHz05~zT;2(SPfTwPDy(%kvjFE3`+ zbZ|X(FoT!clCbC-2QG^;yxf|=V~0v`D$7V7e(aZ*bUk^?-nSa4fVU8^02^F~AOF?s zhyU`+i>YN!iU6 &aigV`>W)ivfS`$Y6WN$px218Me2l@MuRGQx8KeE8X?f|6bbp z`2W66ty7+*b<*f92Q0wON M1Fo}oT( IZU>70jc<4vZ^}cw=HDGj7CW}FVKeeXt zdS|*QB6JSNq71t_GkEYo5>w4)j8V1sh2LM*@z9T-d!s7qooaeZ0}BACp`+u0|9GPB zrMs`2+SI_H3=g!VuzQZ+q72y6mB#)1lQ5<-Dn`}*m+$_Y_6L6O#9s@jfWHD@0f41z zX#3;$9_f4O?)PE}xOB?!$Nfp{>B`IsT#NyGx>C4re+v3EO`YofTkrmxw)?*Ku%(~) z4qK-){Z#-9u))>-$L~MVzwQ3N#gryeItBi?FNx-!%yGHt7-MMePUDXyK*bo<2e#jT zecQd?|EmKP@K*#Z!0xHode3+6AAI$pk1#eFTpDG#uQ`GJy_snyf>Oj7!~WhZ?%kJ! zHno}_we;bgkKB0Rp6}de>8D+i@*6^bRlouOOUvQFUEjKM__arGWSHEvQ?-D5_9k$k zuS6TRVq(C7zAWz9n}9kMRG{YY>wo@4%U%ES2TMCGla${O`l|yL0GPQ9TJHSD??!h& z`I)KU%2^Ee>`9=lKZ{awkpXBO$l{(oCF*{Hnxng){9MbO-~64KJ8hGc-w^t%1QuX} zYv1p_cI)Wwr#=r%cI9O)hP!sh(K?XD y$vjfBwvWEy5Xl^D_gqxy9|@T