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'([\s\S]*)'): - obtain = obtain.split('
') - elif obtain.find('
'): - obtain = obtain.split('
') - for i in range(len(obtain)): - if obtain[i].find(''): - r = re.search('>(.*)', msg) - if r: - text += r.group(1) + ' ' - obtain[i] = obtain[i].split('')[-1] - print(f'明日方舟获取额外信息....{obtain}') - data[key]['获取途径'] = obtain - # 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') - # trs = soup.find('div', {'class': 'poke-bg'}).find('table').find('tbody').find_all('tr') - # for tr in trs: - # if tr.find('th').text.find('常驻/限定') != -1: - # data[key]['常驻/限定'] = tr.find('td').text - # break + _trs = '' + for table in soup.find_all('table', {'class': 'wikitable'}): + if str(table).find('常驻/限定') != -1: + _trs = table.find('tbody').find_all('tr') + break + for tr in _trs: + if str(tr).find('限定UP') != -1: + data[key]['常驻/限定'] = '限定UP' + logger.info(f'原神获取额外数据 {key}...{data[key]["常驻/限定"]}') + break + elif str(tr).find('常驻UP') != -1: + data[key]['常驻/限定'] = '常驻UP' + logger.info(f'原神获取额外数据 {key}...{data[key]["常驻/限定"]}') + break if game_name == 'pretty': for keys in data.keys(): for key in data[keys].keys(): r = re.search(r'.*?40px-(.*)图标.png', str(data[keys][key])) if r: data[keys][key] = r.group(1) - print(f'赛马娘额外修改数据....{keys}[{key}]=> {r.group(1)}') + logger.info(f'赛马娘额外修改数据...{keys}[{key}]=> {r.group(1)}') if game_name == 'guardian': for keys in data.keys(): for key in data[keys].keys(): r = re.search(r'.*?-star_(.*).png', str(data[keys][key])) if r: data[keys][key] = r.group(1) - print(f'坎公骑士剑额外修改数据...{keys}[{key}] => {r.group(1)}') + logger.info(f'坎公骑士剑额外修改数据...{keys}[{key}] => {r.group(1)}') return data @@ -199,6 +201,7 @@ def init_attr(game_name: str): return att_dict, start_index, index +# 解析key def parse_key(key: str, game_name): attr = '' if game_name == 'genshin_arms': @@ -209,11 +212,17 @@ def parse_key(key: str, game_name): return key, attr -def replace_name(member_dict: dict, game_name: str): +# 拿到名称 +def replace_update_name(member_dict: dict, game_name: str): name = member_dict['名称'] if game_name == 'pretty_card': name = member_dict['中文名'] - return name + name = remove_prohibited_str(name) + member_dict['中文名'] = name + else: + name = remove_prohibited_str(name) + member_dict['名称'] = name + return member_dict, name # 拿到tbody,不同游戏tbody可能不同 @@ -234,3 +243,32 @@ def get_tbody(soup: bs4.BeautifulSoup, game_name: str, url: str): max_count = len(tbody.find_all('tr')) return _tbody + +async def _async_update_prts_extra_info(url: str, key: str, session: aiohttp.ClientSession): + for i in range(10): + try: + async with session.get(f'https://wiki.biligame.com/arknights/{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'([\s\S]*)'): + obtain = obtain.split('
') + elif obtain.find('
'): + obtain = obtain.split('
') + for i in range(len(obtain)): + if obtain[i].find(''): + r = re.search('>(.*)', msg) + if r: + text += r.group(1) + ' ' + obtain[i] = obtain[i].split('')[-1] + logger.info(f'明日方舟获取额外信息 {key}...{obtain}') + x = {key: {}} + x[key]['获取途径'] = obtain + return x + except TimeoutError: + logger.warning(f'访问{url}{key} 第 {i}次 超时...已再次访问') + return {} + diff --git a/plugins/draw_card/update_game_requests_info.py b/plugins/draw_card/update_game_requests_info.py new file mode 100644 index 00000000..aada3b69 --- /dev/null +++ b/plugins/draw_card/update_game_requests_info.py @@ -0,0 +1,148 @@ +import aiohttp +from .config import DRAW_PATH +from asyncio.exceptions import TimeoutError +from .util import download_img +from bs4 import BeautifulSoup +from .util import remove_prohibited_str +from services.log import logger +import asyncio +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_requests_info(game_name: str): + try: + 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=headers) as session: + if game_name in ['fgo', 'fgo_card']: + if game_name == 'fgo': + url = 'http://fgo.vgtime.com/servant/ajax?card=&wd=&ids=&sort=12777&o=desc&pn=' + else: + url = 'http://fgo.vgtime.com/equipment/ajax?wd=&ids=&sort=12958&o=desc&pn=' + for i in range(9999): + async with session.get(f'{url}{i}', timeout=7) as response: + fgo_data = json.loads(await response.text()) + if int(fgo_data['nums']) == 0: + break + for x in fgo_data['data']: + x['name'] = remove_prohibited_str(x['name']) + key = x['name'] + data = add_to_data(data, x, game_name) + await download_img(data[key]['头像'], game_name, key) + logger.info(f'{key} is update...') + if game_name == 'onmyoji': + url = 'https://yys.res.netease.com/pc/zt/20161108171335/js/app/all_shishen.json?v74=' + async with session.get(f'{url}', timeout=7) as response: + onmyoji_data = await response.json() + for x in onmyoji_data: + x['name'] = remove_prohibited_str(x['name']) + key = x['name'] + data = add_to_data(data, x, game_name) + logger.info(f'{key} 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: + json.dump(data, wf, ensure_ascii=False, indent=4) + return data, 200 + + +# 添加到字典 +def add_to_data(data: dict, x: dict, game_name: str) -> dict: + member_dict = {} + if game_name == 'fgo': + member_dict = { + 'id': x['id'], + 'card_id': x['charid'], + '头像': x['icon'], + '名称': x['name'], + '职阶': x['classes'], + '星级': x['star'], + 'hp': x['lvmax4hp'], + 'atk': x['lvmax4atk'], + 'card_quick': x['cardquick'], + 'card_arts': x['cardarts'], + 'card_buster': x['cardbuster'], + '宝具': x['tprop'], + } + if game_name == 'fgo_card': + member_dict = { + 'id': x['id'], + 'card_id': x['equipid'], + '头像': x['icon'], + '名称': x['name'], + '星级': x['star'], + 'hp': x['lvmax_hp'], + 'atk': x['lvmax_atk'], + 'skill_e': x['skill_e'].split('
')[: -1], + } + if game_name == 'onmyoji': + member_dict = { + 'id': x['id'], + '名称': x['name'], + '星级': x['level'], + } + data[member_dict['名称']] = member_dict + return data + + +# 获取额外数据 +async def _last_check(data: dict, game_name: str, session: aiohttp.ClientSession) -> dict: + if game_name == 'fgo': + url = 'http://fgo.vgtime.com/servant/' + tasks = [] + for key in data.keys(): + tasks.append(asyncio.ensure_future(_async_update_fgo_extra_info(url, key, data[key]['id'], session))) + asyResult = await asyncio.gather(*tasks) + for x in asyResult: + for key in x.keys(): + data[key]['入手方式'] = x[key]['入手方式'] + if game_name == 'onmyoji': + url = 'https://yys.163.com/shishen/{}.html' + for key in data.keys(): + async with session.get(f'{url.format(data[key]["id"])}', timeout=7) as response: + soup = BeautifulSoup(await response.text(), 'lxml') + data[key]['头像'] = "https:" + soup.find('div', {'class': 'pic_wrap'}).find('img')['src'] + await download_img(data[key]['头像'], game_name, key) + return data + + +async def _async_update_fgo_extra_info(url: str, key: str, _id: str, session: aiohttp.ClientSession): + # 防止访问超时 + for i in range(10): + try: + async with session.get(f'{url}{_id}', timeout=7) as response: + soup = BeautifulSoup(await response.text(), 'lxml') + obtain = soup.find('table', {'class': 'uk-table uk-codex-table'}).find_all('td')[-1].text + if obtain.find('限时活动免费获取 活动结束后无法获得') != -1: + obtain = ['活动获取'] + elif obtain.find('非限时UP无法获得') != -1: + obtain = ['限时召唤'] + else: + if obtain.find('&') != -1: + obtain = obtain.strip().split('&') + else: + obtain = obtain.strip().split(' ') + logger.info(f'Fgo获取额外信息 {key}....{obtain}') + x = {key: {}} + x[key]['入手方式'] = obtain + return x + except TimeoutError: + logger.warning(f'访问{url}{_id} 第 {i}次 超时...已再次访问') + return {} + + + + + + diff --git a/plugins/draw_card/update_game_simple_info.py b/plugins/draw_card/update_game_simple_info.py new file mode 100644 index 00000000..c912fca9 --- /dev/null +++ b/plugins/draw_card/update_game_simple_info.py @@ -0,0 +1,143 @@ +import aiohttp +from .config import DRAW_PATH +from asyncio.exceptions import TimeoutError +from bs4 import BeautifulSoup +from .util import download_img +from .util import remove_prohibited_str +from urllib.parse import unquote +from services.log import logger +import bs4 + +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_simple_info(url: str, game_name: str) -> 'dict, int': + try: + 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=headers) as session: + async with session.get(url, timeout=7) as response: + soup = BeautifulSoup(await response.text(), 'lxml') + divs = get_char_divs(soup, game_name) + for div in divs: + type_lst = get_type_lst(div, game_name) + index = 0 + for char_lst in type_lst: + contents = get_char_lst_contents(char_lst, game_name) + for char in contents: + data = await retrieve_char_data(char, game_name, data, index) + index += 1 + data = await _last_check(data, game_name) + 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)) + return data, 200 + + +# 获取所有包含需要图片的divs +def get_char_divs(soup: bs4.BeautifulSoup, game_name: str) -> bs4.element.ResultSet: + if game_name == 'pcr': + return soup.find_all('div', {'class': 'tabbertab'}) + if game_name == 'azur': + return soup.find_all('div', {'class': 'resp-tabs'}) + + +# 拿到所有类型 +def get_type_lst(div: bs4.element.Tag, game_name: str): + if game_name in ['pcr', 'azur']: + return div.find('div', {'class': 'resp-tabs-container'}).find_all('div', {'class': 'resp-tab-content'}) + + +# 获取所有角色div +def get_char_lst_contents(char_lst: bs4.element.Tag, game_name: str): + contents = [] + # logger.info(len(char_lst.find_all('tr'))) + if game_name == 'pcr': + contents = char_lst.contents + if game_name == 'azur': + contents = char_lst.find('table').find('tbody').contents[-1].find('td').contents + return [x for x in contents if x != '\n'] + + +# 额外数据 +async def _last_check(data: dict, game_name: str) -> dict: + if game_name == 'azur': + idx = 1 + for url in [ + 'https://patchwiki.biligame.com/images/blhx/thumb/1/15/pxho13xsnkyb546tftvh49etzdh74cf.png/60px' + '-舰娘头像外框普通.png', + 'https://patchwiki.biligame.com/images/blhx/thumb/a/a9/k8t7nx6c8pan5vyr8z21txp45jxeo66.png/60px' + '-舰娘头像外框稀有.png', + 'https://patchwiki.biligame.com/images/blhx/thumb/a/a5/5whkzvt200zwhhx0h0iz9qo1kldnidj.png/60px' + '-舰娘头像外框精锐.png', + 'https://patchwiki.biligame.com/images/blhx/thumb/a/a2/ptog1j220x5q02hytpwc8al7f229qk9.png/60px-' + '舰娘头像外框超稀有.png' + ]: + await download_img(url, 'azur', f'{idx}_star') + idx += 1 + + return data + + +azur_type = { + '0': '驱逐', + '1': '轻巡', + '2': '重巡', + '3': '超巡', + '4': '战巡', + '5': '战列', + '6': '航母', + '7': '航站', + '8': '轻航', + '9': '重炮', + '10': '维修', + '11': '潜艇', + '12': '运输', +} + + +# 整理数据 +async def retrieve_char_data(char: bs4.element.Tag, game_name: str, data: dict, index: int = 0) -> dict: + member_dict = {} + if game_name == 'pcr': + member_dict = { + '头像': unquote(char.find('img', {'class': 'img-kk'})['src']), + '名称': remove_prohibited_str(char.find('a')['title']), + '星级': 3 - index} + if game_name == 'azur': + char = char.find('td').find('div') + avatar_img = char.find('a').find('img') + try: + member_dict['头像'] = unquote(str(avatar_img['srcset']).split(' ')[-2]) + except KeyError: + member_dict['头像'] = unquote(str(avatar_img['src']).split(' ')[-2]) + member_dict['名称'] = remove_prohibited_str(str(avatar_img['alt'])[: str(avatar_img['alt']).find('头像')]) + star = char.find('div').find('img')['alt'] + if star == '舰娘头像外框普通.png': + star = 1 + elif star == '舰娘头像外框稀有.png': + star = 2 + elif star == '舰娘头像外框精锐.png': + star = 3 + elif star == '舰娘头像外框超稀有.png': + star = 4 + elif star == '舰娘头像外框海上传奇.png': + star = 5 + elif star in ['舰娘头像外框最高方案.png', '舰娘头像外框决战方案.png', '舰娘头像外框超稀有META.png']: + star = 6 + member_dict['星级'] = star + member_dict['类型'] = azur_type[str(index)] + await download_img(member_dict['头像'], game_name, member_dict['名称']) + data[member_dict['名称']] = member_dict + logger.info(f'{member_dict["名称"]} is update...') + return data diff --git a/plugins/draw_card/util.py b/plugins/draw_card/util.py index ff568338..b0c69892 100644 --- a/plugins/draw_card/util.py +++ b/plugins/draw_card/util.py @@ -1,19 +1,21 @@ -import os + import aiohttp import aiofiles from asyncio.exceptions import TimeoutError from aiohttp.client_exceptions import InvalidURL from typing import List, Union, Set -import asyncio from pathlib import Path -from .config import path_dict, DRAW_PATH +from .config import path_dict +from configs.path_config import IMAGE_PATH import nonebot import pypinyin from util.img_utils import CreateImg -from configs.path_config import IMAGE_PATH +import platform +from services.log import logger import random from dataclasses import dataclass -from services.log import logger +import os +import asyncio try: import ujson as json except ModuleNotFoundError: @@ -23,6 +25,9 @@ except ModuleNotFoundError: driver: nonebot.Driver = nonebot.get_driver() +loop = asyncio.get_event_loop() + + headers = {'User-Agent': '"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)"'} @@ -43,8 +48,9 @@ class UpEvent: async def download_img(url: str, path: str, name: str) -> bool: path = path.split('_')[0] codename = cn2py(name) - Path(IMAGE_PATH + f'/draw_card/{path}').mkdir(exist_ok=True, parents=True) - if not os.path.exists(IMAGE_PATH + f'/draw_card/{path}/{codename}.png'): + file = Path(IMAGE_PATH + f'/draw_card/{path}/{codename}.png') + if not file.exists(): + file.parent.mkdir(exist_ok=True, parents=True) try: async with aiohttp.ClientSession(headers=headers) as session: async with session.get(url, timeout=7) as response: @@ -66,7 +72,7 @@ async def download_img(url: str, path: str, name: str) -> bool: @driver.on_startup def _check_dir(): for dir_name in path_dict.keys(): - _p = Path(DRAW_PATH + f'/draw_card/' + dir_name) + _p = Path(IMAGE_PATH + f'/draw_card/' + dir_name) if not _p.exists(): _p.mkdir(parents=True, exist_ok=True) @@ -74,17 +80,20 @@ def _check_dir(): async def generate_img(card_set: Union[Set[BaseData], List[BaseData]], game_name: str, star_list: list) -> str: # try: img_list = [] - color_list = [] + background_list = [] for x in card_set: if game_name == 'prts': if x.star == 6: - color_list.append('#FFD700') + background_list.append('#FFD700') elif x.star == 5: - color_list.append('#DAA520') + background_list.append('#DAA520') elif x.star == 4: - color_list.append('#9370D8') + background_list.append('#9370D8') else: - color_list.append('white') + background_list.append('white') + if game_name == 'azur': + if os.path.exists(IMAGE_PATH + f'/draw_card/{game_name}/{x.star}_star.png'): + background_list.append(IMAGE_PATH + f'/draw_card/{game_name}/{x.star}_star.png') pyname = cn2py(x.name) img_list.append(IMAGE_PATH + f'/draw_card/{game_name}/{pyname}.png') img_len = len(img_list) @@ -96,7 +105,7 @@ async def generate_img(card_set: Union[Set[BaseData], List[BaseData]], game_name h = 100 * int(img_len / 10) else: h = 100 * int(img_len / 10) + 100 - card_img = await asyncio.get_event_loop().run_in_executor(None, _pst, h, img_list, game_name, color_list) + card_img = await asyncio.get_event_loop().run_in_executor(None, _pst, h, img_list, game_name, background_list) num = 0 for n in star_list: num += n @@ -105,23 +114,28 @@ async def generate_img(card_set: Union[Set[BaseData], List[BaseData]], game_name return A.pic2bs4() -def _pst(h: int, img_list: list, game_name: str, color_list: list): +def _pst(h: int, img_list: list, game_name: str, background_list: list): card_img = CreateImg(100 * 10, h, 100, 100) idx = 0 for img in img_list: try: if game_name == 'prts': - bk = CreateImg(100, 100, color=color_list[idx]) + bk = CreateImg(100, 100, color=background_list[idx]) b = CreateImg(94, 94, background=img) bk.paste(b, (3, 3)) b = bk - idx += 1 + elif game_name == 'azur' and background_list: + bk = CreateImg(100, 100, background=background_list[idx]) + b = CreateImg(98, 90, background=img) + bk.paste(b, (1, 5)) + b = bk else: b = CreateImg(100, 100, background=img) except FileNotFoundError: - logger.warning(f'{img} not exists') + print(f'{img} not exists') b = CreateImg(100, 100, color='black') card_img.paste(b) + idx += 1 return card_img @@ -234,3 +248,15 @@ def check_num(num: str, max_num: int) -> 'str, bool': else: return str(num), True + +# 移除windows和linux下特殊字符 +def remove_prohibited_str(name: str): + if platform.system().lower() == 'windows': + tmp = '' + for i in name: + if i not in ['\\', '/', ':', '*', '?', '"', '<', '>', '|']: + tmp += i + name = tmp + else: + name = name.replace('/', '') + return name diff --git a/plugins/genshin/query_resource_points/__init__.py b/plugins/genshin/query_resource_points/__init__.py index 8e170d54..29857d09 100644 --- a/plugins/genshin/query_resource_points/__init__.py +++ b/plugins/genshin/query_resource_points/__init__.py @@ -1,4 +1,5 @@ from nonebot import on_command, on_regex +from nonebot.rule import to_me from .query_resource import get_resource_map_mes, get_resource_list_mes, up_label_and_point_list from util.utils import get_message_text, scheduler from nonebot.adapters.cqhttp import Bot, MessageEvent @@ -13,7 +14,7 @@ except ModuleNotFoundError: qr = on_command("原神资源查询", priority=5, block=True) qr_lst = on_command("原神资源列表", priority=5, block=True) -rex_qr = on_regex('.*?(在哪|在哪里|哪有|哪里有).*?', priority=5, block=True) +rex_qr = on_regex('.*?(在哪|在哪里|哪有|哪里有).*?', rule=to_me(), priority=5, block=True) with open(os.path.dirname(__file__) + '/resource_type_id.json', 'r', encoding='utf-8') as f: diff --git a/plugins/help/config.py b/plugins/help/config.py index 1e98b0fa..e5b3868f 100644 --- a/plugins/help/config.py +++ b/plugins/help/config.py @@ -31,11 +31,13 @@ entertainment_help = { 'fake_msg': '构造一个假消息 --> 指令:假消息', 'shop': '商店系统(初始送100金币) --> 指令:商店/我的金币/购买道具/使用道具', 'draw_card_prts': '换个地方当非酋TvT... --> 指令:方舟一井/方舟N抽(0 指令:原神一井/原神N抽(0 指令:原神一井/原神N抽(0 指令:赛马娘一井/赛马娘N抽/赛马娘卡一井/赛马娘卡N抽(0 指令:坎公骑冠剑一井/坎公骑冠剑武器一井/坎公骑冠剑N抽/坎公骑冠剑武器N抽(0 指令:pcr一井/pcrN抽(0 直接查看 骰子娘帮助!', + 'draw_card_azur': '我跟方舟坐狱友 --> 指令:碧蓝轻型/重型/特型N抽(0 指令:fgoN抽(0 指令:阴阳师N抽(0 指令:我有一个朋友想问问xxx(内容)', 'nickname': '区区昵称! --> 指令:以后叫我xx(昵称)/我是谁/取消昵称', 'almanac': '这是一张正经的黄历 --> 指令:原神黄历', @@ -50,5 +52,6 @@ other_help = [ '这是一份正经的自我介绍 --> 指令:自我介绍', '不得看看自己权力多大? --> 指令:我的权限', '有人记得你是什么时候加入我们的 --> 指令:我的信息', - '让我看看更新了什么 --> 指令:更新信息' + '让我看看更新了什么 --> 指令:更新信息', + '真寻给我把话收回去! --> 指令:撤回 [id](默认0)', ] diff --git a/plugins/help/data_source.py b/plugins/help/data_source.py index 94e357c4..04787fce 100644 --- a/plugins/help/data_source.py +++ b/plugins/help/data_source.py @@ -8,10 +8,10 @@ from configs.config import INITIAL_OPEN_CASE_COUNT, INITIAL_SETU_PROBABILITY, AD export = require("nonebot_plugin_manager") -width = 1200 +width = 1500 e_height = 0 -u_height = 700 -o_height = 1250 +u_height = 850 +o_height = 1500 # f_height = @@ -47,9 +47,9 @@ def create_help_img(): A.paste(e, (0, 0)) A.paste(u, (0, u_height)) A.paste(o, (0, o_height)) - A.text((10, h * 0.72), '大部分交互功能可以通过输入‘取消’,‘算了’来取消当前交互\n对我说 “指令名 帮助” 获取对应详细帮助\n' + A.text((10, h * 0.76), '大部分交互功能可以通过输入‘取消’,‘算了’来取消当前交互\n对我说 “指令名 帮助” 获取对应详细帮助\n' '可以通过 “滴滴滴- 后接内容” 联系管理员(有趣的想法尽管来吧!<还有Bug和建议>)\n[群管理员请看 管理员帮助(群主与管理员自带 5 级权限)]') - A.text((10, h * 0.79), f"【注】「色图概率:好感度 + 70%\n" + A.text((10, h * 0.81), f"【注】「色图概率:好感度 + 70%\n" f"\t\t每 3 点好感度 + 1次开箱,初始 20 次\n" f"\t\t开启/关闭功能只需输入‘开启/关闭 指令名’(每个功能的第一个指令)」\n" f"\t\t示例:开启签到") @@ -98,10 +98,10 @@ def create_group_help_img(group_id: int): A.paste(u, (0, u_height)) A.paste(o, (0, o_height)) # A.text((width, 10), f'总开关【{"√" if data["总开关"] else "×"}】') - A.text((10, h * 0.72), '大部分交互功能可以通过输入‘取消’,‘算了’来取消当前交互\n对我说 “指令名 帮助” 获取对应详细帮助\n' + A.text((10, h * 0.76), '大部分交互功能可以通过输入‘取消’,‘算了’来取消当前交互\n对我说 “指令名 帮助” 获取对应详细帮助\n' '可以通过 “滴滴滴- 后接内容” 联系管理员(有趣的想法尽管来吧!<还有Bug和建议>)' f'\n[群管理员请看 管理员帮助(群主与管理员自带 {ADMIN_DEFAULT_AUTH} 级权限)]') - A.text((10, h * 0.79), f"【注】「色图概率:好感度 + {int(INITIAL_SETU_PROBABILITY*100)}%\n" + A.text((10, h * 0.81), f"【注】「色图概率:好感度 + {int(INITIAL_SETU_PROBABILITY*100)}%\n" f"\t\t每 3 点好感度 + 1次开箱,初始 {INITIAL_OPEN_CASE_COUNT} 次\n" f"\t\t开启/关闭功能只需输入‘开启/关闭 指令名’(每个功能的第一个指令)」\n" f"\t\t示例:开启签到\n" @@ -132,7 +132,7 @@ def parse_cmd(cmd, group_id, plugin_list): def rcmd(dfg): - if dfg in ['prts', 'genshin', 'pretty', 'guardian', 'pcr']: + if dfg in ['prts', 'genshin', 'pretty', 'guardian', 'pcr', 'azur', 'onmyoji', 'fgo']: return 'draw_card_' + dfg if dfg == 'r': return 'pixiv_r' diff --git a/plugins/nonebot_plugin_picsearcher/__init__.py b/plugins/nonebot_plugin_picsearcher/__init__.py index 4fb2ee55..37ac4de9 100644 --- a/plugins/nonebot_plugin_picsearcher/__init__.py +++ b/plugins/nonebot_plugin_picsearcher/__init__.py @@ -9,6 +9,7 @@ from nonebot.typing import T_State from services.log import logger from util.utils import get_message_text, get_message_imgs from configs.config import MAX_FIND_IMG_COUNT +from nonebot.rule import to_me from .ex import get_des as get_des_ex from .iqdb import get_des as get_des_iqdb @@ -127,7 +128,7 @@ async def handle_pic(bot: Bot, event: GroupMessageEvent, state: T_State): pass -previous = on_command("上一张图是什么", aliases={"上一张", "这是什么"}) +previous = on_command("上一张图是什么", aliases={"上一张", "这是什么"}, rule=to_me(), block=True) @previous.handle() diff --git a/plugins/nonebot_plugin_withdraw/__init__.py b/plugins/nonebot_plugin_withdraw/__init__.py new file mode 100644 index 00000000..bdcb27e0 --- /dev/null +++ b/plugins/nonebot_plugin_withdraw/__init__.py @@ -0,0 +1,75 @@ +from typing import Any, Dict +from nonebot import get_driver, on_command +from nonebot.adapters.cqhttp import Bot, Event, GroupMessageEvent, PrivateMessageEvent +from nonebot.rule import to_me +from nonebot.typing import T_State, T_CalledAPIHook + +from .config import Config +global_config = get_driver().config +withdraw_config = Config(**global_config.dict()) + +msg_ids = {} +max_size = withdraw_config.withdraw_max_size + + +def get_key(msg_type, id): + return f'{msg_type}_{id}' + + +async def save_msg_id(bot: Bot, e: Exception, api: str, data: Dict[str, Any], result: Any) -> T_CalledAPIHook: + try: + if api == 'send_msg': + msg_type = data['message_type'] + id = data['group_id'] if msg_type == 'group' else data['user_id'] + elif api == 'send_private_msg': + msg_type = 'private' + id = data['user_id'] + elif api == 'send_group_msg': + msg_type = 'group' + id = data['group_id'] + else: + return + key = get_key(msg_type, id) + msg_id = result['message_id'] + + if key not in msg_ids: + msg_ids[key] = [] + msg_ids[key].append(msg_id) + if len(msg_ids) > max_size: + msg_ids[key].pop(0) + except: + pass + + +Bot._called_api_hook.add(save_msg_id) + + +withdraw = on_command('withdraw', aliases={'撤回'}, rule=to_me(), priority=1, block=True) + + +@withdraw.handle() +async def _(bot: Bot, event: Event, state: T_State): + if isinstance(event, GroupMessageEvent): + msg_type = 'group' + id = event.group_id + elif isinstance(event, PrivateMessageEvent): + msg_type = 'private' + id = event.user_id + else: + return + key = get_key(msg_type, id) + + num = event.get_plaintext().strip() + if not num: + num = 0 + elif num.isdigit() and 0 <= int(num) < len(msg_ids[key]): + num = int(num) + else: + return + + try: + idx = -num - 1 + await bot.delete_msg(message_id=msg_ids[key][idx]) + msg_ids[key].pop(idx) + except: + await withdraw.finish('撤回失败,可能已超时') diff --git a/plugins/nonebot_plugin_withdraw/config.py b/plugins/nonebot_plugin_withdraw/config.py new file mode 100644 index 00000000..5e26d25b --- /dev/null +++ b/plugins/nonebot_plugin_withdraw/config.py @@ -0,0 +1,8 @@ +from pydantic import BaseSettings + + +class Config(BaseSettings): + withdraw_max_size: int = 50 + + class Config: + extra = 'ignore' diff --git a/plugins/one_friend/__init__.py b/plugins/one_friend/__init__.py index a62d3635..3aa6cc28 100644 --- a/plugins/one_friend/__init__.py +++ b/plugins/one_friend/__init__.py @@ -8,7 +8,7 @@ from PIL import Image, ImageDraw, ImageFont from nonebot import on_regex from nonebot.typing import T_State from nonebot.adapters.cqhttp import Bot, GroupMessageEvent -from util.utils import get_message_text, get_local_proxy +from util.utils import get_message_text, get_local_proxy, get_message_at from util.img_utils import pic2b64 from configs.path_config import TTF_PATH import re @@ -28,10 +28,14 @@ async def get_pic(qq): @one_friend.handle() async def _(bot: Bot, event: GroupMessageEvent, state: T_State): arr = [] - member_list = await bot.get_group_member_list(self_id=event.self_id, group_id=event.group_id) - for member in member_list: - arr.append(member['user_id']) msg = get_message_text(event.json()) + qq = get_message_at(event.json()) + if not qq: + member_list = await bot.get_group_member_list(self_id=event.self_id, group_id=event.group_id) + for member in member_list: + arr.append(member['user_id']) + else: + qq = qq[0] msg = re.search(r'^我.*?朋友.*?' r'(想问问|说|让我问问|想问|让我问|想知道|让我帮他问问|让我帮他问|让我帮忙问|让我帮忙问问|问)(.*)', msg) @@ -39,7 +43,7 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State): if not msg: msg = '都不知道问什么' msg = msg.replace('他', '我').replace('她', '我') - image = Image.open(BytesIO(await get_pic(choice(arr)))) + image = Image.open(BytesIO(await get_pic(choice(arr) if not qq else qq))) img_origin = Image.new('RGBA', (100, 100), (255, 255, 255)) scale = 3 # 使用新的半径构建alpha层 diff --git a/plugins/pixiv/data_source.py b/plugins/pixiv/data_source.py index a82e2f57..cc3003b6 100644 --- a/plugins/pixiv/data_source.py +++ b/plugins/pixiv/data_source.py @@ -27,7 +27,7 @@ async def download_pixiv_imgs(urls: list, user_id: int) -> str: for img in urls: async with aiohttp.ClientSession(headers=get_user_agent()) as session: for _ in range(3): - async with session.get(img, proxy=get_local_proxy(), timeout=3) as response: + async with session.get(img, proxy=get_local_proxy(), timeout=2) as response: async with aiofiles.open(IMAGE_PATH + f'temp/{user_id}_{index}_pixiv.jpg', 'wb') as f: try: await f.write(await response.read()) @@ -53,7 +53,7 @@ async def parser_data(url: str, num: int) -> 'list, list, int': async with aiohttp.ClientSession() as session: for _ in range(3): try: - async with session.get(url, proxy=get_local_proxy(), timeout=4) as response: + async with session.get(url, proxy=get_local_proxy(), timeout=2) as response: data = feedparser.parse(await response.text())['entries'] break except TimeoutError: diff --git a/plugins/quotations.py b/plugins/quotations.py index 759ce6c1..cf9df91b 100644 --- a/plugins/quotations.py +++ b/plugins/quotations.py @@ -22,7 +22,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): async with aiohttp.ClientSession() as session: async with session.get(url, proxy=get_local_proxy(), timeout=5) as response: data = await response.json() - result = f'{data["hitokoto"]}\t————{data["from"]}' + result = f'{data["hitokoto"]}\t——{data["from"]}' await quotations.send(result) logger.info( f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'}) 发送语录:" diff --git a/plugins/send_setu/__init__.py b/plugins/send_setu/__init__.py index 277b587f..d0eed4fc 100644 --- a/plugins/send_setu/__init__.py +++ b/plugins/send_setu/__init__.py @@ -1,12 +1,13 @@ import random from nonebot import on_command, on_regex +from nonebot.permission import SUPERUSER from services.log import logger from models.sigin_group_user import SignGroupUser from util.utils import FreqLimiter, UserExistLimiter, is_number, get_message_text, get_message_imgs from nonebot.typing import T_State from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent, PrivateMessageEvent from .data_source import get_setu, get_luoxiang, search_online_setu, get_setu_urls, \ - check_r18_and_keyword, find_img_index + check_r18_and_keyword, find_img_index, delete_img, add_img from nonebot.adapters.cqhttp.exception import ActionFailed import re from models.count_user import UserCount @@ -39,6 +40,8 @@ path = "setu/" setu = on_command("色图", aliases={"涩图", "不够色", "来一发", "再来点"}, priority=5, block=True) setu_reg = on_regex('(.*)[份|发|张|个|次|点](.*)[瑟|色|涩]图', priority=5, block=True) find_setu = on_command("查色图", priority=5, block=True) +delete_setu = on_command('删除色图', aliases={'删除涩图'}, priority=5, block=True, permission=SUPERUSER) +upload_setu = on_command('上传色图', aliases={'上传涩图'}, priority=5, block=True, permission=SUPERUSER) @setu.handle() @@ -228,7 +231,9 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): logger.info( f"USER {event.user_id} GROUP {event.group_id if event.message_type != 'private' else 'private'}" f" 发送 {index} 色图成功") + _ulmt.set_False(event.user_id) else: + _ulmt.set_False(event.user_id) return if list(bot.config.nickname)[0].find(keyword) != -1: await setu.finish('咳咳咳,虽然我很可爱,但是我木有自己的色图~~~有的话记得发我一份呀') @@ -275,6 +280,32 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): await find_setu.send(await find_img_index(img, event.user_id), at_sender=True) +@delete_setu.handle() +async def _(bot: Bot, event: MessageEvent, state: T_State): + _id = get_message_text(event.json()) + if _id: + flag, text = delete_img(int(_id)) + if flag: + await delete_setu.finish(f'删除色图 id:{_id} 成功', at_sender=True) + else: + await delete_setu.finish(f'删除色图 id:{_id} 失败,{text}', at_sender=True) +@upload_setu.handle() +async def _(bot: Bot, event: MessageEvent, state: T_State): + imgs = get_message_imgs(event.json()) + if imgs: + lens, add_count = await add_img(imgs) + if add_count == 0: + await upload_setu.finish('上传的涩图已在色图库中,未成功上传,可以通过 查色图 来查看色图在图库中的id', at_sender=True) + id_s = '' + for i in range(add_count, 0, -1): + id_s += f'{lens - add_count} ' + await upload_setu.finish(f"这次一共为 色图 库 添加了 {add_count} 张图片\n" + f"依次的Id为:{id_s[:-1]}\n" + f"小真寻感谢您对图库的扩充!WW", at_sender=True) + logger.info( + f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'})" + f" 上传色图ID:{id_s[:-1]}") + diff --git a/plugins/send_setu/data_source.py b/plugins/send_setu/data_source.py index ec95f059..e28d6a41 100644 --- a/plugins/send_setu/data_source.py +++ b/plugins/send_setu/data_source.py @@ -143,14 +143,6 @@ async def check_r18_and_keyword(msg: str, user_id) -> 'str, int, int': return keyword, r18, num -# def delete_img(index): -# if os.path.exists(IMAGE_PATH + path + f"{index}.jpg"): -# img_hash = str(get_img_hash(IMAGE_PATH + f"setu/{index}.jpg")) -# tp = list(setu_hash_dict.keys())[list(setu_hash_dict.values()).index(img_hash)] -# logger.info(f"色图 {index}.jpg 与 {tp}.jpg 相似, 删除....") -# os.remove(IMAGE_PATH + path + f"{index}.jpg") - - async def find_img_index(img_url, user_id): try: setu_hash_dict = json.load(open(TXT_PATH + 'setu_img_hash.json')) @@ -168,3 +160,57 @@ async def find_img_index(img_url, user_id): return "该图不在色图库中!" +def delete_img(_id: int): + lens = len(os.listdir(IMAGE_PATH + path)) - 1 + if _id < 0 or _id > lens: + return False, f'超过上下限限制,上限:{lens}' + try: + os.remove(IMAGE_PATH + path + f'{_id}.jpg') + if _id != lens: + setu_hash_dict = json.load(open(TXT_PATH + 'setu_img_hash.json')) + setu_hash_dict[str(_id)] = setu_hash_dict[str(lens)] + os.rename(IMAGE_PATH + path + f'{lens}.jpg', IMAGE_PATH + path + f'{_id}.jpg') + with open(TXT_PATH + 'setu_img_hash.json', 'w') as f: + json.dump(setu_hash_dict, f, ensure_ascii=False, indent=4) + return True, '' + except Exception as e: + logger.error(f'删除色图错误 e:{e}') + return False, str(type(e)) + + +# 添加涩图 +async def add_img(imgs: list): + index = 0 + lens = len(os.listdir(IMAGE_PATH + path)) + add_count = 0 + setu_hash_dict = json.load(open(TXT_PATH + 'setu_img_hash.json')) + async with aiohttp.ClientSession() as session: + for img in imgs: + async with session.get(img, proxy=get_local_proxy(), timeout=5) as res: + async with aiofiles.open(IMAGE_PATH + f"temp/add_setu_check_{index}.jpg", 'wb') as f: + await f.write(await res.read()) + index += 1 + index -= 1 + for i in range(index, -1, -1): + img_hash = str(get_img_hash(IMAGE_PATH + f"temp/add_setu_check_{index}.jpg")) + print(f'img_hash: {img_hash}') + if img_hash not in setu_hash_dict.values(): + os.rename(IMAGE_PATH + f"temp/add_setu_check_{index}.jpg", IMAGE_PATH + path + f'/{lens}.jpg') + print(f'{lens}: {img_hash}') + setu_hash_dict[lens] = img_hash + lens += 1 + add_count += 1 + if add_count: + with open(TXT_PATH + 'setu_img_hash.json', 'w') as f: + json.dump(setu_hash_dict, f, ensure_ascii=False, indent=4) + return lens, add_count + + + + + + + + + + diff --git a/plugins/server_ip.py b/plugins/server_ip.py index b330a494..52f2f085 100644 --- a/plugins/server_ip.py +++ b/plugins/server_ip.py @@ -17,14 +17,15 @@ async def _(bot: Bot, event: PrivateMessageEvent, state: T_State): "|* 请不要发给其他人! *|\n" "csgo ~号键控制台输入 connect 121.40.195.22 进入服务器\n" "然后再公屏输入 !diy 来使用皮肤(英文感叹号,注意)\n" - "【说不定可以凑到内战噢,欢迎~{娱乐为主,别骂人球球了}】", at_sender=True) + "【说不定可以凑到内战噢,欢迎~{娱乐为主}】", at_sender=True) @server_ip.handle() async def _(bot: Bot, event: GroupMessageEvent, state: T_State): if event.group_id == 698279647: await server_ip.finish("嗨呀!当前服务器地址是:" - "\ncsgo:\n\tay: 121.40.195.22\n\twzt: 101.200.199.143\n我的世界:\n\t47.111.1.220:25565") + "\ncsgo:\n\tay: 121.40.195.22\n\t" + "wzt: 101.200.199.143\n\t夜之北枭: 101.132.170.254\n我的世界:\n\t47.111.1.220:25565") elif event.group_id == 1046451860: await server_ip.finish("嗨呀!当前服务器地址是:\n121.40.195.22\n !diy") else: diff --git a/plugins/songpicker2/__init__.py b/plugins/songpicker2/__init__.py index 3d839677..bd001da0 100644 --- a/plugins/songpicker2/__init__.py +++ b/plugins/songpicker2/__init__.py @@ -28,6 +28,8 @@ async def handle_songName(bot: Bot, event: Event, state: T_State): songInfoList = list() for songId in songIdList: songInfoDict = await dataget.songInfo(songId) + if songInfoDict == '网易云网络繁忙!': + await songpicker.finish('网易云网络繁忙!') songInfoList.append(songInfoDict) # songInfoMessage = await dataProcess.mergeSongInfo(songInfoList) # await songpicker.send(songInfoMessage) diff --git a/plugins/songpicker2/data_source.py b/plugins/songpicker2/data_source.py index c6069c52..fe60031e 100644 --- a/plugins/songpicker2/data_source.py +++ b/plugins/songpicker2/data_source.py @@ -90,7 +90,7 @@ class dataGet(dataApi): # ['nickname']] = r['hotComments'][i]['content'] # return songComments - async def songInfo(self, songId: int) -> dict: + async def songInfo(self, songId: int): ''' 根据传递的songId,获取歌曲名、歌手、专辑等信息,作为dict返回 ''' @@ -98,6 +98,9 @@ class dataGet(dataApi): r = await self.api.getSongInfo(songId) if r is None: raise WrongDataError + print(r) + if r['code'] == '-460': + return '网易云网络繁忙!' songInfo["songName"] = r["songs"][0]["name"] songArtists = list() diff --git a/plugins/statistics_hook.py b/plugins/statistics_hook.py index 7daaa97f..3e0e5e9b 100644 --- a/plugins/statistics_hook.py +++ b/plugins/statistics_hook.py @@ -80,7 +80,13 @@ def check_exists_key(group_id, plugin_name): _prefix_count_dict['total_statistics'][group_id][plugin_name] = 0 if not _prefix_count_dict['day_statistics'].get(group_id): _prefix_count_dict['day_statistics'][group_id] = { - plugin_name: 0, + '1': {plugin_name: 0}, + '2': {plugin_name: 0}, + '3': {plugin_name: 0}, + '4': {plugin_name: 0}, + '5': {plugin_name: 0}, + '6': {plugin_name: 0}, + '7': {plugin_name: 0}, } elif not _prefix_count_dict['day_statistics'][group_id].get(plugin_name): _prefix_count_dict['day_statistics'][group_id][plugin_name] = 0 diff --git a/plugins/update_gocqhttp/__init__.py b/plugins/update_gocqhttp/__init__.py index 8c1f5cbb..79b2596f 100644 --- a/plugins/update_gocqhttp/__init__.py +++ b/plugins/update_gocqhttp/__init__.py @@ -10,7 +10,6 @@ from configs.config import UPDATE_GOCQ_GROUP from pathlib import Path path = str((Path() / "resources" / "gocqhttp_file").absolute()) + '/' -print(path) lasted_gocqhttp = on_command("更新gocq", permission=GROUP, priority=5, block=True) @@ -23,7 +22,7 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State): # try: if event.group_id in UPDATE_GOCQ_GROUP: await lasted_gocqhttp.send('检测中...') - info = await download_gocq_lasted() + info = await download_gocq_lasted(path) if info == 'gocqhttp没有更新!': await lasted_gocqhttp.finish('gocqhttp没有更新!') if _ulmt.check(event.group_id): @@ -31,7 +30,7 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State): _ulmt.set_True(event.group_id) try: for file in os.listdir(path): - await upload_gocq_lasted(file, event.group_id) + await upload_gocq_lasted(path, file, event.group_id) logger.info(f'更新了cqhttp...{file}') await lasted_gocqhttp.send(f'gocqhttp更新了,已上传成功!\n更新内容:\n{info}') except Exception as e: @@ -49,13 +48,13 @@ async def _(): if UPDATE_GOCQ_GROUP: bot = get_bot() try: - info = await download_gocq_lasted() + info = await download_gocq_lasted(path) if info == 'gocqhttp没有更新!': logger.info('gocqhttp没有更新!') return for group in UPDATE_GOCQ_GROUP: for file in os.listdir(path): - await upload_gocq_lasted(file, group) + await upload_gocq_lasted(path, file, group) await bot.send_group_msg(group_id=group, message=f"gocqhttp更新了,已上传成功!\n更新内容:\n{info}") except Exception as e: logger.error(f'自动更新gocq出错 e:{e}') diff --git a/plugins/update_gocqhttp/data_source.py b/plugins/update_gocqhttp/data_source.py index 27ee1122..f49f82bb 100644 --- a/plugins/update_gocqhttp/data_source.py +++ b/plugins/update_gocqhttp/data_source.py @@ -7,16 +7,13 @@ import aiofiles from bs4 import BeautifulSoup import os if platform.system() == 'Windows': - path = os.getcwd() + '/resources/gocqhttp_file/' asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) -else: - path = r'/home/hibiki/hibikibot/resources/gocqhttp_file/' url = 'https://github.com/Mrs4s/go-cqhttp/releases' -async def download_gocq_lasted(): +async def download_gocq_lasted(path: str): async with aiohttp.ClientSession(headers=get_user_agent()) as session: async with session.get(url, proxy=get_local_proxy()) as response: soup = BeautifulSoup(await response.text(), 'lxml') @@ -52,7 +49,7 @@ async def download_gocq_lasted(): return update_info -async def upload_gocq_lasted(name, group_id): +async def upload_gocq_lasted(path, name, group_id): bot = get_bot() folder_id = 0 for folder in (await bot.get_group_root_files(group_id=group_id))['folders']: diff --git a/resources/gocqhttp_file/v0.9.40-fix5-linux-arm64.tar.gz b/resources/gocqhttp_file/v0.9.40-fix5-linux-arm64.tar.gz deleted file mode 100644 index 1a337e80..00000000 Binary files a/resources/gocqhttp_file/v0.9.40-fix5-linux-arm64.tar.gz and /dev/null differ diff --git a/resources/gocqhttp_file/v0.9.40-fix5-windows-amd64.zip b/resources/gocqhttp_file/v0.9.40-fix5-windows-amd64.zip deleted file mode 100644 index 9eb55425..00000000 Binary files a/resources/gocqhttp_file/v0.9.40-fix5-windows-amd64.zip and /dev/null differ