diff --git a/plugins/admin_bot_manage/timing_task.py b/plugins/admin_bot_manage/timing_task.py index 45359728..8fcee5ab 100644 --- a/plugins/admin_bot_manage/timing_task.py +++ b/plugins/admin_bot_manage/timing_task.py @@ -2,6 +2,7 @@ from utils.utils import scheduler, get_bot from .data_source import update_member_info from services.log import logger from models.group_info import GroupInfo +from asyncpg.exceptions import ConnectionDoesNotExistError # 自动更新群员信息 @@ -37,5 +38,5 @@ async def _(): if g not in all_group: await update_member_info(g) logger.info(f"快速更新群信息以及权限:{g}") - except IndexError: + except (IndexError, ConnectionDoesNotExistError): pass diff --git a/plugins/ai/data_source.py b/plugins/ai/data_source.py index 5fad6e2f..aee2cb9a 100644 --- a/plugins/ai/data_source.py +++ b/plugins/ai/data_source.py @@ -150,7 +150,7 @@ def no_result() -> str: random.choice( [ "你在说啥子?", - f"纯洁的{list(get_bot().config.nickname)[0]}没听懂", + f"纯洁的小真寻没听懂", "下次再告诉你(下次一定)", "你觉得我听懂了吗?嗯?", "我!不!知!道!", diff --git a/plugins/auto_invite/__init__.py b/plugins/auto_invite/__init__.py index c8b3ed4e..113539af 100644 --- a/plugins/auto_invite/__init__.py +++ b/plugins/auto_invite/__init__.py @@ -4,27 +4,34 @@ from models.friend_user import FriendUser from datetime import datetime from configs.config import AUTO_ADD_FRIEND from nonebot.adapters.cqhttp.exception import ActionFailed +from utils.utils import scheduler __plugin_name__ = "好友群聊处理请求 [Hidden]" friend_req = on_request(priority=5) +exists_list = [] + + @friend_req.handle() async def _(bot: Bot, event: FriendRequestEvent, state: dict): - user = await bot.get_stranger_info(user_id=event.user_id) - nickname = user["nickname"] - await bot.send_private_msg( - user_id=int(list(bot.config.superusers)[0]), - message=f"*****一份好友申请*****\n" - f"昵称:{nickname}({event.user_id})\n" - f"自动同意:{'√' if AUTO_ADD_FRIEND else '×'}\n" - f"日期:{str(datetime.now()).split('.')[0]}\n" - f"备注:{event.comment}", - ) - if AUTO_ADD_FRIEND: - await bot.set_friend_add_request(flag=event.flag, approve=True) - await FriendUser.add_friend_info(user["user_id"], user["nickname"]) + global exists_list + if f"{event.user_id}" not in exists_list: + exists_list.append(f"{event.user_id}") + user = await bot.get_stranger_info(user_id=event.user_id) + nickname = user["nickname"] + await bot.send_private_msg( + user_id=int(list(bot.config.superusers)[0]), + message=f"*****一份好友申请*****\n" + f"昵称:{nickname}({event.user_id})\n" + f"自动同意:{'√' if AUTO_ADD_FRIEND else '×'}\n" + f"日期:{str(datetime.now()).split('.')[0]}\n" + f"备注:{event.comment}", + ) + if AUTO_ADD_FRIEND: + await bot.set_friend_add_request(flag=event.flag, approve=True) + await FriendUser.add_friend_info(user["user_id"], user["nickname"]) group_req = on_request(priority=5, block=True) @@ -32,6 +39,7 @@ group_req = on_request(priority=5, block=True) @group_req.handle() async def _(bot: Bot, event: GroupRequestEvent, state: dict): + global exists_list if event.sub_type == "invite": if str(event.user_id) in bot.config.superusers: try: @@ -41,17 +49,28 @@ async def _(bot: Bot, event: GroupRequestEvent, state: dict): except ActionFailed: pass else: - nickname = await FriendUser.get_user_name(event.user_id) - await bot.send_private_msg( - user_id=int(list(bot.config.superusers)[0]), - message=f"*****一份入群申请*****\n" - f"申请人:{nickname}({event.user_id})\n" - f"群聊:{event.group_id}\n" - f"邀请日期:{str(datetime.now()).split('.')[0]}", - ) - await bot.send_private_msg( - user_id=event.user_id, - message="想要邀请我偷偷入群嘛~已经提醒真寻的管理员大人了\n" - "请确保已经群主或群管理沟通过!\n" - "等待管理员处理吧!", - ) + if f"{event.user_id}:{event.group_id}" not in exists_list: + exists_list.append(f"{event.user_id}:{event.group_id}") + nickname = await FriendUser.get_user_name(event.user_id) + await bot.send_private_msg( + user_id=int(list(bot.config.superusers)[0]), + message=f"*****一份入群申请*****\n" + f"申请人:{nickname}({event.user_id})\n" + f"群聊:{event.group_id}\n" + f"邀请日期:{str(datetime.now()).split('.')[0]}", + ) + await bot.send_private_msg( + user_id=event.user_id, + message="想要邀请我偷偷入群嘛~已经提醒真寻的管理员大人了\n" + "请确保已经群主或群管理沟通过!\n" + "等待管理员处理吧!", + ) + + +@scheduler.scheduled_job( + "interval", + minutes=5, +) +async def _(): + global exists_list + exists_list = [] diff --git a/plugins/genshin/query_resource_points/map.py b/plugins/genshin/query_resource_points/map.py index 460aa850..75c3272c 100644 --- a/plugins/genshin/query_resource_points/map.py +++ b/plugins/genshin/query_resource_points/map.py @@ -1,7 +1,7 @@ from pathlib import Path from configs.path_config import IMAGE_PATH, TXT_PATH from utils.image_utils import CreateImg -from typing import Tuple +from typing import Tuple, List from math import sqrt, pow import random @@ -28,6 +28,7 @@ class Map: deviation: Tuple[int, int] = (25, 51), padding: int = 100, planning_route: bool = False, + ratio: float = 1, ): """ 参数: @@ -36,14 +37,21 @@ class Map: :param deviation: 坐标误差 :param padding: 截图外边距 :param planning_route: 是否规划最佳线路 + :param ratio: 压缩比率 """ self.map = CreateImg(0, 0, background=map_path) self.resource_name = resource_name self.center_x = center_point[0] self.center_y = center_point[1] self.deviation = deviation - self.padding = padding + self.padding = int(padding * ratio) self.planning_route = planning_route + self.ratio = ratio + + self.deviation = ( + int(self.deviation[0] * ratio), + int(self.deviation[1] * ratio), + ) data = json.load(open(resource_label_file, "r", encoding="utf8")) # 资源 id @@ -67,27 +75,27 @@ class Map: # 资源坐标 data = json.load(open(resource_point_file, "r", encoding="utf8")) self.resource_point = [ - ( - self.center_x + int(data[x]["x_pos"]), - self.center_y + int(data[x]["y_pos"]), + Resources( + int((self.center_x + data[x]["x_pos"]) * ratio), + int((self.center_y + data[x]["y_pos"]) * ratio), ) for x in data if x != "CENTER_POINT" and data[x]["label_id"] == self.resource_id ] # 传送锚点坐标 self.teleport_anchor_point = [ - ( - self.center_x + int(data[x]["x_pos"]), - self.center_y + int(data[x]["y_pos"]), + Resources( + int((self.center_x + data[x]["x_pos"]) * ratio), + int((self.center_y + data[x]["y_pos"]) * ratio), ) for x in data if x != "CENTER_POINT" and data[x]["label_id"] == self.teleport_anchor_id ] # 神像坐标 self.teleport_god_point = [ - ( - self.center_x + int(data[x]["x_pos"]), - self.center_y + int(data[x]["y_pos"]), + Resources( + int((self.center_x + data[x]["x_pos"]) * ratio), + int((self.center_y + data[x]["y_pos"]) * ratio), ) for x in data if x != "CENTER_POINT" and data[x]["label_id"] == self.teleport_god_id @@ -95,21 +103,23 @@ class Map: # 将地图上生成资源图标 def generate_resource_icon_in_map(self) -> int: - x_list = [x[0] for x in self.resource_point] - y_list = [x[1] for x in self.resource_point] + x_list = [x.x for x in self.resource_point] + y_list = [x.y for x in self.resource_point] min_width = min(x_list) - self.padding max_width = max(x_list) + self.padding min_height = min(y_list) - self.padding max_height = max(y_list) + self.padding + self._generate_transfer_icon((min_width, min_height, max_width, max_height)) + for res in self.resource_point: + icon = self._get_icon_image(self.resource_id) + self.map.paste( + icon, (res.x - self.deviation[0], res.y - self.deviation[1]), True + ) if self.planning_route: self._generate_best_route() - self._generate_transfer_icon((min_width, min_height, max_width, max_height)) - for x, y in self.resource_point: - icon = self._get_icon_image(self.resource_id) - self.map.paste(icon, (x - self.deviation[0], y - self.deviation[1]), True) self.map.crop((min_width, min_height, max_width, max_height)) rand = random.randint(1, 10000) - self.map.save(f'{IMAGE_PATH}/temp/genshin_map_{rand}.png') + self.map.save(f"{IMAGE_PATH}/temp/genshin_map_{rand}.png") return rand # 资源数量 @@ -119,40 +129,98 @@ class Map: # 生成传送锚点和神像 def _generate_transfer_icon(self, box: Tuple[int, int, int, int]): min_width, min_height, max_width, max_height = box - for points in [self.teleport_anchor_point, self.teleport_god_point]: + for resources in [self.teleport_anchor_point, self.teleport_god_point]: id_ = ( self.teleport_anchor_id - if points == self.teleport_anchor_point + if resources == self.teleport_anchor_point else self.teleport_god_id ) - for x, y in points: - if min_width < x < max_width and min_height < y < max_height: + for res in resources: + if min_width < res.x < max_width and min_height < res.y < max_height: icon = self._get_icon_image(id_) self.map.paste( - icon, (x - self.deviation[0], y - self.deviation[1]), True + icon, + (res.x - self.deviation[0], res.y - self.deviation[1]), + True, ) # 生成最优路线(说是最优其实就是直线最短) def _generate_best_route(self): - for x, y in self.resource_point: - min_deviation = 999999 - xy = None - for points in [ - self.resource_point, - self.teleport_anchor_point, - self.teleport_god_point, - ]: - for r_x, r_y in points: - distance = int(sqrt(pow(abs(r_x - x), 2) + pow(abs(r_y - y), 2))) - if distance < min_deviation and x != r_x and y != r_y: - min_deviation = distance - xy = (x, y, r_x, r_y) + resources_route = [] + # 先连上最近的资源路径 + for res in self.resource_point: + # 拿到最近的资源 + current_res, _ = res.get_resource_distance( + self.resource_point + + self.teleport_anchor_point + + self.teleport_god_point + ) + self.map.line( + (current_res.x, current_res.y, res.x, res.y), (255, 0, 0), width=1 + ) + resources_route.append((current_res, res)) + teleport_list = self.teleport_anchor_point + self.teleport_god_point + for res1, res2 in resources_route: + point_list = [x for x in resources_route if res1 in x or res2 in x] + if not list(set(point_list).intersection(set(teleport_list))): + if res1 not in teleport_list and res2 not in teleport_list: + # while True: + # tmp = [x for x in point_list] + # break + teleport1, distance1 = res1.get_resource_distance(teleport_list) + teleport2, distance2 = res2.get_resource_distance(teleport_list) + if distance1 > distance2: + self.map.line( + (teleport1.x, teleport1.y, res1.x, res1.y), + (255, 0, 0), + width=1, + ) + else: + self.map.line( + (teleport2.x, teleport2.y, res2.x, res2.y), + (255, 0, 0), + width=1, + ) - self.map.line(xy, (255, 0, 0), width=3) + # self.map.line(xy, (255, 0, 0), width=3) # 获取资源图标 def _get_icon_image(self, id_: int) -> "CreateImg": icon = icon_path / f"{id_}.png" if icon.exists(): - return CreateImg(50, 50, background=icon) - return CreateImg(50, 50, background=f"{icon_path}/box.png") + return CreateImg( + int(50 * self.ratio), int(50 * self.ratio), background=icon + ) + return CreateImg( + int(50 * self.ratio), + int(50 * self.ratio), + background=f"{icon_path}/box.png", + ) + + # def _get_shortest_path(self, res: 'Resources', res_2: 'Resources'): + + +# 资源类 +class Resources: + def __init__(self, x: int, y: int): + self.x = x + self.y = y + + def get_distance(self, x: int, y: int): + return int(sqrt(pow(abs(self.x - x), 2) + pow(abs(self.y - y), 2))) + + # 拿到资源在该列表中的最短路径 + def get_resource_distance(self, resources: List["Resources"]) -> "Resources, int": + current_res = None + min_distance = 999999 + for res in resources: + distance = self.get_distance(res.x, res.y) + if distance < min_distance and res != self: + current_res = res + min_distance = distance + return current_res, min_distance + + + + + diff --git a/plugins/genshin/query_resource_points/query_resource.py b/plugins/genshin/query_resource_points/query_resource.py index 2c5157de..e190269a 100644 --- a/plugins/genshin/query_resource_points/query_resource.py +++ b/plugins/genshin/query_resource_points/query_resource.py @@ -16,6 +16,7 @@ import nonebot import aiohttp import aiofiles import os + try: import ujson as json except ModuleNotFoundError: @@ -38,20 +39,29 @@ CENTER_POINT: Optional[Tuple[int, int]] = None resource_name_list: List[str] = [] +MAP_RATIO = 0.5 + # 查找资源 async def query_resource(resource_name: str) -> str: + global CENTER_POINT planning_route: bool = False if resource_name and resource_name[-2:] == "路径": resource_name = resource_name[:-2].strip() planning_route = True if not resource_name or resource_name not in resource_name_list: return f"未查找到 {resource_name} 资源,可通过 “原神资源列表” 获取全部资源名称.." - map_ = Map(resource_name, CENTER_POINT, planning_route=planning_route) + map_ = Map( + resource_name, CENTER_POINT, planning_route=planning_route, ratio=MAP_RATIO + ) count = map_.get_resource_count() - rand = await asyncio.get_event_loop().run_in_executor(None, map_.generate_resource_icon_in_map) - return f"{image(f'genshin_map_{rand}.png', 'temp')}" \ - f"\n\n※ {resource_name} 一共找到 {count} 个位置点\n※ 数据来源于米游社wiki" + rand = await asyncio.get_event_loop().run_in_executor( + None, map_.generate_resource_icon_in_map + ) + return ( + f"{image(f'genshin_map_{rand}.png', 'temp')}" + f"\n\n※ {resource_name} 一共找到 {count} 个位置点\n※ 数据来源于米游社wiki" + ) # 原神资源列表 @@ -76,7 +86,7 @@ async def init(flag: bool = False): global CENTER_POINT, resource_name_list semaphore = asyncio.Semaphore(10) async with aiohttp.ClientSession(headers=get_user_agent()) as session: - await download_map_init(session, semaphore, flag) + await download_map_init(session, semaphore, MAP_RATIO, flag) await download_resource_data(session, semaphore) await download_resource_type(session) if not CENTER_POINT: @@ -137,42 +147,57 @@ async def download_resource_data(session: ClientSession, semaphore: Semaphore): # 下载原神地图并拼图 -async def download_map_init(session: ClientSession, semaphore: Semaphore, flag: bool = False): - global CENTER_POINT +async def download_map_init( + session: ClientSession, semaphore: Semaphore, ratio: float = 1, flag: bool = False +): + global CENTER_POINT, MAP_RATIO map_path.mkdir(exist_ok=True, parents=True) + _map = map_path / "map.png" + if os.path.getsize(_map) > 1024 * 1024 * 30: + _map.unlink() async with session.get(MAP_URL, timeout=5) as response: if response.status == 200: data = await response.json() if data["message"] == "OK": data = json.loads(data["data"]["info"]["detail"]) CENTER_POINT = (data["origin"][0], data["origin"][1]) - # padding_w, padding_h = data['padding'] - data = data["slices"] - idx = 0 - for x in data: - idj = 0 - for j in x: - await download_image( - j["url"], - f"{map_path}/{idx}_{idj}.png", - session, - semaphore, - force_flag=flag - ) - idj += 1 - idx += 1 - map_width, map_height = CreateImg( - 0, 0, background=f"{map_path}/0_0.png" - ).size - lens = len([x for x in os.listdir(f"{map_path}") if x.startswith("0")]) - background_image = CreateImg( - map_width * lens, map_height * lens, map_width, map_height - ) - for i in range(idx): - for j in range(idj): - x = CreateImg(0, 0, background=f"{map_path}/{i}_{j}.png") - background_image.paste(x) - background_image.save(f"{map_path}/map.png") + if not _map.exists(): + # padding_w, padding_h = data['padding'] + data = data["slices"] + idx = 0 + for x in data: + idj = 0 + for j in x: + await download_image( + j["url"], + f"{map_path}/{idx}_{idj}.png", + session, + semaphore, + force_flag=flag, + ) + idj += 1 + idx += 1 + map_width, map_height = CreateImg( + 0, 0, background=f"{map_path}/0_0.png" + ).size + map_width = map_width * MAP_RATIO + map_height = map_height * MAP_RATIO + lens = len( + [x for x in os.listdir(f"{map_path}") if x.startswith("0")] + ) + background_image = CreateImg( + map_width * lens, map_height * lens, map_width, map_height + ) + for i in range(idx): + for j in range(idj): + x = CreateImg( + 0, + 0, + background=f"{map_path}/{i}_{j}.png", + ratio=MAP_RATIO, + ) + background_image.paste(x) + background_image.save(f"{map_path}/map.png") else: logger.warning(f'获取原神地图失败 msg: {data["message"]}') else: @@ -238,3 +263,8 @@ async def download_image( logger.warning(f"原神图片打开错误..已删除,等待下次更新... file: {path}") if os.path.exists(path): os.remove(path) + + +# +# def _get_point_ratio(): +# diff --git a/plugins/mute.py b/plugins/mute.py index 9ada8000..23763ecb 100644 --- a/plugins/mute.py +++ b/plugins/mute.py @@ -3,6 +3,7 @@ from nonebot.adapters.cqhttp import Bot, GroupMessageEvent from nonebot.adapters.cqhttp.permission import GROUP from utils.utils import get_message_text, is_number, get_message_imgs, get_local_proxy from nonebot.typing import T_State +from asyncio.exceptions import TimeoutError import time from nonebot.adapters.cqhttp.exception import ActionFailed from configs.path_config import DATA_PATH, IMAGE_PATH @@ -47,13 +48,16 @@ def save_data(): async def download_img_and_hash(url, group_id): - async with aiohttp.ClientSession() as session: - async with session.get(url, proxy=get_local_proxy(), timeout=10) as response: - async with aiofiles.open( - IMAGE_PATH + f"temp/mute_{group_id}_img.jpg", "wb" - ) as f: - await f.write(await response.read()) - return str(get_img_hash(IMAGE_PATH + f"temp/mute_{group_id}_img.jpg")) + try: + async with aiohttp.ClientSession() as session: + async with session.get(url, proxy=get_local_proxy(), timeout=10) as response: + async with aiofiles.open( + IMAGE_PATH + f"temp/mute_{group_id}_img.jpg", "wb" + ) as f: + await f.write(await response.read()) + return str(get_img_hash(IMAGE_PATH + f"temp/mute_{group_id}_img.jpg")) + except TimeoutError: + return '' mute_dict = {} diff --git a/plugins/nonebot_plugin_manager/__init__.py b/plugins/nonebot_plugin_manager/__init__.py index d21d65cf..52fe47b0 100644 --- a/plugins/nonebot_plugin_manager/__init__.py +++ b/plugins/nonebot_plugin_manager/__init__.py @@ -36,7 +36,7 @@ flmt = FreqLimiter(60) # 在 Matcher 运行前检测其是否启用 @run_preprocessor async def _(matcher: Matcher, bot: Bot, event: Event, state: T_State): - if not isinstance(event, MessageEvent): + if not isinstance(event, MessageEvent) and matcher.module != 'poke': return plugin = matcher.module group_id = _get_group_id(event) diff --git a/plugins/parse_bilibili_json.py b/plugins/parse_bilibili_json.py index 5a348422..1754af94 100644 --- a/plugins/parse_bilibili_json.py +++ b/plugins/parse_bilibili_json.py @@ -1,4 +1,4 @@ -from nonebot import on_message, on_command +from nonebot import on_message from services.log import logger from nonebot.adapters.cqhttp import Bot, GroupMessageEvent from nonebot.typing import T_State @@ -26,6 +26,7 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State): event.json() ): data = json.loads(get_message_json(event.json())[0]["data"]) + print(data) if data: if data.get("desc") == "哔哩哔哩": async with aiohttp.ClientSession(headers=get_user_agent()) as session: diff --git a/plugins/pix_gallery/pix.py b/plugins/pix_gallery/pix.py index 0e45a58b..46860f10 100644 --- a/plugins/pix_gallery/pix.py +++ b/plugins/pix_gallery/pix.py @@ -11,7 +11,7 @@ from models.pixiv import Pixiv import random -pix = on_command("pix", aliases={'PIX'}, priority=5, block=True) +pix = on_command("pix", aliases={"PIX"}, priority=5, block=True) @pix.handle() @@ -60,4 +60,4 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): logger.info( f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})" f" 查看PIX图库PID: {pid}" - ) \ No newline at end of file + ) diff --git a/plugins/send_setu/data_source.py b/plugins/send_setu/data_source.py index 261f6ee6..08252aca 100644 --- a/plugins/send_setu/data_source.py +++ b/plugins/send_setu/data_source.py @@ -2,7 +2,7 @@ from configs.path_config import IMAGE_PATH from utils.message_builder import image from services.log import logger from aiohttp.client_exceptions import ClientConnectorError -from utils.image_utils import get_img_hash +from utils.image_utils import get_img_hash, compressed_image from asyncpg.exceptions import UniqueViolationError from utils.utils import get_local_proxy from asyncio.exceptions import TimeoutError @@ -10,6 +10,7 @@ from typing import List, Optional from models.setu import Setu import aiohttp import aiofiles +import asyncio import os import random @@ -26,18 +27,15 @@ r18_path = "_r18/" # 获取url async def get_setu_urls( - tags: List[str], num: int = 1, r18: int = 0, command: str = '' + tags: List[str], num: int = 1, r18: int = 0, command: str = "" ) -> "List[str], List[str], List[tuple], int": tags = tags[:20] if len(tags) > 20 else tags params = { "r18": r18, # 添加r18参数 0为否,1为是,2为混合 "tag": "|".join(tags), # 若指定tag "num": 100, # 一次返回的结果数量,范围为1到10,不提供 APIKEY 时固定为1 - "size1200": "original", # 是否使用 master_1200 缩略图,以节省流量或提升加载速度 + "size": ["original"], # 是否使用 master_1200 缩略图,以节省流量或提升加载速度 } - urls = [] - text_list = [] - add_databases_list = [] async with aiohttp.ClientSession() as session: for count in range(3): logger.info(f"get_setu_url: count --> {count}") @@ -49,36 +47,13 @@ async def get_setu_urls( data = await response.json() if not data["error"]: data = data["data"] - for i in range(len(data)): - img_url = data[i]["urls"]["original"] - img_url = ( - img_url.replace("i.pixiv.cat", "i.pximg.net") - if "i.pixiv.cat" in img_url - else img_url - ) - title = data[i]["title"] - author = data[i]["author"] - pid = data[i]["pid"] - urls.append(img_url) - text_list.append( - f"title:{title}\nauthor:{author}\nPID:{pid}" - ) - tags = [] - for j in range(len(data[i]["tags"])): - tags.append(data[i]["tags"][j]) - if command != '色图r': - if 'R-18' in tags: - tags.remove('R-18') - add_databases_list.append( - ( - title, - author, - pid, - "", - img_url, - ",".join(tags), - ) - ) + ( + urls, + text_list, + add_databases_list, + ) = await asyncio.get_event_loop().run_in_executor( + None, _setu_data_process, data, command + ) num = num if num < len(data) else len(data) random_idx = random.sample(range(len(data)), num) x_urls = [] @@ -101,7 +76,9 @@ headers = { } -async def search_online_setu(url_: str, id_: int = None, path_: str = None) -> "MessageSegment, int": +async def search_online_setu( + url_: str, id_: int = None, path_: str = None +) -> "MessageSegment, int": if "i.pixiv.cat" in url_: url_ = url_.replace("i.pixiv.cat", "i.pximg.net") async with aiohttp.ClientSession(headers=headers) as session: @@ -110,18 +87,25 @@ async def search_online_setu(url_: str, id_: int = None, path_: str = None) -> " try: async with session.get(url_, proxy=get_local_proxy(), timeout=3) as res: if res.status == 200: - index = str(random.randint(1, 100000)) if id_ is None else id_ - path_ = 'temp' if path_ is None else path_ - if id_: - file = f'{index}.jpg' - else: - file = f'{index}_temp_setu.jpg' - async with aiofiles.open(f'{IMAGE_PATH}/{path_}/{file}', "wb") as f: + index = random.randint(1, 100000) if id_ is None else id_ + path_ = "temp" if not path_ else path_ + file = f"{index}_temp_setu.jpg" if not path_ else f"{index}.jpg" + async with aiofiles.open( + f"{IMAGE_PATH}/{path_}/{file}", "wb" + ) as f: try: await f.write(await res.read()) except TimeoutError: - # return '\n这图没下载过来~(网太差?)', -1, False continue + if id_ is not None: + if ( + os.path.getsize(f"{IMAGE_PATH}/{path_}/{index}.jpg") + > 1024 * 1024 * 1.5 + ): + compressed_image( + os.path.join(path_, f"{index}.jpg"), + os.path.join(path_, f"{index}.jpg"), + ) logger.info(f"下载 lolicon图片 {url_} 成功, id:{index}") return image(file, path_), index else: @@ -152,7 +136,7 @@ async def add_data_to_database(lst: List[tuple]): if tmp: for x in tmp: try: - r18 = 1 if 'R-18' in x[5] else 0 + r18 = 1 if "R-18" in x[5] else 0 idx = await Setu.get_image_count(r18) await Setu.add_setu_data( idx, @@ -229,3 +213,39 @@ async def find_img_index(img_url, user_id): f"PID:{setu_img.pid}" ) return "该图不在色图库中或色图库未更新!" + + +# 处理色图数据 +def _setu_data_process(data: dict, command: str) -> "list, list, list": + urls = [] + text_list = [] + add_databases_list = [] + for i in range(len(data)): + img_url = data[i]["urls"]["original"] + img_url = ( + img_url.replace("i.pixiv.cat", "i.pximg.net") + if "i.pixiv.cat" in img_url + else img_url + ) + title = data[i]["title"] + author = data[i]["author"] + pid = data[i]["pid"] + urls.append(img_url) + text_list.append(f"title:{title}\nauthor:{author}\nPID:{pid}") + tags = [] + for j in range(len(data[i]["tags"])): + tags.append(data[i]["tags"][j]) + if command != "色图r": + if "R-18" in tags: + tags.remove("R-18") + add_databases_list.append( + ( + title, + author, + pid, + "", + img_url, + ",".join(tags), + ) + ) + return urls, text_list, add_databases_list diff --git a/plugins/shop/gold.py b/plugins/shop/gold.py index 6a981fc4..2dba4ab0 100644 --- a/plugins/shop/gold.py +++ b/plugins/shop/gold.py @@ -19,7 +19,7 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State): @gold_rank.handle() async def _(bot: Bot, event: GroupMessageEvent, state: T_State): all_users = await BagUser.get_all_users(event.group_id) - all_user_id = [user.qq for user in all_users] + all_user_id = [user.user_qq for user in all_users] all_user_data = [user.gold for user in all_users] await gold_rank.finish( "金币排行:\n" + await init_rank(all_user_id, all_user_data, event.group_id) diff --git a/plugins/statistics_hook.py b/plugins/statistics_hook.py index 6d762102..6eb2be98 100644 --- a/plugins/statistics_hook.py +++ b/plugins/statistics_hook.py @@ -92,7 +92,7 @@ async def _( # print(f'model --> {model}') for plugin in plugins2info_dict: if plugin == model: - print(f'plugin --> {plugin}') + # print(f'plugin --> {plugin}') try: group_id = str(event.group_id) except AttributeError: diff --git a/plugins/super_cmd/__init__.py b/plugins/super_cmd/__init__.py index 6d0bc12f..46c7a951 100644 --- a/plugins/super_cmd/__init__.py +++ b/plugins/super_cmd/__init__.py @@ -4,7 +4,7 @@ from models.level_user import LevelUser from nonebot.typing import T_State from nonebot.adapters.cqhttp import Bot, MessageEvent, Message from nonebot.rule import to_me -from utils.utils import get_message_at, get_message_text, is_number, get_bot +from utils.utils import get_message_at, get_message_text, is_number, get_bot, scheduler from services.log import logger from .data_source import open_remind, close_remind from models.group_info import GroupInfo @@ -234,3 +234,17 @@ def _clear_data() -> float: file_size = 0 size += file_size return float(size) + + +# 早上好 +@scheduler.scheduled_job( + "cron", + hour=1, + minute=1, +) +async def _(): + size = await asyncio.get_event_loop().run_in_executor( + None, _clear_data + ) + logger.info('自动清理临时数据完成,' + "共清理了 {:.2f}MB 的数据...".format(size / 1024 / 1024)) + diff --git a/plugins/update_setu/__init__.py b/plugins/update_setu/__init__.py index dfe66696..e41622c3 100644 --- a/plugins/update_setu/__init__.py +++ b/plugins/update_setu/__init__.py @@ -12,15 +12,22 @@ __plugin_name__ = "更新色图 [Hidden]" __plugin_usage__ = '无' +exists_flag = False update_setu = on_command("更新色图", rule=to_me(), permission=SUPERUSER, priority=1, block=True) @update_setu.handle() async def _(bot: Bot, event: Event, state: T_State): + global exists_flag if DOWNLOAD_SETU: - await update_setu.send("开始更新色图...", at_sender=True) - await update_setu.finish(await update_setu_img(), at_sender=True) + if not exists_flag: + exists_flag = True + await update_setu.send("开始更新色图...", at_sender=True) + await update_setu.send(await update_setu_img(), at_sender=True) + exists_flag = False + else: + await update_setu.finish("色图正在更新....") else: await update_setu.finish('更新色图配置未开启') @@ -32,5 +39,6 @@ async def _(bot: Bot, event: Event, state: T_State): minute=30, ) async def _(): - if DOWNLOAD_SETU: + global exists_flag + if DOWNLOAD_SETU and not exists_flag: await update_setu_img() diff --git a/plugins/update_setu/data_source.py b/plugins/update_setu/data_source.py index eacc304b..71fc2457 100644 --- a/plugins/update_setu/data_source.py +++ b/plugins/update_setu/data_source.py @@ -25,53 +25,54 @@ async def update_old_setu_data(): path = Path(TXT_PATH) setu_data_file = path / "setu_data.json" r18_data_file = path / "r18_setu_data.json" - index = 0 - r18_index = 0 - count = 0 - fail_count = 0 - for file in [setu_data_file, r18_data_file]: - if file.exists(): - data = json.load(open(file, "r", encoding="utf8")) - for x in data: - if file == setu_data_file: - idx = index - if 'R-18' in data[x]["tags"]: - data[x]["tags"].remove('R-18') - else: - idx = r18_index - img_url = ( - data[x]["img_url"].replace("i.pixiv.cat", "i.pximg.net") - if "i.pixiv.cat" in data[x]["img_url"] - else data[x]["img_url"] - ) - # idx = r18_index if 'R-18' in data[x]["tags"] else index - try: - await Setu.add_setu_data( - idx, - data[x]["title"], - data[x]["author"], - data[x]["pid"], - data[x]["img_hash"], - img_url, - ",".join(data[x]["tags"]), - ) - count += 1 - if 'R-18' in data[x]["tags"]: - r18_index += 1 + if setu_data_file.exists() or r18_data_file.exists(): + index = 0 + r18_index = 0 + count = 0 + fail_count = 0 + for file in [setu_data_file, r18_data_file]: + if file.exists(): + data = json.load(open(file, "r", encoding="utf8")) + for x in data: + if file == setu_data_file: + idx = index + if 'R-18' in data[x]["tags"]: + data[x]["tags"].remove('R-18') else: - index += 1 - logger.info(f'添加旧色图数据成功 PID:{data[x]["pid"]} index:{idx}....') - except UniqueViolationError: - fail_count += 1 - logger.info(f'添加旧色图数据失败,色图重复 PID:{data[x]["pid"]} index:{idx}....') - file.unlink() - setu_url_path = path / "setu_url.json" - setu_r18_url_path = path / "setu_r18_url.json" - if setu_url_path.exists(): - setu_url_path.unlink() - if setu_r18_url_path.exists(): - setu_r18_url_path.unlink() - logger.info(f"更新旧色图数据完成,成功更新数据:{count} 条,累计失败:{fail_count} 条") + idx = r18_index + img_url = ( + data[x]["img_url"].replace("i.pixiv.cat", "i.pximg.net") + if "i.pixiv.cat" in data[x]["img_url"] + else data[x]["img_url"] + ) + # idx = r18_index if 'R-18' in data[x]["tags"] else index + try: + await Setu.add_setu_data( + idx, + data[x]["title"], + data[x]["author"], + data[x]["pid"], + data[x]["img_hash"], + img_url, + ",".join(data[x]["tags"]), + ) + count += 1 + if 'R-18' in data[x]["tags"]: + r18_index += 1 + else: + index += 1 + logger.info(f'添加旧色图数据成功 PID:{data[x]["pid"]} index:{idx}....') + except UniqueViolationError: + fail_count += 1 + logger.info(f'添加旧色图数据失败,色图重复 PID:{data[x]["pid"]} index:{idx}....') + file.unlink() + setu_url_path = path / "setu_url.json" + setu_r18_url_path = path / "setu_r18_url.json" + if setu_url_path.exists(): + setu_url_path.unlink() + if setu_r18_url_path.exists(): + setu_r18_url_path.unlink() + logger.info(f"更新旧色图数据完成,成功更新数据:{count} 条,累计失败:{fail_count} 条") headers = { @@ -142,7 +143,6 @@ async def update_setu_img(): break except (TimeoutError, ClientConnectorError) as e: logger.warning(f"{image.local_id}.jpg 更新失败 ..{type(e)}:{e}") - pass except Exception as e: _success -= 1 logger.error(f"更新色图 {image.local_id}.jpg 错误 {type(e)}: {e}") @@ -151,6 +151,8 @@ async def update_setu_img(): error_info.append( f"更新色图 {image.local_id}.jpg 错误 {type(e)}: {e}" ) + else: + logger.info(f'更新色图 {image.local_id}.jpg 已存在') await get_bot().send_private_msg( user_id=int(list(get_bot().config.superusers)[0]), message=f'{str(datetime.now()).split(".")[0]} 更新 色图 完成,实际更新 {_success} 张,以下为更新时未知错误:\n' diff --git a/plugins/weather/__init__.py b/plugins/weather/__init__.py index d5a788ea..0fecb438 100644 --- a/plugins/weather/__init__.py +++ b/plugins/weather/__init__.py @@ -1,10 +1,9 @@ from nonebot import on_regex -from .data_source import get_weather_of_city +from .data_source import get_weather_of_city, update_city, get_city_list from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent from jieba import posseg from services.log import logger from nonebot.typing import T_State -from .config import city_list import re from utils.utils import get_message_text @@ -26,14 +25,9 @@ async def _(bot: Bot, event: MessageEvent, state: T_State): msg += "市" city = "" if msg: - citys = [] - for x in city_list.keys(): - for city in city_list[x]: - citys.append(city) + city_list = get_city_list() for word in posseg.lcut(msg): - if word.word in city_list.keys(): - await weather.finish("不要查一个省的天气啊,这么大查起来很累人的..", at_sender=True) - if word.flag == "ns" or word.word[:-1] in citys: + if word.flag == "ns" or word.word[:-1] in city_list: city = str(word.word).strip() break if word.word == "火星": diff --git a/plugins/weather/config.py b/plugins/weather/config.py deleted file mode 100644 index 48efab72..00000000 --- a/plugins/weather/config.py +++ /dev/null @@ -1,327 +0,0 @@ -city_list = { - "北京": ["北京"], - "天津": ["天津"], - "山西": ["太原", "阳泉", "晋城", "长治", "临汾", "运城", "忻州", "吕梁", "晋中", "大同", "朔州"], - "河北": [ - "沧州", - "石家庄", - "唐山", - "保定", - "廊坊", - "衡水", - "邯郸", - "邢台", - "张家口", - "辛集", - "秦皇岛", - "定州", - "承德", - "涿州", - ], - "山东": [ - "济南", - "淄博", - "聊城", - "德州", - "滨州", - "济宁", - "菏泽", - "枣庄", - "烟台", - "威海", - "泰安", - "青岛", - "临沂", - "莱芜", - "东营", - "潍坊", - "日照", - ], - "河南": [ - "郑州", - "新乡", - "鹤壁", - "安阳", - "焦作", - "濮阳", - "开封", - "驻马店", - "商丘", - "三门峡", - "南阳", - "洛阳", - "周口", - "许昌", - "信阳", - "漯河", - "平顶山", - "济源", - ], - "广东": [ - "珠海", - "中山", - "肇庆", - "深圳", - "清远", - "揭阳", - "江门", - "惠州", - "河源", - "广州", - "佛山", - "东莞", - "潮州", - "汕尾", - "梅州", - "阳江", - "云浮", - "韶关", - "湛江", - "汕头", - "茂名", - ], - "浙江": ["舟山", "温州", "台州", "绍兴", "衢州", "宁波", "丽水", "金华", "嘉兴", "湖州", "杭州"], - "宁夏": ["中卫", "银川", "吴忠", "石嘴山", "固原"], - "江苏": [ - "镇江", - "扬州", - "盐城", - "徐州", - "宿迁", - "无锡", - "苏州", - "南通", - "南京", - "连云港", - "淮安", - "常州", - "泰州", - ], - "湖南": [ - "长沙", - "邵阳", - "怀化", - "株洲", - "张家界", - "永州", - "益阳", - "湘西", - "娄底", - "衡阳", - "郴州", - "岳阳", - "常德", - "湘潭", - ], - "吉林": ["长春", "长春", "通化", "松原", "四平", "辽源", "吉林", "延边", "白山", "白城"], - "福建": ["漳州", "厦门", "福州", "三明", "莆田", "宁德", "南平", "龙岩", "泉州"], - "甘肃": [ - "张掖", - "陇南", - "兰州", - "嘉峪关", - "白银", - "武威", - "天水", - "庆阳", - "平凉", - "临夏", - "酒泉", - "金昌", - "甘南", - "定西", - ], - "陕西": ["榆林", "西安", "延安", "咸阳", "渭南", "铜川", "商洛", "汉中", "宝鸡", "安康"], - "辽宁": [ - "营口", - "铁岭", - "沈阳", - "盘锦", - "辽阳", - "锦州", - "葫芦岛", - "阜新", - "抚顺", - "丹东", - "大连", - "朝阳", - "本溪", - "鞍山", - ], - "江西": ["鹰潭", "宜春", "上饶", "萍乡", "南昌", "景德镇", "吉安", "抚州", "新余", "九江", "赣州"], - "黑龙江": [ - "伊春", - "七台河", - "牡丹江", - "鸡西", - "黑河", - "鹤岗", - "哈尔滨", - "大兴安岭", - "绥化", - "双鸭山", - "齐齐哈尔", - "佳木斯", - "大庆", - ], - "安徽": [ - "宣城", - "铜陵", - "六安", - "黄山", - "淮南", - "合肥", - "阜阳", - "亳州", - "安庆", - "池州", - "宿州", - "芜湖", - "马鞍山", - "淮北", - "滁州", - "蚌埠", - ], - "湖北": [ - "孝感", - "武汉", - "十堰", - "荆门", - "黄冈", - "襄阳", - "咸宁", - "随州", - "黄石", - "恩施", - "鄂州", - "荆州", - "宜昌", - "潜江", - "天门", - "神农架", - "仙桃", - ], - "青海": ["西宁", "海西", "海东", "玉树", "黄南", "海南", "海北", "果洛"], - "新疆": [ - "乌鲁木齐", - "克州", - "阿勒泰", - "五家渠", - "石河子", - "伊犁", - "吐鲁番", - "塔城", - "克拉玛依", - "喀什", - "和田", - "哈密", - "昌吉", - "博尔塔拉", - "阿克苏", - "巴音郭楞", - "阿拉尔", - "图木舒克", - "铁门关", - ], - "贵州": ["铜仁", "黔东南", "贵阳", "安顺", "遵义", "黔西南", "黔南", "六盘水", "毕节"], - "四川": [ - "遂宁", - "攀枝花", - "眉山", - "凉山", - "成都", - "巴中", - "广安", - "自贡", - "甘孜", - "资阳", - "宜宾", - "雅安", - "内江", - "南充", - "绵阳", - "泸州", - "凉山", - "乐山", - "广元", - "甘孜", - "德阳", - "达州", - "阿坝", - ], - "上海": ["上海"], - "广西": [ - "南宁", - "贵港", - "玉林", - "梧州", - "钦州", - "柳州", - "来宾", - "贺州", - "河池", - "桂林", - "防城港", - "崇左", - "北海", - "百色", - ], - "西藏": ["拉萨", "山南", "日喀则", "那曲", "林芝", "昌都", "阿里"], - "云南": [ - "昆明", - "红河", - "大理", - "玉溪", - "昭通", - "西双版纳", - "文山", - "曲靖", - "普洱", - "怒江", - "临沧", - "丽江", - "红河", - "迪庆", - "德宏", - "大理", - "楚雄", - "保山", - ], - "内蒙古": [ - "呼和浩特", - "乌兰察布", - "兴安", - "赤峰", - "呼伦贝尔", - "锡林郭勒", - "乌海", - "通辽", - "巴彦淖尔", - "阿拉善", - "鄂尔多斯", - "包头", - ], - "海南": [ - "海口", - "三沙", - "三亚", - "临高", - "五指山", - "陵水", - "文昌", - "万宁", - "白沙", - "乐东", - "澄迈", - "屯昌", - "定安", - "东方", - "保亭", - "琼中", - "琼海", - "儋州", - "昌江", - ], - "重庆": ["重庆"], - "台湾": ["台北", "高雄", "基隆", "台中", "台南", "新竹", "嘉义", "新北", "桃园"], -} diff --git a/plugins/weather/data_source.py b/plugins/weather/data_source.py index 040b4014..212674e1 100644 --- a/plugins/weather/data_source.py +++ b/plugins/weather/data_source.py @@ -1,21 +1,99 @@ -import requests +from services.log import logger from utils.message_builder import image +from utils.user_agent import get_user_agent +from configs.path_config import TXT_PATH +from asyncio.exceptions import TimeoutError +from typing import List +from nonebot import Driver +from pathlib import Path +import aiohttp +import ujson as json +import nonebot + +driver: Driver = nonebot.get_driver() + +china_city = Path(TXT_PATH) / "china_city.json" + +try: + with open(china_city, "r", encoding="utf8") as f: + data = json.load(f) +except FileNotFoundError: + data = {} -async def get_weather_of_city(city) -> str: - url = "http://wthrcdn.etouch.cn/weather_mini?city=" + city - data_json = requests.get(url).json() - if "desc" in data_json: - if data_json["desc"] == "invilad-citykey": - return "你为啥不查火星的天气呢?小真寻只支持国内天气查询!!" + image("shengqi", "zhenxun") - elif data_json["desc"] == "OK": - w_type = data_json["data"]["forecast"][0]["type"] - w_max = data_json["data"]["forecast"][0]["high"][3:] - w_min = data_json["data"]["forecast"][0]["low"][3:] - fengli = data_json["data"]["forecast"][0]["fengli"][9:-3] - ganmao = data_json["data"]["ganmao"] - fengxiang = data_json["data"]["forecast"][0]["fengxiang"] - repass = f"{city}的天气是 {w_type} 天\n最高温度: {w_max}\n最低温度: {w_min}\n风力: {fengli} {fengxiang}\n{ganmao}" - return repass +async def get_weather_of_city(city: str) -> str: + code = _check_exists_city(city) + if code == 999: + return "不要查一个省份的天气啊,很累人的!" + elif code == 998: + return "真寻只可以查询国内的天气喔..." else: - return "好像出错了?" + async with aiohttp.ClientSession(headers=get_user_agent()) as session: + async with session.get( + f"http://wthrcdn.etouch.cn/weather_mini?city={city}", timeout=5 + ) as res: + data_json = json.loads(await res.text(encoding="utf8")) + if "desc" in data_json: + if data_json["desc"] == "invilad-citykey": + return "你为啥不查火星的天气呢?小真寻只支持国内天气查询!!" + image( + "shengqi", "zhenxun" + ) + elif data_json["desc"] == "OK": + w_type = data_json["data"]["forecast"][0]["type"] + w_max = data_json["data"]["forecast"][0]["high"][3:] + w_min = data_json["data"]["forecast"][0]["low"][3:] + fengli = data_json["data"]["forecast"][0]["fengli"][9:-3] + ganmao = data_json["data"]["ganmao"] + fengxiang = data_json["data"]["forecast"][0]["fengxiang"] + repass = f"{city}的天气是 {w_type} 天\n最高温度: {w_max}\n最低温度: {w_min}\n风力: {fengli} {fengxiang}\n{ganmao}" + return repass + else: + return "好像出错了?" + + +# 更新城市 +@driver.on_startup +async def update_city(): + global data + try: + async with aiohttp.ClientSession(headers=get_user_agent()) as session: + async with session.get( + "http://www.weather.com.cn/data/city3jdata/china.html", timeout=5 + ) as res: + provinces_data = json.loads(await res.text(encoding="utf8")) + for province in provinces_data.keys(): + data[provinces_data[province]] = [] + async with session.get( + f"http://www.weather.com.cn/data/city3jdata/provshi/{province}.html", + timeout=5, + ) as res: + city_data = json.loads(await res.text(encoding="utf8")) + for city in city_data.keys(): + data[provinces_data[province]].append(city_data[city]) + with open(china_city, "w", encoding="utf8") as f: + json.dump(data, f, indent=4, ensure_ascii=False) + logger.info("自动更新城市列表完成.....") + except TimeoutError: + logger.info("自动更新城市列表超时.....") + + +# 城市是否存在或是否是省份 +def _check_exists_city(city: str) -> int: + city = city if city[-1] != "市" else city[:-1] + for province in data.keys(): + # 查询省份了 + if city == province and len(data[province]) != 1: + return 999 + for city_ in data[province]: + if city_ == city: + return 200 + return 998 + + +def get_city_list() -> List[str]: + global data + city_list = [] + for p in data.keys(): + for c in data[p]: + city_list.append(c) + return city_list diff --git a/plugins/yiqing/__init__.py b/plugins/yiqing/__init__.py index 17a5145c..663310c4 100644 --- a/plugins/yiqing/__init__.py +++ b/plugins/yiqing/__init__.py @@ -1,10 +1,8 @@ from nonebot import on_command -from .data_source import get_yiqing_data, clear_data +from .data_source import get_yiqing_data from services.log import logger from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent from nonebot.typing import T_State -from .config import city_list -from utils.utils import scheduler __plugin_name__ = "疫情查询" __plugin_usage__ = "查询疫情帮助:\n\t对我说 查询疫情 省份/城市,我会回复疫情的实时数据\n\t示例: 查询疫情 温州" @@ -16,43 +14,16 @@ yiqing = on_command("疫情", aliases={"查询疫情", "疫情查询"}, priority @yiqing.handle() async def _(bot: Bot, event: MessageEvent, state: T_State): msg = str(event.get_message()).strip() - if not msg or msg in ["帮助"]: - await yiqing.finish(__plugin_usage__) - if msg: - if msg in city_list.keys(): - province = msg - city = "" - else: - for key in city_list.keys(): - if msg in city_list.get(key): - province = key - city = msg - break + result = await get_yiqing_data(msg) + if result: + await yiqing.send(result) + logger.info( + f"(USER {event.user_id}, GROUP " + f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 查询疫情: {msg}" + ) else: - await yiqing.finish(__plugin_usage__) - try: - result = await get_yiqing_data(province, city) - if result: - await yiqing.send(result) - logger.info( - f"(USER {event.user_id}, GROUP " - f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 查询疫情:" - + result - ) - else: - await yiqing.send("查询失败!!!!", at_sender=True) - logger.info( - f"(USER {event.user_id}, GROUP " - f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 查询疫情失败" - ) - except UnboundLocalError: - await yiqing.finish("参数正确吗?只要一个参数啊", at_sender=True) - - -@scheduler.scheduled_job( - "cron", - hour=0, - minute=1, -) -async def _(): - clear_data() + await yiqing.send("查询失败!!!!", at_sender=True) + logger.info( + f"(USER {event.user_id}, GROUP " + f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 查询疫情失败" + ) diff --git a/plugins/yiqing/config.py b/plugins/yiqing/config.py deleted file mode 100644 index 6aee7603..00000000 --- a/plugins/yiqing/config.py +++ /dev/null @@ -1,34 +0,0 @@ -city_list = { - "北京": ["北京"], - "天津": ["天津"], - "山西": ["太原", "阳泉", "晋城", "长治", "临汾", "运城", "忻州", "吕梁", "晋中", "大同", "朔州"], - "河北": ["沧州", "石家庄", "唐山", "保定", "廊坊", "衡水", "邯郸", "邢台", "张家口", "辛集", "秦皇岛", "定州", "承德", "涿州"], - "山东": ["济南", "淄博", "聊城", "德州", "滨州", "济宁", "菏泽", "枣庄", "烟台", "威海", "泰安", "青岛", "临沂", "莱芜", "东营", "潍坊", "日照"], - "河南": ["郑州", "新乡", "鹤壁", "安阳", "焦作", "濮阳", "开封", "驻马店", "商丘", "三门峡", "南阳", "洛阳", "周口", "许昌", "信阳", "漯河", "平顶山", "济源"], - "广东": ["珠海", "中山", "肇庆", "深圳", "清远", "揭阳", "江门", "惠州", "河源", "广州", "佛山", "东莞", "潮州", "汕尾", "梅州", "阳江", "云浮", "韶关", "湛江", "汕头", "茂名"], - "浙江": ["舟山", "温州", "台州", "绍兴", "衢州", "宁波", "丽水", "金华", "嘉兴", "湖州", "杭州"], - "宁夏": ["中卫", "银川", "吴忠", "石嘴山", "固原"], - "江苏": ["镇江", "扬州", "盐城", "徐州", "宿迁", "无锡", "苏州", "南通", "南京", "连云港", "淮安", "常州", "泰州"], - "湖南": ["长沙", "邵阳", "怀化", "株洲", "张家界", "永州", "益阳", "湘西", "娄底", "衡阳", "郴州", "岳阳", "常德", "湘潭"], - "吉林": ["长春", "长春", "通化", "松原", "四平", "辽源", "吉林", "延边", "白山", "白城"], - "福建": ["漳州", "厦门", "福州", "三明", "莆田", "宁德", "南平", "龙岩", "泉州"], - "甘肃": ["张掖", "陇南", "兰州", "嘉峪关", "白银", "武威", "天水", "庆阳", "平凉", "临夏", "酒泉", "金昌", "甘南", "定西"], - "陕西": ["榆林", "西安", "延安", "咸阳", "渭南", "铜川", "商洛", "汉中", "宝鸡", "安康"], - "辽宁": ["营口", "铁岭", "沈阳", "盘锦", "辽阳", "锦州", "葫芦岛", "阜新", "抚顺", "丹东", "大连", "朝阳", "本溪", "鞍山"], - "江西": ["鹰潭", "宜春", "上饶", "萍乡", "南昌", "景德镇", "吉安", "抚州", "新余", "九江", "赣州"], - "黑龙江": ["伊春", "七台河", "牡丹江", "鸡西", "黑河", "鹤岗", "哈尔滨", "大兴安岭", "绥化", "双鸭山", "齐齐哈尔", "佳木斯", "大庆"], - "安徽": ["宣城", "铜陵", "六安", "黄山", "淮南", "合肥", "阜阳", "亳州", "安庆", "池州", "宿州", "芜湖", "马鞍山", "淮北", "滁州", "蚌埠"], - "湖北": ["孝感", "武汉", "十堰", "荆门", "黄冈", "襄阳", "咸宁", "随州", "黄石", "恩施", "鄂州", "荆州", "宜昌", "潜江", "天门", "神农架", "仙桃"], - "青海": ["西宁", "海西", "海东", "玉树", "黄南", "海南", "海北", "果洛"], - "新疆": ["乌鲁木齐", "克州", "阿勒泰", "五家渠", "石河子", "伊犁", "吐鲁番", "塔城", "克拉玛依", "喀什", "和田", "哈密", "昌吉", "博尔塔拉", "阿克苏", "巴音郭楞", "阿拉尔", "图木舒克", "铁门关"], - "贵州": ["铜仁", "黔东南", "贵阳", "安顺", "遵义", "黔西南", "黔南", "六盘水", "毕节"], - "四川": ["遂宁", "攀枝花", "眉山", "凉山", "成都", "巴中", "广安", "自贡", "甘孜", "资阳", "宜宾", "雅安", "内江", "南充", "绵阳", "泸州", "凉山", "乐山", "广元", "甘孜", "德阳", "达州", "阿坝"], - "上海": ["上海"], - "广西": ["南宁", "贵港", "玉林", "梧州", "钦州", "柳州", "来宾", "贺州", "河池", "桂林", "防城港", "崇左", "北海", "百色"], - "西藏": ["拉萨", "山南", "日喀则", "那曲", "林芝", "昌都", "阿里"], - "云南": ["昆明", "红河", "大理", "玉溪", "昭通", "西双版纳", "文山", "曲靖", "普洱", "怒江", "临沧", "丽江", "红河", "迪庆", "德宏", "大理", "楚雄", "保山"], - "内蒙古": ["呼和浩特", "乌兰察布", "兴安", "赤峰", "呼伦贝尔", "锡林郭勒", "乌海", "通辽", "巴彦淖尔", "阿拉善", "鄂尔多斯", "包头"], - "海南": ["海口", "三沙", "三亚", "临高", "五指山", "陵水", "文昌", "万宁", "白沙", "乐东", "澄迈", "屯昌", "定安", "东方", "保亭", "琼中", "琼海", "儋州", "昌江"], - "重庆": ["重庆"], - "台湾": ["台北", "高雄", "基隆", "台中", "台南", "新竹", "嘉义", "新北", "桃园"] -} \ No newline at end of file diff --git a/plugins/yiqing/data_source.py b/plugins/yiqing/data_source.py index 33c0db5c..e9be4b32 100644 --- a/plugins/yiqing/data_source.py +++ b/plugins/yiqing/data_source.py @@ -1,67 +1,88 @@ -from datetime import datetime -import aiohttp from utils.user_agent import get_user_agent -import json -import os from configs.path_config import TXT_PATH -from utils.utils import get_local_proxy +from typing import List +from pathlib import Path +import ujson as json +import aiohttp + +china_city = Path(TXT_PATH) / "china_city.json" + +try: + with open(china_city, "r", encoding="utf8") as f: + data = json.load(f) +except FileNotFoundError: + data = {} -url = "https://api.yimian.xyz/coro/" +url = "https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5" -async def get_yiqing_data(province, city_=""): - if not os.path.exists(TXT_PATH + "yiqing/"): - os.mkdir(TXT_PATH + "yiqing/") - if not os.path.exists(TXT_PATH + "yiqing/" + str(datetime.now().date()) + ".json"): - async with aiohttp.ClientSession(headers=get_user_agent()) as session: - async with session.get(url, proxy=get_local_proxy(), timeout=7) as response: - datalist = await response.json() - with open( - TXT_PATH + "yiqing/" + str(datetime.now().date()) + ".json", "w" - ) as f: - json.dump(datalist, f) - datalist = json.load( - open(TXT_PATH + "yiqing/" + str(datetime.now().date()) + ".json", "r") - ) - result = "" - for data in datalist: - if data["provinceShortName"] == province: - if city_ == "": - result = ( - province - + "疫情数据:\n现存确诊: " - + str(data["currentConfirmedCount"]) - + "\n累计确诊: " - + str(data["confirmedCount"]) - + "\n治愈: " - + str(data["curedCount"]) - + "\n死亡: " - + str(data["deadCount"]) - ) - break +async def get_yiqing_data(area: str): + global data + province = None + city = None + province_type = "省" + if area == '中国': + province = area + province_type = "" + elif area in data.keys(): + province = area + if len(data[area]) == 1: + province_type = "市" + city = "" + else: + for p in data.keys(): + if area in data[p]: + province = p + city = area + if not province and not city: + return "小真寻只支持国内的疫情查询喔..." + async with aiohttp.ClientSession(headers=get_user_agent()) as session: + async with session.get(url, timeout=7) as response: + epidemic_data = json.loads((await response.json())["data"]) + last_update_time = epidemic_data["lastUpdateTime"] + if area == "中国": + data_ = epidemic_data["areaTree"][0] else: - for city in data["cities"]: - if city["cityName"] == city_: - result = ( - city_ - + "疫情数据:\n现存确诊: " - + str(city["currentConfirmedCount"]) - + "\n累计确诊: " - + str(city["confirmedCount"]) - + "\n治愈: " - + str(city["curedCount"]) - + "\n死亡: " - + str(city["deadCount"]) - ) - break - return result + data_ = [ + x + for x in epidemic_data["areaTree"][0]["children"] + if x["name"] == province + ][0] + if city: + try: + data_ = [x for x in data_["children"] if x["name"] == city][0] + except IndexError: + return '未查询到...' + confirm = data_["total"]["confirm"] # 累计确诊 + heal = data_["total"]["heal"] # 累计治愈 + dead = data_["total"]["dead"] # 累计死亡 + dead_rate = data_["total"]["deadRate"] # 死亡率 + heal_rate = data_["total"]["healRate"] # 治愈率 + now_confirm = data_["total"]["nowConfirm"] # 目前确诊 + suspect = data_["total"]["suspect"] # 疑似 + add_confirm = data_["today"]["confirm"] # 新增确诊 + x = f"{city}市" if city else f'{province}{province_type}' + return ( + f"{x} 疫情数据:\n" + f"\t目前确诊:\n" + f"\t\t确诊人数:{now_confirm}(+{add_confirm})\n" + f"\t\t疑似人数:{suspect}\n" + f"==================\n" + f"\t累计数据:\n" + f"\t\t确诊人数:{confirm}\n" + f"\t\t治愈人数:{heal}\n" + f"\t\t死亡人数:{dead}\n" + f"\t治愈率:{heal_rate}%\n" + f"\t死亡率:{dead_rate}%\n" + f"更新日期:{last_update_time}" + ) -def clear_data(): - for file in os.listdir(TXT_PATH + "yiqing/"): - os.remove(TXT_PATH + "yiqing/" + file) - - -if __name__ == "__main__": - print(get_yiqing_data("浙江", city_="")) +def get_city_list() -> List[str]: + global data + city_list = [] + for p in data.keys(): + for c in data[p]: + city_list.append(c) + return city_list diff --git a/utils/image_utils.py b/utils/image_utils.py index 96ab81ca..fc16df56 100644 --- a/utils/image_utils.py +++ b/utils/image_utils.py @@ -285,7 +285,8 @@ class CreateImg: """ 说明: 检查文本所需宽度是否大于图片宽度 - :param word: 文本内容 + 参数: + :param word: 文本内容 """ return self.ttfont.getsize(word)[0] > self.w