diff --git a/configs/config.py b/configs/config.py index d6b6af8e..132f111d 100644 --- a/configs/config.py +++ b/configs/config.py @@ -7,7 +7,7 @@ except ModuleNotFoundError: # 是否使用配置文件 -USE_CONFIG_FILE = False +USE_CONFIG_FILE = True # API KEY(必要) diff --git a/models/group_remind.py b/models/group_remind.py index 8437ab8a..9f93e64f 100644 --- a/models/group_remind.py +++ b/models/group_remind.py @@ -6,9 +6,9 @@ class GroupRemind(db.Model): id = db.Column(db.Integer(), primary_key=True) group_id = db.Column(db.BigInteger(), nullable=False) - hy = db.Column(db.Boolean(), default=True) # 进群欢迎 - kxcz = db.Column(db.Boolean(), default=True) # 开箱重置 - zwa = db.Column(db.Boolean(), default=True) # 早晚安 + hy = db.Column(db.Boolean(), default=False) # 进群欢迎 + kxcz = db.Column(db.Boolean(), default=False) # 开箱重置 + zwa = db.Column(db.Boolean(), default=False) # 早晚安 gb = db.Column(db.Boolean(), default=True) # 广播 blpar = db.Column(db.Boolean(), default=True) # bilibili转发解析 pa = db.Column(db.Boolean(), default=True) # 爬 diff --git a/plugins/admin_bot_manage/__init__.py b/plugins/admin_bot_manage/__init__.py index 47cf97f4..c8322843 100644 --- a/plugins/admin_bot_manage/__init__.py +++ b/plugins/admin_bot_manage/__init__.py @@ -31,7 +31,7 @@ group_status = on_command('oc_reminds', aliases={'开启早晚安', '关闭早 '开启丢人爬', '关闭丢人爬', '开启原神黄历提醒', '关闭原神黄历提醒', '开启全部通知', '开启所有通知', '关闭全部通知', '关闭所有通知', - '群通知状态'}, permission=GROUP, priority=4, block=True) + '群通知状态'}, permission=GROUP, priority=1, block=True) switch_rule = on_command('switch_rule', aliases=cmds, permission=GROUP, priority=4, block=True) custom_welcome = on_command('自定义进群欢迎消息', aliases={'自定义欢迎消息', '自定义群欢迎消息'}, permission=GROUP, priority=5, block=True) diff --git a/plugins/ai/data_source.py b/plugins/ai/data_source.py index 6280a386..732e7299 100644 --- a/plugins/ai/data_source.py +++ b/plugins/ai/data_source.py @@ -82,7 +82,7 @@ async def get_qqbot_chat_result(text: str, img_url: str, user_id: int, user_name return '' resp_payload = json.loads(await response.text()) if resp_payload['intent']: - if resp_payload['intent']['code'] == 4003: + if resp_payload['intent']['code'] != 0: index += 1 # 该AI很屑!!!!!!!!!!!! async with sess.get(f'http://api.qingyunke.com/api.php?key=free&appid=0&msg={text}') as res: diff --git a/plugins/bt/__init__.py b/plugins/bt/__init__.py index cd9a16e1..29989780 100644 --- a/plugins/bt/__init__.py +++ b/plugins/bt/__init__.py @@ -7,21 +7,16 @@ from nonebot.adapters.cqhttp import PrivateMessageEvent from util.utils import get_message_text from nonebot.adapters.cqhttp.permission import PRIVATE from util.utils import UserExistLimiter +from asyncio.exceptions import TimeoutError __plugin_name__ = '磁力搜索' __plugin_usage__ = r""" * 请各位使用后不要转发 * -* 有时可能搜不到,再试一次就行了 * -参数: -U(时间) -H(热度) -S(大小) - -V(仅视频) -P(仅图片) -A(仅压缩包) - -R (R18懂的都懂) - num(页数, 如果不知道页数请不要填,并且是倒叙,比如页数总数是29,你想查看第一页的内容, 就使用 bt 29 xxx) --按相关度检索(默认) -bt [关键词] --按更新时间检索(参数不区分大小写,但要注意空格) -bt -U [关键词] --搜索第10页数 -bt 10(倒着) [关键词] +* 拒绝反冲斗士! * +bt [关键词] [页数](默认为1) +示例: +bt 钢铁侠 +bt 钢铁侠 3 """.strip() _ulmt = UserExistLimiter() @@ -36,16 +31,8 @@ async def _(bot: Bot, event: PrivateMessageEvent, state: T_State): msg = get_message_text(event.json()) if not msg: await bt.reject('你想搜索什么呢?', at_sender=True) - mp = msg.split(" ") - if len(mp) > 1: - args = '' - for i in range(len(mp) - 1): - args += mp[i] + ' ' - state['args'] = args - state['bt'] = mp[1] - else: - state['bt'] = get_message_text(event.json()) - state['args'] = '' + state['keyword'] = msg + state['page'] = '1' @bt.handle() @@ -55,41 +42,37 @@ async def _(bot: Bot, event: PrivateMessageEvent, state: T_State): if _ulmt.check(event.user_id): await bt.finish('您有bt任务正在进行,请等待结束.', at_sender=True) mp = get_message_text(event.json()).split(" ") - if len(mp) > 1: - args = '' - for i in range(len(mp) - 1): - args += mp[i] + ' ' - state['args'] = args.strip() - state['bt'] = mp[-1] + if len(mp) == 2: + state['keyword'] = mp[0] + state['page'] = mp[1] else: - state['bt'] = get_message_text(event.json()) - state['args'] = '' + state['keyword'] = mp[0] + state['page'] = '1' -@bt.got('bt', prompt='虚空磁力?查什么GKD') +@bt.got('keyword', prompt='虚空磁力?查什么GKD') async def _(bot: Bot, event: PrivateMessageEvent, state: T_State): _ulmt.set_True(event.user_id) - keyword = state['bt'] - args = state['args'] + keyword = state['keyword'] + page = state['page'] await bt.send('开始搜索....', at_sender=True) + send_flag = False try: - if args.find('-R') == -1 and args.find('-r') == -1: - bt_report = await get_bt_info(keyword, args) - else: - bt_report = await get_bt_info(keyword, args, '0') - if bt_report: - if len(bt_report.split("\n")) < 2: - await bt.finish(bt_report + '搜索失败了,再试一次也许能成', at_sender=True) - else: - await bt.send("如果有页数没资源请再试一次\n" + bt_report) - logger.info( - f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'})" - f" 搜索bt {args} {keyword}") - else: - logger.error("没查询到资源") - await bt.send("没有查询到资源(也有可能是超时,再试一次?)", at_sender=True) - _ulmt.set_False(event.user_id) - except Exception as e: - _ulmt.set_False(event.user_id) - await bt.send("bt出错啦,再试一次?", at_sender=True) - logger.info(f'bt {keyword} 出错 e:{e}') + async for title, itype, create_time, file_size, link in get_bt_info(keyword, page): + await bt.send(f'标题:{title}\n' + f'类型:{itype}\n' + f'创建时间:{create_time}\n' + f'文件大小:{file_size}\n' + f'种子:{link}') + send_flag = True + except TimeoutError: + pass + if not send_flag: + await bt.send(f'{keyword} 超时或未搜索到...') + logger.info(f'USER {event.user_id} BT搜索 {keyword} 第 {page} 页') + _ulmt.set_False(event.user_id) + + + + + diff --git a/plugins/bt/data_source.py b/plugins/bt/data_source.py index 8115cb71..1b99c144 100644 --- a/plugins/bt/data_source.py +++ b/plugins/bt/data_source.py @@ -1,96 +1,41 @@ from util.user_agent import get_user_agent import aiohttp -from lxml import etree -from lxml.etree import Element from configs.config import MAXINFO_BT -from urllib import parse -from html import unescape -from util.utils import get_local_proxy, is_number -import time +from bs4 import BeautifulSoup +from util.utils import get_local_proxy import platform if platform.system() == 'Windows': import asyncio asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) -url = 'https://www.btmet.com/search.php' +url = 'http://www.eclzz.world' -async def get_bt_info(keyword: str, args: str, r18: str = '1') -> str: - cookiesDit = { - 'r18': r18 - } - s_time = time.time() - params = get_params(keyword, args) - async with aiohttp.ClientSession(headers=get_user_agent(), cookies=cookiesDit) as session: - async with session.get(url, proxy=get_local_proxy(), params=params, timeout=30) as response: - html = etree.HTML(await response.text()) - print(response.url) - num = html.xpath('//div[@id="wall"]//span/b/text()')[0] - print(num) - if num.find(",") != -1: - num = num.split(',')[0] - if num == '0': - return "没有找到记录" - - div_all = html.xpath('//div[@class="search-item"]')[1:] - div_all = div_all[:MAXINFO_BT] if len(div_all) > MAXINFO_BT else div_all - line_list = [await get_item_line(div) for div in div_all] - clist = [] - for line in line_list: - if line.strip() != '': - clist.append(line) - - return f"搜索 {keyword} 结果(共 {int(int(num.text) / 10) if int(num) % 10 == 0 else int(int(num) / 10) + 1} " \ - f"页)(耗时 {int(time.time() - s_time)} 秒):\n" + "\n\n".join(clist) +async def get_bt_info(keyword: str, page: str): + async with aiohttp.ClientSession(headers=get_user_agent()) as session: + async with session.get(f"{url}/s/{keyword}_rel_{page}.html", proxy=get_local_proxy(), timeout=5) as response: + text = await response.text() + if text.find('大约0条结果') != -1: + return + soup = BeautifulSoup(text, 'lxml') + item_lst = soup.find_all('div', {'class': 'search-item'}) + for item in item_lst[:MAXINFO_BT]: + divs = item.find_all('div') + title = str(divs[0].find('a').text).replace('', '').replace('', '').strip() + spans = divs[2].find_all('span') + itype = spans[0].text + create_time = spans[1].find('b').text + file_size = spans[2].find('b').text + link = await get_download_link(divs[0].find('a')['href'], session) + yield title, itype, create_time, file_size, link -async def get_item_line(div: Element) -> str: - try: - magent = div.xpath('./div[2]/a/@href')[0] - size = div.xpath('./div[@class="f_left"]/div[@class="item-bar"]/span/b/font/text()')[0] - type = div.xpath('./div[@class="f_left"]/div[@class="item-bar"]/span[@class="cpill blue-pill"]/text()')[0].strip() - - title_doc = div.xpath('.//a[@class="smashTitle"]//text()')[0] - title_code = title_doc[title_doc.find('("') + 2: title_doc.find('")')] - title_xml_code = parse.unquote(title_code) - title_xml = etree.HTML(unescape(title_xml_code)) - title = title_xml.xpath('string(.)') - except Exception: - return '' - return "【{}】| {}\n【{}】| {}".format(type, title, size, magent) +async def get_download_link(_url: str, session) -> str: + async with session.get(f"{url}{_url}", proxy=get_local_proxy(), timeout=30) as response: + soup = BeautifulSoup(await response.text(), 'lxml') + return soup.find('a', {'id': 'down-url'})['href'] -# https://www.btmet.com/search.php?q=%E9%92%A2%E9%93%81%E4%BE%A0&c=5&o=0&l=&p=2 -def get_params(keyword: str, args: str) -> dict: - params = { - 'q': keyword, - 'c': '', - 'l': '', - 'o': 0, - 'p': '' - } - if not args: - return params - args = args.split(" ") - for arg in args: - if '-U' == arg.upper(): - params['o'] = 1 - if '-S' == arg.upper(): - params['o'] = 2 - if '-H' == arg.upper(): - params['o'] = 3 - if '-V' == arg.upper(): - params['c'] = 1 - if '-P' == arg.upper(): - params['c'] = 2 - if '-A' == arg.upper(): - params['c'] = 5 - if is_number(arg): - params['p'] = arg - return params - - -# print(asyncio.get_event_loop().run_until_complete(get_bt_info('钢铁侠', ''))) diff --git a/plugins/draw_card/__init__.py b/plugins/draw_card/__init__.py index 52fa2299..8735f886 100644 --- a/plugins/draw_card/__init__.py +++ b/plugins/draw_card/__init__.py @@ -1,29 +1,33 @@ from nonebot import on_regex, on_keyword -from nonebot.adapters.cqhttp import Bot, MessageEvent +from nonebot.adapters.cqhttp import Bot, MessageEvent, Message 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 .genshin_handle import genshin_draw, update_genshin_info, reset_count, reload_genshin_pool +from .prts_handle import update_prts_info, prts_draw, reload_prts_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 .azur_handle import update_azur_info, azur_draw +from .fgo_handle import update_fgo_info, fgo_draw +from .onmyoji_handle import update_onmyoji_info, onmyoji_draw from .update_game_info import update_info -from .util import check_num +from .util import is_number, check_num from .rule import is_switch -from .config import PRTS_FLAG, PRETTY_FLAG, GUARDIAN_FLAG, GENSHIN_FLAG, PCR_FLAG - - +from .config import PRTS_FLAG, PRETTY_FLAG, GUARDIAN_FLAG, GENSHIN_FLAG, PCR_FLAG, AZUR_FLAG, FGO_FLAG, ONMYOJI_FLAG +from .async_update_game_info import async_update_game +import re +import asyncio +from util.utils import scheduler +from services.log import logger 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) +prts_up_reload = on_keyword({'重载方舟卡池'}, priority=1, 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 = on_regex('.*?原神(武器|角色)?池?[1-9|一][0-9]{0,2}[抽|井]', rule=is_switch('genshin'), priority=5, block=True) genshin_update = on_keyword({'更新原神信息'}, permission=SUPERUSER, priority=1, block=True) +genshin_reset = on_keyword({'重置原神抽卡'}, priority=1, block=True) +genshin_up_reload = on_keyword({'重载原神卡池'}, priority=1, 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) @@ -31,15 +35,17 @@ pretty_update = on_keyword({'更新马娘信息', '更新赛马娘信息'}, perm 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 = 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) +azur = on_regex('.*?碧蓝航?线?(轻型|重型|特型)池?[1-9|一][0-9]{0,2}[抽]', rule=is_switch('azur'), priority=5, block=True) +azur_update = on_keyword({'更新碧蓝信息', '更新碧蓝航线信息'}, permission=SUPERUSER, priority=1, block=True) +fgo = on_regex('.*?fgo[1-9|一][0-9]{0,2}[抽]', rule=is_switch('fgo'), priority=5, block=True) +fgo_update = on_keyword({'更新fgo信息'}, permission=SUPERUSER, priority=1, block=True) -@test.handle() -async def _(bot: Bot, event: MessageEvent, state: T_State): - await update_pcr_info() +onmyoji = on_regex('.*?阴阳师[1-9|一][0-9]{0,2}[抽]', rule=is_switch('onmyoji'), priority=5, block=True) +onmyoji_update = on_keyword({'更新阴阳师信息'}, permission=SUPERUSER, priority=1, block=True) @prts.handle() @@ -56,28 +62,46 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): else: return await prts.send(await prts_draw(int(num)), at_sender=True) + logger.info( + f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'}) 方舟 {num}抽") -@prts_reload.handle() +@prts_up_reload.handle() async def _(bot: Bot, event: MessageEvent, state: T_State): - await reload_pool() - await prts_reload.finish('重载完成!') + text = await reload_prts_pool() + await prts_up_reload.finish(Message(f'重载完成!\n{text}')) @genshin.handle() async def _(bot: Bot, event: MessageEvent, state: T_State): msg = str(event.get_message()).strip() - if msg in ['原神一井', '原神1井']: - num = 180 - else: - rmsg = re.search(r'.*?原神(.*)抽', msg) - if rmsg: - num, flag = check_num(rmsg.group(1), 180) + rmsg = re.search(r'.*?原神(武器|角色)?池?(.*)[抽|井]', msg) + if rmsg: + pool_name = rmsg.group(1) + if pool_name == '武器': + pool_name = 'arms' + elif pool_name == '角色': + pool_name = 'char' + else: + pool_name = '' + num = rmsg.group(2) + if msg.find('一井') != -1 or msg.find('1井') != -1: + num = 180 + else: + num, flag = check_num(num, 180) if not flag: await genshin.finish(num, at_sender=True) - else: - return - await genshin.send(await genshin_draw(event.user_id, int(num)), at_sender=True) + else: + return + await genshin.send(await genshin_draw(event.user_id, int(num), pool_name), at_sender=True) + logger.info( + f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'}) 原神 {num}抽") + + +@genshin_up_reload.handle() +async def _(bot: Bot, event: MessageEvent, state: T_State): + text = await reload_genshin_pool() + await genshin_reset.finish(Message(f'重载成功!\n{text}')) @genshin_reset.handle() @@ -110,6 +134,8 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): else: return await pretty.send(await pretty_draw(int(num), pool_name), at_sender=True) + logger.info( + f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'}) 赛马娘 {num}抽") @guardian.handle() @@ -133,6 +159,8 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): else: return await guardian.send(await guardian_draw(int(num), pool_name), at_sender=True) + logger.info( + f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'}) 坎公骑冠剑 {num}抽") @pcr.handle() @@ -149,12 +177,59 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): else: return await pcr.send(await pcr_draw(int(num)), at_sender=True) + logger.info( + f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'}) 公主连结 {num}抽") + + +@azur.handle() +async def _(bot: Bot, event: MessageEvent, state: T_State): + msg = str(event.get_message()).strip() + rmsg = re.search('.*?碧蓝航?线?(轻型|重型|特型)池?(.*)[抽]', msg) + if rmsg: + pool_name = rmsg.group(1) + num, flag = check_num(rmsg.group(2), 300) + if not flag: + await azur.finish(num, at_sender=True) + else: + return + await azur.send(await azur_draw(int(num), pool_name), at_sender=True) + logger.info( + f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'}) 碧蓝航线 {num}抽") + + +@fgo.handle() +async def _(bot: Bot, event: MessageEvent, state: T_State): + msg = str(event.get_message()).strip() + rmsg = re.search('.*?fgo(.*)抽', msg) + if rmsg: + num, flag = check_num(rmsg.group(1), 300) + if not flag: + await fgo.finish(num, at_sender=True) + else: + return + await fgo.send(await fgo_draw(int(num)), at_sender=True) + logger.info( + f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'}) fgo {num}抽") + + +@onmyoji.handle() +async def _(bot: Bot, event: MessageEvent, state: T_State): + msg = str(event.get_message()).strip() + rmsg = re.search('.*?阴阳师(.*)抽', msg) + if rmsg: + num, flag = check_num(rmsg.group(1), 300) + if not flag: + await onmyoji.finish(num, at_sender=True) + else: + return + await onmyoji.send(await onmyoji_draw(int(num)), at_sender=True) + logger.info( + f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'}) 阴阳师 {num}抽") @prts_update.handle() async def _(bot: Bot, event: MessageEvent, state: T_State): await update_prts_info() - await reload_pool() await prts_update.finish('更新完成!') @@ -182,6 +257,24 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): await genshin_update.finish('更新完成!') +@azur_update.handle() +async def _(bot: Bot, event: MessageEvent, state: T_State): + await update_azur_info() + await genshin_update.finish('更新完成!') + + +@fgo_update.handle() +async def _(bot: Bot, event: MessageEvent, state: T_State): + await update_fgo_info() + await genshin_update.finish('更新完成!') + + +@onmyoji_update.handle() +async def _(bot: Bot, event: MessageEvent, state: T_State): + await update_onmyoji_info() + await genshin_update.finish('更新完成!') + + # 更新资源 @scheduler.scheduled_job( 'cron', @@ -189,34 +282,28 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): minute=1, ) async def _(): - try: - if PRTS_FLAG: - await update_prts_info() - except Exception as e: - logger.error(f'draw_card: 更新 明日方舟 失败 e:{e}') - try: - if GENSHIN_FLAG: - await update_genshin_info() - except Exception as e: - logger.error(f'draw_card: 更新 原神 失败 e:{e}') - try: - if PRETTY_FLAG: - await update_pretty_info() - except Exception as 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}') + tasks = [] + if PRTS_FLAG: + tasks.append(asyncio.ensure_future(update_prts_info())) + if GENSHIN_FLAG: + tasks.append(asyncio.ensure_future(update_genshin_info())) + if PRETTY_FLAG: + tasks.append(asyncio.ensure_future(update_pretty_info())) + if GUARDIAN_FLAG: + tasks.append(asyncio.ensure_future(update_guardian_info())) + if PCR_FLAG: + tasks.append(asyncio.ensure_future(update_pcr_info())) + if AZUR_FLAG: + tasks.append(asyncio.ensure_future(update_azur_info())) + if FGO_FLAG: + tasks.append(asyncio.ensure_future(update_fgo_info())) + if ONMYOJI_FLAG: + tasks.append(asyncio.ensure_future(update_onmyoji_info())) + await asyncio.gather(*tasks) + logger.info('draw_card 抽卡自动更新完成...') -# 每天四点重载up卡池 +# 每天四点重载方舟up卡池 @scheduler.scheduled_job( 'cron', hour=4, @@ -224,5 +311,19 @@ async def _(): ) async def _(): if PRTS_FLAG: - await reload_pool() - logger.info(f'draw_card: 04: 01 重载方舟卡池') + await reload_prts_pool() + logger.info('自动重载方舟卡池UP成功') + + +# 每天下午六点点重载原神up卡池 +@scheduler.scheduled_job( + 'cron', + hour=18, + minute=1, +) +async def _(): + if PRTS_FLAG: + await reload_genshin_pool() + logger.info('自动重载原神卡池UP成功') + + diff --git a/plugins/draw_card/announcement.py b/plugins/draw_card/announcement.py index 41ab5082..bf4e6583 100644 --- a/plugins/draw_card/announcement.py +++ b/plugins/draw_card/announcement.py @@ -3,7 +3,6 @@ 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 try: import ujson as json @@ -12,9 +11,53 @@ except ModuleNotFoundError: 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_up_char = Path(DRAW_PATH + "/draw_card_up/prts_up_char.json") +genshin_up_char = Path(DRAW_PATH + "/draw_card_up/genshin_up_char.json") prts_url = "https://wiki.biligame.com/arknights/%E6%96%B0%E9%97%BB%E5%85%AC%E5%91%8A" +genshin_url = "https://wiki.biligame.com/ys/%E7%A5%88%E6%84%BF" + + +# 是否过时 +def is_expired(data: dict): + times = data['time'].split('-') + for i in range(len(times)): + times[i] = str(datetime.now().year) + '-' + times[i].split('日')[0].strip().replace('月', '-') + start_date = datetime.strptime(times[0], '%Y-%m-%d').date() + end_date = datetime.strptime(times[1], '%Y-%m-%d').date() + now = datetime.now().date() + return start_date < now < end_date + + +# 检查写入 +def check_write(data: dict, up_char_file, game_name: str = ''): + tmp = data + if game_name == 'genshin': + tmp = data['char'] + if not is_expired(tmp): + if game_name == 'genshin': + data['char']['title'] = '' + data['arms']['title'] = '' + else: + data['title'] = '' + else: + with open(up_char_file, 'w', encoding='utf8') as f: + json.dump(data, f, indent=4, ensure_ascii=False) + if not up_char_file.exists(): + with open(up_char_file, 'w', encoding='utf8') as f: + json.dump(data, f, indent=4, ensure_ascii=False) + else: + with open(up_char_file, 'r', encoding='utf8') as f: + old_data = json.load(f) + tmp = old_data + if game_name == 'genshin': + tmp = old_data['char'] + if is_expired(tmp): + return old_data + else: + with open(up_char_file, 'w', encoding='utf8') as f: + json.dump(data, f, indent=4, ensure_ascii=False) + return data def _get_up_char(r: str, text: str): @@ -39,13 +82,13 @@ class PrtsAnnouncement: if a.text.find('寻访') != -1: url = a.get('href') break - async with session.get(f'https://wiki.biligame.com/{url}', proxy=get_local_proxy(), timeout=7) as res: + async with session.get(f'https://wiki.biligame.com/{url}', timeout=7) as res: return await res.text(), a.text[:-4] @staticmethod async def update_up_char(): - up_char_file.parent.mkdir(parents=True, exist_ok=True) - data = {'up_char': {'6': {}, '5': {}, '4': {}}, 'title': '', 'time': ''} + prts_up_char.parent.mkdir(parents=True, exist_ok=True) + data = {'up_char': {'6': {}, '5': {}, '4': {}}, 'title': '', 'time': '', 'pool_img': ''} text, title = await PrtsAnnouncement.get_announcement_text() soup = BeautifulSoup(text, 'lxml') data['title'] = title @@ -87,34 +130,66 @@ class PrtsAnnouncement: char = char.replace('[限定]', '').replace('[', '').replace(']', '') data['up_char'][star][char.strip()] = f'权{weight}' # data['time'] = '03月09日16:00 - 05月23日03:59' - if not is_expired(data): - data['title'] = '' - else: - with open(up_char_file, 'w', encoding='utf8') as f: - json.dump(data, f, indent=4, ensure_ascii=False) - if not up_char_file.exists(): - with open(up_char_file, 'w', encoding='utf8') as f: - json.dump(data, f, indent=4, ensure_ascii=False) - else: - with open(up_char_file, 'r', encoding='utf8') as f: - old_data = json.load(f) - if is_expired(old_data): - return old_data - else: - with open(up_char_file, 'w', encoding='utf8') as f: - json.dump(data, f, indent=4, ensure_ascii=False) - return data + return check_write(data, prts_up_char) + + +class GenshinAnnouncement: + + @staticmethod + async def get_announcement_text(): + async with aiohttp.ClientSession(headers=headers) as session: + async with session.get(genshin_url, timeout=7) as res: + return await res.text() + + @staticmethod + async def update_up_char(): + genshin_up_char.parent.mkdir(exist_ok=True, parents=True) + data = { + 'char': {'up_char': {'5': {}, '4': {}}, 'title': '', 'time': '', 'pool_img': ''}, + 'arms': {'up_char': {'5': {}, '4': {}}, 'title': '', 'time': '', 'pool_img': ''} + } + text = await GenshinAnnouncement.get_announcement_text() + soup = BeautifulSoup(text, 'lxml') + try: + div = soup.find_all('div', {'class': 'row'})[1] + tables = div.find_all('table', {'class': 'wikitable'}) + for table in tables: + trs = table.find('tbody').find_all('tr') + pool_img = trs[0].find('th').find('img') + if pool_img['title'].find('角色活动') == -1: + itype = 'arms' + else: + itype = 'char' + try: + data[itype]['pool_img'] = str(pool_img['srcset']).split(' ')[0] + except KeyError: + data[itype]['pool_img'] = pool_img['src'] + data[itype]['title'] = str(pool_img['title']).split(f'期{"角色" if itype == "char" else "武器"}')[0][:-3] + data[itype]['time'] = trs[1].find('td').text + if data[itype]['time'][-1] == '\n': + data[itype]['time'] = data[itype]['time'][:-1] + tmp = '' + for tm in data[itype]['time'].split('~'): + date_time_sp = tm.split('/') + date_time_sp[2] = date_time_sp[2].strip().replace(' ', '日 ') + tmp += date_time_sp[1] + '月' + date_time_sp[2] + ' - ' + data[itype]['time'] = tmp[:-2].strip() + for a in trs[2].find('td').find_all('a'): + char_name = a['title'] + data[itype]['up_char']['5'][char_name] = "50" + for a in trs[3].find('td').find_all('a'): + char_name = a['title'] + data[itype]['up_char']['4'][char_name] = "50" + except Exception as e: + print(f'更新原神UP失败,疑似UP池已结束, e:{e}') + with open(genshin_up_char, 'r', encoding='utf8') as f: + data = json.load(f) + data['char']['title'] = '' + data['arms']['title'] = '' + with open(genshin_up_char, 'w', encoding='utf8') as wf: + json.dump(data, wf, ensure_ascii=False, indent=4) + return data + return check_write(data, genshin_up_char, 'genshin') -# 是否过时 -def is_expired(data: dict): - times = data['time'].split('-') - for i in range(len(times)): - times[i] = str(datetime.now().year) + '-' + times[i].split('日')[0].strip().replace('月', '-') - start_date = datetime.strptime(times[0], '%Y-%m-%d').date() - end_date = datetime.strptime(times[1], '%Y-%m-%d').date() - now = datetime.now().date() - return start_date < now < end_date -# ad = Announcement('https://wiki.biligame.com/arknights/%E6%96%B0%E9%97%BB%E5%85%AC%E5%91%8A') -# asyncio.get_event_loop().run_until_complete(check_up_char('prts')) diff --git a/plugins/draw_card/async_update_game_info.py b/plugins/draw_card/async_update_game_info.py new file mode 100644 index 00000000..949c5331 --- /dev/null +++ b/plugins/draw_card/async_update_game_info.py @@ -0,0 +1,65 @@ +import asyncio +import nonebot +import os +from .pcr_handle import update_pcr_info, init_pcr_data +from .azur_handle import update_azur_info, init_azur_data +from .prts_handle import update_prts_info, init_prts_data +from .pretty_handle import update_pretty_info, init_pretty_data +from .guardian_handle import update_guardian_info, init_guardian_data +from .genshin_handle import update_genshin_info, init_genshin_data +from .fgo_handle import update_fgo_info, init_fgo_data +from .onmyoji_handle import update_onmyoji_info, init_onmyoji_data +from .config import DRAW_PATH, PRTS_FLAG, PRETTY_FLAG, GUARDIAN_FLAG, PCR_FLAG, AZUR_FLAG, GENSHIN_FLAG, FGO_FLAG, \ + ONMYOJI_FLAG + + +driver: nonebot.Driver = nonebot.get_driver() + + +@driver.on_startup +async def async_update_game(): + tasks = [] + init_lst = [init_pcr_data, init_pretty_data, init_azur_data, init_prts_data, init_genshin_data, init_guardian_data, + init_fgo_data, init_onmyoji_data] + if PRTS_FLAG and not os.path.exists(DRAW_PATH + 'prts.json'): + tasks.append(asyncio.ensure_future(update_prts_info())) + init_lst.remove(init_prts_data) + + if PRETTY_FLAG and (not os.path.exists(DRAW_PATH + 'pretty.json') or + not os.path.exists(DRAW_PATH + 'pretty_card.json')): + tasks.append(asyncio.ensure_future(update_pretty_info())) + init_lst.remove(init_pretty_data) + + if GUARDIAN_FLAG and not os.path.exists(DRAW_PATH + 'guardian.json'): + tasks.append(asyncio.ensure_future(update_guardian_info())) + + if PCR_FLAG and not os.path.exists(DRAW_PATH + 'pcr.json'): + tasks.append(asyncio.ensure_future(update_pcr_info())) + init_lst.remove(init_pcr_data) + + if GENSHIN_FLAG and (not os.path.exists(DRAW_PATH + 'genshin.json') or + not os.path.exists(DRAW_PATH + 'genshin_arms.json')): + tasks.append(asyncio.ensure_future(update_genshin_info())) + init_lst.remove(init_genshin_data) + + if AZUR_FLAG and not os.path.exists(DRAW_PATH + 'azur.json'): + tasks.append(asyncio.ensure_future(update_azur_info())) + init_lst.remove(init_azur_data) + + if FGO_FLAG and (not os.path.exists(DRAW_PATH + 'fgo.json') or + not os.path.exists(DRAW_PATH + 'fgo_card.json')): + tasks.append(asyncio.ensure_future(update_fgo_info())) + init_lst.remove(init_fgo_data) + + if ONMYOJI_FLAG and not os.path.exists(DRAW_PATH + 'onmyoji.json'): + tasks.append(asyncio.ensure_future(update_onmyoji_info())) + init_lst.remove(init_onmyoji_data) + + await asyncio.gather(*tasks) + for func in init_lst: + await func() + + + + + diff --git a/plugins/draw_card/azur_handle.py b/plugins/draw_card/azur_handle.py new file mode 100644 index 00000000..7c16c8e5 --- /dev/null +++ b/plugins/draw_card/azur_handle.py @@ -0,0 +1,63 @@ + +from nonebot.adapters.cqhttp import MessageSegment +import random +from .update_game_simple_info import update_simple_info +from .util import generate_img, init_star_rst, BaseData, set_list, get_star, max_card, format_card_information +from .config import AZUR_ONE_P, AZUR_TWO_P, AZUR_THREE_P, AZUR_FOUR_P, AZUR_FLAG, DRAW_PATH +from dataclasses import dataclass +from .init_card_pool import init_game_pool +try: + import ujson as json +except ModuleNotFoundError: + import json + +ALL_CHAR = [] + + +@dataclass +class AzurChar(BaseData): + itype: str # 舰娘类型 + + +async def azur_draw(count: int, pool_name: str): + # 0 1 2 + cnlist = ['金', '紫', '蓝', '白'] + star_list = [0, 0, 0, 0] + char_list, char_dict, max_star_list, star_list, max_star_index_list = \ + format_card_information(count, star_list, _get_azur_card, pool_name) + rst = init_star_rst(star_list, cnlist, max_star_list, max_star_index_list) + if count > 90: + char_list = set_list(char_list) + return MessageSegment.image("base64://" + await generate_img(char_list, 'azur', star_list)) \ + + '\n' + rst[:-1] + '\n' + max_card(char_dict) + + +async def update_azur_info(): + global ALL_CHAR + url = 'https://wiki.biligame.com/blhx/舰娘图鉴' + data, code = await update_simple_info(url, 'azur') + if code == 200: + ALL_CHAR = init_game_pool('azur', data, AzurChar) + + +async def init_azur_data(): + global ALL_CHAR + if AZUR_FLAG: + with open(DRAW_PATH + 'azur.json', 'r', encoding='utf8') as f: + azur_dict = json.load(f) + ALL_CHAR = init_game_pool('azur', azur_dict, AzurChar) + + +# 抽取卡池 +def _get_azur_card(pool_name: str): + global ALL_CHAR + if pool_name == '轻型': + itype = ['驱逐', '轻巡', '维修'] + elif pool_name == '重型': + itype = ['重巡', '战列', '战巡', '重炮'] + else: + itype = ['维修', '潜艇', '重巡', '轻航', '航母'] + star = get_star([4, 3, 2, 1], [AZUR_FOUR_P, AZUR_THREE_P, AZUR_TWO_P, AZUR_ONE_P]) + chars = [x for x in ALL_CHAR if x.star == star and x.itype in itype and not x.limited] + return random.choice(chars), 4 - star + diff --git a/plugins/draw_card/config.py b/plugins/draw_card/config.py index 619248e5..cfad980f 100644 --- a/plugins/draw_card/config.py +++ b/plugins/draw_card/config.py @@ -1,22 +1,30 @@ import nonebot from pathlib import Path -from configs.path_config import DRAW_PATH +from configs.path_config import DATA_PATH +from configs.config import FGO_FLAG, PCR_FLAG, AZUR_FLAG, PRTS_FLAG,\ + PRETTY_FLAG, GUARDIAN_FLAG, GENSHIN_FLAG, ONMYOJI_FLAG, PCR_TAI try: import ujson as json except ModuleNotFoundError: import json -DRAW_PATH = DRAW_PATH + +DRAW_PATH = DATA_PATH + '/draw_card/' _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_FLAG = PRTS_FLAG +GENSHIN_FLAG = GENSHIN_FLAG +PRETTY_FLAG = PRETTY_FLAG +GUARDIAN_FLAG = GUARDIAN_FLAG +PCR_FLAG = PCR_FLAG +AZUR_FLAG = AZUR_FLAG +FGO_FLAG = FGO_FLAG +ONMYOJI_FLAG = ONMYOJI_FLAG + +PCR_TAI = PCR_TAI # 方舟概率 PRTS_SIX_P = 0.02 @@ -65,12 +73,37 @@ PCR_ONE_P = 0.795 PCR_G_THREE_P = 0.025 PCR_G_TWO_P = 0.975 +# 碧蓝航线 +AZUR_FIVE_P = 0.012 +AZUR_FOUR_P = 0.07 +AZUR_THREE_P = 0.12 +AZUR_TWO_P = 0.51 +AZUR_ONE_P = 0.3 + +# FGO +FGO_SERVANT_FIVE_P = 0.01 +FGO_SERVANT_FOUR_P = 0.03 +FGO_SERVANT_THREE_P = 0.4 +FGO_CARD_FIVE_P = 0.04 +FGO_CARD_FOUR_P = 0.12 +FGO_CARD_THREE_P = 0.4 + +# 阴阳师 +ONMYOJI_SP = 0.0025 +ONMYOJI_SSR = 0.01 +ONMYOJI_SR = 0.2 +ONMYOJI_R = 0.7875 + + path_dict = { 'genshin': '原神', 'prts': '明日方舟', 'pretty': '赛马娘', 'guardian': '坎公骑冠剑', 'pcr': '公主连结', + 'azur': '碧蓝航线', + 'fgo': '命运-冠位指定', + 'onmyoji': '阴阳师', } driver: nonebot.Driver = nonebot.get_driver() @@ -82,7 +115,10 @@ config_default_data = { 'prts': '明日方舟', 'pretty': '赛马娘', 'guardian': '坎公骑冠剑', - 'PCR': '公主连结', + 'pcr': '公主连结', + 'azur': '碧蓝航线', + 'fgo': '命运-冠位指定', + 'onmyoji': '阴阳师', }, 'prts': { @@ -130,6 +166,30 @@ config_default_data = { 'PCR_TWO_P': 0.18, 'PCR_ONE_P': 0.795, }, + + 'azur': { + 'AZUR_FIVE_P': 0.012, + 'AZUR_FOUR_P': 0.07, + 'AZUR_THREE_P': 0.12, + 'AZUR_TWO_P': 0.51, + 'AZUR_ONE_P': 0.3, + }, + + 'fgo': { + 'FGO_SERVANT_FIVE_P': 0.01, + 'FGO_SERVANT_FOUR_P': 0.03, + 'FGO_SERVANT_THREE_P': 0.4, + 'FGO_CARD_FIVE_P': 0.04, + 'FGO_CARD_FOUR_P': 0.12, + 'FGO_CARD_THREE_P': 0.4, + }, + + 'onmyoji': { + 'ONMYOJI_SP': 0.0025, + 'ONMYOJI_SSR': 0.01, + 'ONMYOJI_SR': 0.2, + 'ONMYOJI_R': 0.7875, + } } @@ -141,7 +201,9 @@ def check_config(): 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 + PCR_THREE_P, PCR_TWO_P, PCR_ONE_P, AZUR_FOUR_P, AZUR_THREE_P, AZUR_TWO_P, AZUR_ONE_P, AZUR_FIVE_P, FGO_CARD_FIVE_P,\ + FGO_CARD_FOUR_P, FGO_CARD_THREE_P, FGO_SERVANT_THREE_P, FGO_SERVANT_FOUR_P, FGO_SERVANT_FIVE_P, ONMYOJI_R, ONMYOJI_SP, \ + ONMYOJI_SSR, ONMYOJI_SR _draw_config.parent.mkdir(parents=True, exist_ok=True) try: data = json.load(open(_draw_config, 'r', encoding='utf8')) @@ -227,6 +289,48 @@ def check_config(): data['pcr']['PCR_TWO_P'] = config_default_data['pcr']['PCR_TWO_P'] data['pcr']['PCR_ONE_P'] = config_default_data['pcr']['PCR_ONE_P'] + try: + AZUR_FIVE_P = float(data['azur']['AZUR_FIVE_P']) + AZUR_FOUR_P = float(data['azur']['AZUR_FOUR_P']) + AZUR_THREE_P = float(data['azur']['AZUR_THREE_P']) + AZUR_TWO_P = float(data['azur']['AZUR_TWO_P']) + AZUR_ONE_P = float(data['azur']['AZUR_ONE_P']) + except KeyError: + data['azur'] = {} + data['azur']['AZUR_FIVE_P'] = config_default_data['azur']['AZUR_FIVE_P'] + data['azur']['AZUR_FOUR_P'] = config_default_data['azur']['AZUR_FOUR_P'] + data['azur']['AZUR_THREE_P'] = config_default_data['azur']['AZUR_THREE_P'] + data['azur']['AZUR_TWO_P'] = config_default_data['azur']['AZUR_TWO_P'] + data['azur']['AZUR_ONE_P'] = config_default_data['azur']['AZUR_ONE_P'] + + try: + FGO_SERVANT_FIVE_P = float(data['fgo']['FGO_SERVANT_FIVE_P']) + FGO_SERVANT_FOUR_P = float(data['fgo']['FGO_SERVANT_FOUR_P']) + FGO_SERVANT_THREE_P = float(data['fgo']['FGO_SERVANT_THREE_P']) + FGO_CARD_FIVE_P = float(data['fgo']['FGO_CARD_FIVE_P']) + FGO_CARD_FOUR_P = float(data['fgo']['FGO_CARD_FOUR_P']) + FGO_CARD_THREE_P = float(data['fgo']['FGO_CARD_THREE_P']) + except KeyError: + data['fgo'] = {} + data['fgo']['FGO_SERVANT_FIVE_P'] = config_default_data['fgo']['FGO_SERVANT_FIVE_P'] + data['fgo']['FGO_SERVANT_FOUR_P'] = config_default_data['fgo']['FGO_SERVANT_FOUR_P'] + data['fgo']['FGO_SERVANT_THREE_P'] = config_default_data['fgo']['FGO_SERVANT_THREE_P'] + data['fgo']['FGO_CARD_FIVE_P'] = config_default_data['fgo']['FGO_CARD_FIVE_P'] + data['fgo']['FGO_CARD_FOUR_P'] = config_default_data['fgo']['FGO_CARD_FOUR_P'] + data['fgo']['FGO_CARD_THREE_P'] = config_default_data['fgo']['FGO_CARD_THREE_P'] + + try: + ONMYOJI_SP = float(data['onmyoji']['ONMYOJI_SP']) + ONMYOJI_SSR = float(data['onmyoji']['ONMYOJI_SSR']) + ONMYOJI_SR = float(data['onmyoji']['ONMYOJI_SR']) + ONMYOJI_R = float(data['onmyoji']['ONMYOJI_R']) + except KeyError: + data['onmyoji'] = {} + data['onmyoji']['ONMYOJI_SP'] = config_default_data['onmyoji']['ONMYOJI_SP'] + data['onmyoji']['ONMYOJI_SSR'] = config_default_data['onmyoji']['ONMYOJI_SSR'] + data['onmyoji']['ONMYOJI_SR'] = config_default_data['onmyoji']['ONMYOJI_SR'] + data['onmyoji']['ONMYOJI_R'] = config_default_data['onmyoji']['ONMYOJI_R'] + json.dump(data, open(_draw_config, 'w', encoding='utf8'), indent=4, ensure_ascii=False) diff --git a/plugins/draw_card/fgo_handle.py b/plugins/draw_card/fgo_handle.py new file mode 100644 index 00000000..f78aca24 --- /dev/null +++ b/plugins/draw_card/fgo_handle.py @@ -0,0 +1,112 @@ + +from nonebot.adapters.cqhttp import MessageSegment +import random +from .update_game_requests_info import update_requests_info +from .util import generate_img, init_star_rst, BaseData, set_list, get_star, max_card +from .config import FGO_CARD_FOUR_P, FGO_CARD_FIVE_P, FGO_CARD_THREE_P, FGO_SERVANT_THREE_P, \ + FGO_SERVANT_FIVE_P, FGO_SERVANT_FOUR_P, FGO_FLAG, DRAW_PATH +from dataclasses import dataclass +from .init_card_pool import init_game_pool + +try: + import ujson as json +except ModuleNotFoundError: + import json + +ALL_CHAR = [] +ALL_CARD = [] + + +@dataclass +class FgoChar(BaseData): + pass + + +async def fgo_draw(count: int): + # 0 1 2 + cnlist = ['★★★★★', '★★★★', '★★★'] + obj_list, obj_dict, max_star_list, star_list, max_star_index_list = _format_card_information(count) + rst = init_star_rst(star_list, cnlist, max_star_list, max_star_index_list) + if count > 90: + obj_list = set_list(obj_list) + return MessageSegment.image("base64://" + await generate_img(obj_list, 'fgo', star_list)) \ + + '\n' + rst[:-1] + '\n' + max_card(obj_dict) + + +async def update_fgo_info(): + global ALL_CHAR, ALL_CARD + data, code = await update_requests_info('fgo') + if code == 200: + ALL_CHAR = init_game_pool('fgo', data, FgoChar) + data, code = await update_requests_info('fgo_card') + if code == 200: + ALL_CARD = init_game_pool('fgo_card', data, FgoChar) + + +async def init_fgo_data(): + global ALL_CHAR, ALL_CARD + if FGO_FLAG: + with open(DRAW_PATH + 'fgo.json', 'r', encoding='utf8') as f: + fgo_dict = json.load(f) + ALL_CHAR = init_game_pool('fgo', fgo_dict, FgoChar) + with open(DRAW_PATH + 'fgo_card.json', 'r', encoding='utf8') as f: + fgo_dict = json.load(f) + ALL_CARD = init_game_pool('fgo', fgo_dict, FgoChar) + + +# 抽取卡池 +def _get_fgo_card(mode: int = 1): + global ALL_CHAR, ALL_CARD + if mode == 1: + star = get_star([8, 7, 6, 5, 4, 3], [FGO_SERVANT_FIVE_P, FGO_SERVANT_FOUR_P, FGO_SERVANT_THREE_P, + FGO_CARD_FIVE_P, FGO_CARD_FOUR_P, FGO_CARD_THREE_P]) + elif mode == 2: + star = get_star([5, 4], [FGO_CARD_FIVE_P, FGO_CARD_FOUR_P]) + else: + star = get_star([8, 7, 6], [FGO_SERVANT_FIVE_P, FGO_SERVANT_FOUR_P, FGO_SERVANT_THREE_P]) + if star > 5: + itype = 'servant' + star -= 3 + chars = [x for x in ALL_CHAR if x.star == star if not x.limited] + else: + itype = 'card' + chars = [x for x in ALL_CARD if x.star == star if not x.limited] + return random.choice(chars), 5 - star, itype + + +# 整理数据 +def _format_card_information(count: int): + max_star_lst = [] # 获取的最高星级角色列表 + max_index_lst = [] # 获取最高星级角色的次数 + star_list = [0, 0, 0] + obj_list = [] # 获取所有角色 + obj_dict = {} # 获取角色次数字典 + servant_count = 0 # 保底计算 + card_count = 0 # 保底计算 + for i in range(count): + servant_count += 1 + card_count += 1 + # 四星卡片保底 + if card_count == 9: + obj, code, itype = _get_fgo_card(2) + # 三星从者保底 + elif servant_count == 10: + obj, code, itype = _get_fgo_card(3) + _count = 0 + # 普通抽 + else: + obj, code, itype = _get_fgo_card() + star_list[code] += 1 + if itype == 'card' and code < 2: + card_count = 0 + if itype == 'servant': + servant_count = 0 + 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/genshin_handle.py b/plugins/draw_card/genshin_handle.py index fe6b8735..748c38ac 100644 --- a/plugins/draw_card/genshin_handle.py +++ b/plugins/draw_card/genshin_handle.py @@ -1,14 +1,15 @@ - import os -from util.init_result import image +from nonebot.adapters.cqhttp import MessageSegment import nonebot import random from .update_game_info import update_info -from .util import generate_img, init_star_rst, BaseData, set_list, get_star +from .util import generate_img, init_star_rst, BaseData, set_list, get_star, UpEvent 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 .announcement import GenshinAnnouncement +from services.log import logger try: import ujson as json except ModuleNotFoundError: @@ -23,21 +24,48 @@ genshin_pl_count = {} ALL_CHAR = [] ALL_ARMS = [] +UP_CHAR = [] +UP_ARMS = [] + + +_CURRENT_CHAR_POOL_TITLE = '' +_CURRENT_ARMS_POOL_TITLE = '' +POOL_IMG = '' + @dataclass class GenshinChar(BaseData): pass -async def genshin_draw(user_id: int, count: int): +async def genshin_draw(user_id: int, count: int, pool_name: str): # 0 1 2 cnlist = ['★★★★★', '★★★★', '★★★'] - 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) + char_list, five_list, five_index_list, char_dict, star_list = _format_card_information(count, user_id, pool_name) temp = '' + title = '' + up_type = [] + up_list = [] + if pool_name == 'char' and _CURRENT_CHAR_POOL_TITLE: + up_type = UP_CHAR + title = _CURRENT_CHAR_POOL_TITLE + elif pool_name == 'arms' and _CURRENT_ARMS_POOL_TITLE: + up_type = UP_ARMS + title = _CURRENT_ARMS_POOL_TITLE + tmp = '' + if up_type: + for x in up_type: + for operator in x.operators: + up_list.append(operator) + if x.star == 5: + tmp += f'五星UP:{" ".join(x.operators)} \n' + elif x.star == 4: + tmp += f'四星UP:{" ".join(x.operators)}' + rst = init_star_rst(star_list, cnlist, five_list, five_index_list, up_list) + pool_info = f'当前up池:{title}\n{tmp}' if title else '' if count > 90: char_list = set_list(char_list) - return image(b64=await generate_img(char_list, 'genshin', star_list)) + '\n' + rst[:-1] + \ + return pool_info + '\n' + MessageSegment.image("base64://" + 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%】" @@ -53,14 +81,11 @@ async def update_genshin_info(): '获取途径', '初始基础属性1', '初始基础属性2', '攻击力(MAX)', '副属性(MAX)', '技能']) if code == 200: - ALL_ARMS = init_game_pool('genshin', data, GenshinChar) + ALL_ARMS = init_game_pool('genshin_arms', data, GenshinChar) + await _init_up_char() -# asyncio.get_event_loop().run_until_complete(update_genshin_info()) - - -@driver.on_startup -async def init_data(): +async def init_genshin_data(): 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'): @@ -71,23 +96,51 @@ async def init_data(): 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) + ALL_ARMS = init_game_pool('genshin_arms', genshin_ARMS_dict, GenshinChar) + await _init_up_char() # 抽取卡池 -def _get_genshin_card(mode: int = 1, add: float = 0.0): - global ALL_ARMS, ALL_CHAR +def _get_genshin_card(mode: int = 1, pool_name: str = '', add: float = 0.0): + global ALL_ARMS, ALL_CHAR, UP_ARMS, UP_CHAR, _CURRENT_ARMS_POOL_TITLE, _CURRENT_CHAR_POOL_TITLE if mode == 1: star = get_star([5, 4, 3], [GENSHIN_FIVE_P + add, GENSHIN_FOUR_P, GENSHIN_THREE_P]) elif mode == 2: star = get_star([5, 4], [GENSHIN_G_FIVE_P + add, GENSHIN_G_FOUR_P]) else: star = 5 - 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) + if pool_name == 'char': + data_lst = UP_CHAR + flag = _CURRENT_CHAR_POOL_TITLE + itype_all_lst = ALL_CHAR + [x for x in ALL_ARMS if x.star == star and x.star < 5] + elif pool_name == 'arms': + data_lst = UP_ARMS + flag = _CURRENT_ARMS_POOL_TITLE + itype_all_lst = ALL_ARMS + [x for x in ALL_CHAR if x.star == star and x.star < 5] + else: + data_lst = '' + flag = '' + itype_all_lst = '' + all_lst = ALL_ARMS + ALL_CHAR + # 是否UP + if flag and star > 3 and pool_name: + # 获取up角色列表 + up_char_lst = [x.operators for x in data_lst if x.star == star][0] + # 成功获取up角色 + if random.random() < 0.5: + up_char_name = random.choice(up_char_lst) + acquire_char = [x for x in all_lst if x.name == up_char_name][0] + else: + # 无up + all_char_lst = [x for x in itype_all_lst if x.star == star and x.name not in up_char_lst and not x.limited] + acquire_char = random.choice(all_char_lst) + else: + chars = [x for x in all_lst if x.star == star and not x.limited] + acquire_char = random.choice(chars) + return acquire_char, 5 - star -def _format_card_information(_count: int, user_id): +def _format_card_information(_count: int, user_id, pool_name): char_list = [] star_list = [0, 0, 0] five_index_list = [] @@ -109,15 +162,15 @@ def _format_card_information(_count: int, user_id): if count == 10 and f_count != 90: if f_count >= 72: add += I72_ADD - char, code = _get_genshin_card(2, add) + char, code = _get_genshin_card(2, pool_name, add=add) count = 0 # 大保底 elif f_count == 90: - char, code = _get_genshin_card(3) + char, code = _get_genshin_card(3, pool_name) else: if f_count >= 72: add += I72_ADD - char, code = _get_genshin_card(add=add) + char, code = _get_genshin_card(pool_name=pool_name, add=add) if code == 1: count = 0 star_list[code] += 1 @@ -142,3 +195,35 @@ def _format_card_information(_count: int, user_id): def reset_count(user_id: int): genshin_count[user_id] = 0 genshin_pl_count[user_id] = 0 + + +# 获取up和概率 +async def _init_up_char(): + global _CURRENT_CHAR_POOL_TITLE, _CURRENT_ARMS_POOL_TITLE, UP_CHAR, UP_ARMS, POOL_IMG + UP_CHAR = [] + UP_ARMS = [] + up_char_dict = await GenshinAnnouncement.update_up_char() + _CURRENT_CHAR_POOL_TITLE = up_char_dict['char']['title'] + _CURRENT_ARMS_POOL_TITLE = up_char_dict['arms']['title'] + if _CURRENT_CHAR_POOL_TITLE and _CURRENT_ARMS_POOL_TITLE: + POOL_IMG = MessageSegment.image(up_char_dict['char']['pool_img']) + \ + MessageSegment.image(up_char_dict['arms']['pool_img']) + logger.info(f'成功获取原神当前up信息...当前up池: {_CURRENT_CHAR_POOL_TITLE} & {_CURRENT_ARMS_POOL_TITLE}') + for key in up_char_dict.keys(): + for star in up_char_dict[key]['up_char'].keys(): + up_char_lst = [] + for char in up_char_dict[key]['up_char'][star].keys(): + up_char_lst.append(char) + if key == 'char': + UP_CHAR.append(UpEvent(star=int(star), operators=up_char_lst, zoom=0)) + else: + UP_ARMS.append(UpEvent(star=int(star), operators=up_char_lst, zoom=0)) + + +async def reload_genshin_pool(): + await _init_up_char() + return f'当前UP池子:{_CURRENT_CHAR_POOL_TITLE} & {_CURRENT_ARMS_POOL_TITLE} {POOL_IMG}' + + + + diff --git a/plugins/draw_card/guardian_handle.py b/plugins/draw_card/guardian_handle.py index 8838f059..f047b683 100644 --- a/plugins/draw_card/guardian_handle.py +++ b/plugins/draw_card/guardian_handle.py @@ -2,7 +2,6 @@ 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 @@ -13,6 +12,7 @@ from .config import DRAW_PATH, GUARDIAN_ONE_CHAR_P, GUARDIAN_TWO_CHAR_P, GUARDIA GUARDIAN_EXCLUSIVE_ARMS_OTHER_P, GUARDIAN_FLAG from dataclasses import dataclass from .init_card_pool import init_game_pool +import asyncio try: import ujson as json except ModuleNotFoundError: @@ -46,7 +46,8 @@ async def guardian_draw(count: int, 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)) \ + return MessageSegment.image( + "base64://" + await generate_img(obj_list, 'guardian', star_list)) \ + '\n' + rst[:-1] + '\n' + max_card(obj_dict) @@ -65,8 +66,7 @@ async def update_guardian_info(): ALL_ARMS = init_game_pool('guardian_arms', data, GuardianArms) -@driver.on_startup -async def init_data(): +async def init_guardian_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'): @@ -81,17 +81,17 @@ async def init_data(): # 抽取卡池 -def _get_guardian_card(itype): +def _get_guardian_card(pool_name: str): global ALL_CHAR, ALL_ARMS - if itype != 'arms': + if pool_name != '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) + return random.choice(chars), 3- star 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) + return random.choice(arms), 5 - star # 整理数据 diff --git a/plugins/draw_card/init_card_pool.py b/plugins/draw_card/init_card_pool.py index 36cbe146..d93c2f53 100644 --- a/plugins/draw_card/init_card_pool.py +++ b/plugins/draw_card/init_card_pool.py @@ -24,7 +24,17 @@ def init_game_pool(game: str, data: dict, Operator: Any): for key in data.keys(): if key.find('旅行者') != -1: continue - tmp_lst.append(Operator(name=key, star=int(data[key]['稀有度'][:1]), limited=False)) + limited = False + if data[key]['常驻/限定'] == '限定UP': + limited = True + tmp_lst.append(Operator(name=key, star=int(data[key]['稀有度'][:1]), limited=limited)) + if game == 'genshin_arms': + for key in data.keys(): + if data[key]['获取途径'].find('祈愿') != -1: + limited = False + if data[key]['获取途径'].find('限定祈愿') != -1: + limited = True + tmp_lst.append(Operator(name=key, star=int(data[key]['稀有度'][:1]), limited=limited)) if game == 'pretty': for key in data.keys(): tmp_lst.append(Operator(name=key, star=data[key]['初始星级'], limited=False)) @@ -40,5 +50,27 @@ def init_game_pool(game: str, data: dict, Operator: Any): if key.find('(') != -1: limited = True tmp_lst.append(Operator(name=data[key]['名称'], star=int(data[key]['星级']), limited=limited)) + if game == 'azur': + for key in data.keys(): + limited = False + if int(data[key]['星级']) > 4 or key.find('兵装') != -1 or key[-1] == '改' or key.find('布里') != -1: + limited = True + tmp_lst.append(Operator(name=data[key]['名称'], star=int(data[key]['星级']), limited=limited, itype=data[key]['类型'])) + if game in ['fgo', 'fgo_card']: + for key in data.keys(): + limited = False + try: + if "圣晶石召唤" not in data[key]['入手方式'] and "圣晶石召唤(Story卡池)" not in data[key]['入手方式']: + limited = True + except KeyError: + pass + tmp_lst.append(Operator(name=data[key]['名称'], star=int(data[key]['星级']), limited=limited)) + if game == 'onmyoji': + for key in data.keys(): + limited = False + if key in ['奴良陆生', '卖药郎', '鬼灯', '阿香', '蜜桃&芥子', '犬夜叉', '杀生丸', '桔梗', '朽木露琪亚', '黑崎一护', + '灶门祢豆子', '灶门炭治郎']: + limited = True + tmp_lst.append(Operator(name=data[key]['名称'], star=data[key]['星级'], limited=limited)) return tmp_lst diff --git a/plugins/draw_card/onmyoji_handle.py b/plugins/draw_card/onmyoji_handle.py new file mode 100644 index 00000000..ca02803f --- /dev/null +++ b/plugins/draw_card/onmyoji_handle.py @@ -0,0 +1,83 @@ + +from nonebot.adapters.cqhttp import MessageSegment +import random +from .update_game_requests_info import update_requests_info +from .util import generate_img, init_star_rst, BaseData, set_list, get_star, max_card +from .config import ONMYOJI_SR, ONMYOJI_SSR, ONMYOJI_SP, ONMYOJI_R, DRAW_PATH, ONMYOJI_FLAG +from dataclasses import dataclass +from .init_card_pool import init_game_pool +import nonebot +try: + import ujson as json +except ModuleNotFoundError: + import json + +ALL_CHAR = [] + + +@dataclass +class OnmyojiChar(BaseData): + pass + + +async def onmyoji_draw(count: int): + # 0 1 2 + cnlist = ['SP', 'SSR', 'SR', 'R'] + obj_list, obj_dict, star_list, rst = format_card_information(count) + rst = init_star_rst(star_list, cnlist, [], []) + rst + if count > 90: + obj_list = set_list(obj_list) + return MessageSegment.image("base64://" + await generate_img(obj_list, 'onmyoji', star_list)) \ + + '\n' + rst[:-1] + '\n' + max_card(obj_dict) + + +async def update_onmyoji_info(): + global ALL_CHAR + data, code = await update_requests_info('onmyoji') + if code == 200: + ALL_CHAR = init_game_pool('onmyoji', data, OnmyojiChar) + + +async def init_onmyoji_data(): + global ALL_CHAR + if ONMYOJI_FLAG: + with open(DRAW_PATH + 'onmyoji.json', 'r', encoding='utf8') as f: + azur_dict = json.load(f) + ALL_CHAR = init_game_pool('onmyoji', azur_dict, OnmyojiChar) + + +onmyoji_star = { + 5: 'SP', + 4: 'SSR', + 3: 'SR', + 2: 'R', +} + + +# 抽取卡池 +def _get_onmyoji_card(): + global ALL_CHAR + star = get_star([5, 4, 3, 2], [ONMYOJI_SP, ONMYOJI_SSR, ONMYOJI_SR, ONMYOJI_R]) + chars = [x for x in ALL_CHAR if x.star == onmyoji_star[star] and not x.limited] + return random.choice(chars), 5 - star + + +def format_card_information(count: int): + star_list = [0, 0, 0, 0] + obj_list = [] # 获取所有角色 + obj_dict = {} # 获取角色次数字典 + rst = '' + for i in range(count): + obj, code = _get_onmyoji_card() + star_list[code] += 1 + if code == 0: + rst += f'第 {i+1} 抽获取SP {obj.name}\n' + elif code == 1: + rst += f'第 {i+1} 抽获取SSR {obj.name}\n' + try: + obj_dict[obj.name] += 1 + except KeyError: + obj_dict[obj.name] = 1 + obj_list.append(obj) + return obj_list, obj_dict, star_list, rst + diff --git a/plugins/draw_card/pcr_handle.py b/plugins/draw_card/pcr_handle.py index 2cd4e387..524062fc 100644 --- a/plugins/draw_card/pcr_handle.py +++ b/plugins/draw_card/pcr_handle.py @@ -1,11 +1,12 @@ import ujson as json import os -from util.init_result import image +from nonebot.adapters.cqhttp import MessageSegment import nonebot import random from .update_game_info import update_info +from .update_game_simple_info import update_simple_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 .config import PCR_TWO_P, PCR_THREE_P, PCR_ONE_P, DRAW_PATH, PCR_FLAG, PCR_G_TWO_P, PCR_G_THREE_P, PCR_TAI from dataclasses import dataclass from .init_card_pool import init_game_pool @@ -26,28 +27,28 @@ async def pcr_draw(count: int): 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)) \ + return MessageSegment.image("base64://" + 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 PCR_TAI: + url = 'https://wiki.biligame.com/pcr/角色图鉴' + data, code = await update_simple_info(url, 'pcr') + else: + 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(): +async def init_pcr_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) + 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) # 抽取卡池 @@ -58,7 +59,7 @@ def _get_pcr_card(mode: int = 1): 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) + return random.choice(chars), 3 - star def _format_card_information(_count: int): @@ -77,7 +78,7 @@ def _format_card_information(_count: int): count = 0 else: char, code = _get_pcr_card() - if code == 1: + if code < 2: count = 0 star_list[code] += 1 if code == 0: diff --git a/plugins/draw_card/pretty_handle.py b/plugins/draw_card/pretty_handle.py index 97331585..0ae6f230 100644 --- a/plugins/draw_card/pretty_handle.py +++ b/plugins/draw_card/pretty_handle.py @@ -1,7 +1,6 @@ - import os import nonebot -from util.init_result import image +from nonebot.adapters.cqhttp import MessageSegment from .update_game_info import update_info from .util import download_img, init_star_rst, generate_img, max_card, BaseData, \ set_list, get_star, format_card_information @@ -9,6 +8,8 @@ import random 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 +import asyncio + try: import ujson as json except ModuleNotFoundError: @@ -36,7 +37,8 @@ async def pretty_draw(count: int, pool_name): rst = init_star_rst(star_list, cnlist, three_list, three_olist) if count > 90: obj_list = set_list(obj_list) - return image(b64=await generate_img(obj_list, 'pretty', star_list)) \ + return MessageSegment.image( + "base64://" + await generate_img(obj_list, 'pretty', star_list)) \ + '\n' + rst[:-1] + '\n' + max_card(obj_dict) @@ -52,33 +54,20 @@ async def update_pretty_info(): ALL_CARD = init_game_pool('pretty_card', data, PrettyChar) -@driver.on_startup -async def init_data(): +async def init_pretty_data(): global ALL_CHAR, ALL_CARD 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) + 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): +def _get_pretty_card(pool_name: str): global ALL_CHAR, ALL_CARD 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) - + chars = [x for x in (ALL_CARD if pool_name == 'card' else ALL_CHAR) if x.star == star] + return random.choice(chars), 3 - star diff --git a/plugins/draw_card/prts_handle.py b/plugins/draw_card/prts_handle.py index 8f90d683..44157a23 100644 --- a/plugins/draw_card/prts_handle.py +++ b/plugins/draw_card/prts_handle.py @@ -1,6 +1,5 @@ -import os -from util.init_result import image +from nonebot.adapters.cqhttp import MessageSegment import nonebot import random from .config import PRTS_FIVE_P, PRTS_FOUR_P, PRTS_SIX_P, PRTS_THREE_P, DRAW_PATH, PRTS_FLAG @@ -9,6 +8,7 @@ from .util import generate_img, init_star_rst, max_card, BaseData, UpEvent, set_ from .init_card_pool import init_game_pool from pathlib import Path from .announcement import PrtsAnnouncement +from services.log import logger from dataclasses import dataclass try: import ujson as json @@ -23,6 +23,7 @@ prts_dict = {} UP_OPERATOR = [] ALL_OPERATOR = [] _CURRENT_POOL_TITLE = '' +POOL_IMG = '' @dataclass @@ -46,7 +47,8 @@ async def prts_draw(count: int = 300): if count > 90: operator_list = set_list(operator_list) pool_info = "当前up池: " if _CURRENT_POOL_TITLE else "" - return pool_info + _CURRENT_POOL_TITLE + image(b64=await generate_img(operator_list, 'prts', star_list)) \ + return pool_info + _CURRENT_POOL_TITLE + MessageSegment.image( + "base64://" + await generate_img(operator_list, 'prts', star_list)) \ + '\n' + rst[:-1] + '\n' + max_card(operator_dict) @@ -58,18 +60,15 @@ async def update_prts_info(): if code == 200: prts_dict = data ALL_OPERATOR = init_game_pool('prts', prts_dict, Operator) + await _init_up_char() -@driver.on_startup -async def init_data(): +async def init_prts_data(): global prts_dict, ALL_OPERATOR 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) + 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() @@ -105,16 +104,19 @@ 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])]) - return acquire_operator, abs(star - 6) + return acquire_operator, 6 - star # 获取up干员和概率 async def _init_up_char(): - global _CURRENT_POOL_TITLE + global _CURRENT_POOL_TITLE, POOL_IMG, UP_OPERATOR + UP_OPERATOR = [] up_char_dict = await PrtsAnnouncement.update_up_char() _CURRENT_POOL_TITLE = up_char_dict['title'] + if _CURRENT_POOL_TITLE: + POOL_IMG = MessageSegment.image(up_char_dict['pool_img']) up_char_dict = up_char_dict['up_char'] - print(f'成功获取明日方舟当前up信息...当前up池: {_CURRENT_POOL_TITLE}') + logger.info(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(): @@ -131,5 +133,6 @@ async def _init_up_char(): UP_OPERATOR.append(UpEvent(star=int(star), operators=average_dict[star][str_zoom], zoom=zoom)) -async def reload_pool(): +async def reload_prts_pool(): await _init_up_char() + return f'当前UP池:{_CURRENT_POOL_TITLE} {POOL_IMG}' diff --git a/plugins/draw_card/rule.py b/plugins/draw_card/rule.py index f13b3729..28939bf1 100644 --- a/plugins/draw_card/rule.py +++ b/plugins/draw_card/rule.py @@ -1,7 +1,7 @@ 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 +from .config import GENSHIN_FLAG, PRTS_FLAG, PRETTY_FLAG, GUARDIAN_FLAG, PCR_FLAG, AZUR_FLAG, FGO_FLAG, ONMYOJI_FLAG def is_switch(game_name: str) -> Rule: @@ -17,6 +17,12 @@ def is_switch(game_name: str) -> Rule: return GUARDIAN_FLAG if game_name == 'pcr': return PCR_FLAG + if game_name == 'azur': + return AZUR_FLAG + if game_name == 'fgo': + return FGO_FLAG + if game_name == 'onmyoji': + return ONMYOJI_FLAG else: return False diff --git a/plugins/draw_card/update_game_info.py b/plugins/draw_card/update_game_info.py index 5acf086c..252bbf73 100644 --- a/plugins/draw_card/update_game_info.py +++ b/plugins/draw_card/update_game_info.py @@ -3,11 +3,13 @@ import aiohttp from .config import DRAW_PATH from asyncio.exceptions import TimeoutError from bs4 import BeautifulSoup +import asyncio from .util import download_img from urllib.parse import unquote +from services.log import logger +from .util import remove_prohibited_str import bs4 import re -from util.utils import get_local_proxy try: import ujson as json except ModuleNotFoundError: @@ -25,13 +27,15 @@ async def update_info(url: str, game_name: str, info_list: list = None) -> 'dict data = {} try: async with aiohttp.ClientSession(headers=headers) as session: - async with session.get(url, proxy=get_local_proxy(), timeout=7) as response: + async with session.get(url, timeout=7) as response: soup = BeautifulSoup(await response.text(), 'lxml') _tbody = get_tbody(soup, game_name, url) trs = _tbody.find_all('tr') att_dict, start_index, index = init_attr(game_name) if game_name == 'guardian': start_index = 1 + if game_name == 'azur': + start_index = 0 for th in trs[0].find_all('th')[start_index:]: text = th.text if text[-1] == '\n': @@ -51,12 +55,13 @@ async def update_info(url: str, game_name: str, info_list: list = None) -> 'dict member_dict = intermediate_check(member_dict, key, game_name, td) avatar_img = await _modify_avatar_url(session, game_name, member_dict["名称"]) member_dict['头像'] = avatar_img if avatar_img else member_dict['头像'] - name = replace_name(member_dict, game_name) + member_dict, name = replace_update_name(member_dict, game_name) await download_img(member_dict['头像'], game_name, name) data[name] = member_dict - print(f'{name} is update...') + logger.info(f'{name} is update...') data = await _last_check(data, game_name, session) except TimeoutError: + logger.warning(f'更新 {game_name} 超时...') return {}, 999 with open(DRAW_PATH + f'{game_name}.json', 'w', encoding='utf8') as wf: wf.write(json.dumps(data, ensure_ascii=False, indent=4)) @@ -94,7 +99,7 @@ def _find_last_tag(element: bs4.element.Tag, attr: str, game_name: str) -> str: # 获取大图(小图快爬) 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}', proxy=get_local_proxy(), timeout=7) as res: + async with session.get(f'https://wiki.biligame.com/arknights/{char_name}', timeout=7) as res: soup = BeautifulSoup(await res.text(), 'lxml') try: img_url = str(soup.find('img', {'class': 'img-bg'})['srcset']).split(' ')[-2] @@ -104,7 +109,7 @@ 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}', proxy=get_local_proxy(), timeout=7) as res: + async with session.get(f'https://wiki.biligame.com/umamusume/{char_name}', 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 @@ -118,7 +123,7 @@ async def _modify_avatar_url(session: aiohttp.ClientSession, game_name: str, cha # except KeyError: # img_url = str(soup.find('img', {'class': 'img-kk'})['src']) # except TypeError: - # print(f'{char_name} 图片还未上传,跳过...') + # logger.info(f'{char_name} 图片还未上传,跳过...') # img_url = '' # return img_url return None @@ -127,49 +132,46 @@ async def _modify_avatar_url(session: aiohttp.ClientSession, game_name: str, cha # 数据最后处理(是否需要额外数据或处理数据) async def _last_check(data: dict, game_name: str, session: aiohttp.ClientSession): if game_name == 'prts': + url = 'https://wiki.biligame.com/arknights/' + tasks = [] for key in data.keys(): - async with session.get(f'https://wiki.biligame.com/arknights/{key}', proxy=get_local_proxy(), timeout=7) as res: + tasks.append(asyncio.ensure_future(_async_update_prts_extra_info(url, key, session))) + asyResult = await asyncio.gather(*tasks) + for x in asyResult: + for key in x.keys(): + data[key]['获取途径'] = x[key]['获取途径'] + if game_name == 'genshin': + for key in data.keys(): + async with session.get(f'https://wiki.biligame.com/ys/{key}', 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'