This commit is contained in:
hibiki 2021-08-04 15:19:45 +08:00
parent b62399e203
commit 910af434ae
22 changed files with 571 additions and 700 deletions

View File

@ -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

View File

@ -150,7 +150,7 @@ def no_result() -> str:
random.choice(
[
"你在说啥子?",
f"纯洁的{list(get_bot().config.nickname)[0]}没听懂",
f"纯洁的小真寻没听懂",
"下次再告诉你(下次一定)",
"你觉得我听懂了吗?嗯?",
"我!不!知!道!",

View File

@ -4,14 +4,21 @@ 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):
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(
@ -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,6 +49,8 @@ async def _(bot: Bot, event: GroupRequestEvent, state: dict):
except ActionFailed:
pass
else:
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]),
@ -55,3 +65,12 @@ async def _(bot: Bot, event: GroupRequestEvent, state: dict):
"请确保已经群主或群管理沟通过!\n"
"等待管理员处理吧!",
)
@scheduler.scheduled_job(
"interval",
minutes=5,
)
async def _():
global exists_list
exists_list = []

View File

@ -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

View File

@ -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')}" \
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,15 +147,21 @@ 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])
if not _map.exists():
# padding_w, padding_h = data['padding']
data = data["slices"]
idx = 0
@ -157,20 +173,29 @@ async def download_map_init(session: ClientSession, semaphore: Semaphore, flag:
f"{map_path}/{idx}_{idj}.png",
session,
semaphore,
force_flag=flag
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")])
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")
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:
@ -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():
#

View File

@ -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,6 +48,7 @@ def save_data():
async def download_img_and_hash(url, group_id):
try:
async with aiohttp.ClientSession() as session:
async with session.get(url, proxy=get_local_proxy(), timeout=10) as response:
async with aiofiles.open(
@ -54,6 +56,8 @@ async def download_img_and_hash(url, group_id):
) 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 = {}

View File

@ -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)

View File

@ -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:

View File

@ -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()

View File

@ -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,35 +47,12 @@ 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)
@ -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

View File

@ -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)

View File

@ -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:

View File

@ -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))

View File

@ -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:
if not exists_flag:
exists_flag = True
await update_setu.send("开始更新色图...", at_sender=True)
await update_setu.finish(await update_setu_img(), 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()

View File

@ -25,6 +25,7 @@ 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"
if setu_data_file.exists() or r18_data_file.exists():
index = 0
r18_index = 0
count = 0
@ -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'

View File

@ -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 == "火星":

View File

@ -1,327 +0,0 @@
city_list = {
"北京": ["北京"],
"天津": ["天津"],
"山西": ["太原", "阳泉", "晋城", "长治", "临汾", "运城", "忻州", "吕梁", "晋中", "大同", "朔州"],
"河北": [
"沧州",
"石家庄",
"唐山",
"保定",
"廊坊",
"衡水",
"邯郸",
"邢台",
"张家口",
"辛集",
"秦皇岛",
"定州",
"承德",
"涿州",
],
"山东": [
"济南",
"淄博",
"聊城",
"德州",
"滨州",
"济宁",
"菏泽",
"枣庄",
"烟台",
"威海",
"泰安",
"青岛",
"临沂",
"莱芜",
"东营",
"潍坊",
"日照",
],
"河南": [
"郑州",
"新乡",
"鹤壁",
"安阳",
"焦作",
"濮阳",
"开封",
"驻马店",
"商丘",
"三门峡",
"南阳",
"洛阳",
"周口",
"许昌",
"信阳",
"漯河",
"平顶山",
"济源",
],
"广东": [
"珠海",
"中山",
"肇庆",
"深圳",
"清远",
"揭阳",
"江门",
"惠州",
"河源",
"广州",
"佛山",
"东莞",
"潮州",
"汕尾",
"梅州",
"阳江",
"云浮",
"韶关",
"湛江",
"汕头",
"茂名",
],
"浙江": ["舟山", "温州", "台州", "绍兴", "衢州", "宁波", "丽水", "金华", "嘉兴", "湖州", "杭州"],
"宁夏": ["中卫", "银川", "吴忠", "石嘴山", "固原"],
"江苏": [
"镇江",
"扬州",
"盐城",
"徐州",
"宿迁",
"无锡",
"苏州",
"南通",
"南京",
"连云港",
"淮安",
"常州",
"泰州",
],
"湖南": [
"长沙",
"邵阳",
"怀化",
"株洲",
"张家界",
"永州",
"益阳",
"湘西",
"娄底",
"衡阳",
"郴州",
"岳阳",
"常德",
"湘潭",
],
"吉林": ["长春", "长春", "通化", "松原", "四平", "辽源", "吉林", "延边", "白山", "白城"],
"福建": ["漳州", "厦门", "福州", "三明", "莆田", "宁德", "南平", "龙岩", "泉州"],
"甘肃": [
"张掖",
"陇南",
"兰州",
"嘉峪关",
"白银",
"武威",
"天水",
"庆阳",
"平凉",
"临夏",
"酒泉",
"金昌",
"甘南",
"定西",
],
"陕西": ["榆林", "西安", "延安", "咸阳", "渭南", "铜川", "商洛", "汉中", "宝鸡", "安康"],
"辽宁": [
"营口",
"铁岭",
"沈阳",
"盘锦",
"辽阳",
"锦州",
"葫芦岛",
"阜新",
"抚顺",
"丹东",
"大连",
"朝阳",
"本溪",
"鞍山",
],
"江西": ["鹰潭", "宜春", "上饶", "萍乡", "南昌", "景德镇", "吉安", "抚州", "新余", "九江", "赣州"],
"黑龙江": [
"伊春",
"七台河",
"牡丹江",
"鸡西",
"黑河",
"鹤岗",
"哈尔滨",
"大兴安岭",
"绥化",
"双鸭山",
"齐齐哈尔",
"佳木斯",
"大庆",
],
"安徽": [
"宣城",
"铜陵",
"六安",
"黄山",
"淮南",
"合肥",
"阜阳",
"亳州",
"安庆",
"池州",
"宿州",
"芜湖",
"马鞍山",
"淮北",
"滁州",
"蚌埠",
],
"湖北": [
"孝感",
"武汉",
"十堰",
"荆门",
"黄冈",
"襄阳",
"咸宁",
"随州",
"黄石",
"恩施",
"鄂州",
"荆州",
"宜昌",
"潜江",
"天门",
"神农架",
"仙桃",
],
"青海": ["西宁", "海西", "海东", "玉树", "黄南", "海南", "海北", "果洛"],
"新疆": [
"乌鲁木齐",
"克州",
"阿勒泰",
"五家渠",
"石河子",
"伊犁",
"吐鲁番",
"塔城",
"克拉玛依",
"喀什",
"和田",
"哈密",
"昌吉",
"博尔塔拉",
"阿克苏",
"巴音郭楞",
"阿拉尔",
"图木舒克",
"铁门关",
],
"贵州": ["铜仁", "黔东南", "贵阳", "安顺", "遵义", "黔西南", "黔南", "六盘水", "毕节"],
"四川": [
"遂宁",
"攀枝花",
"眉山",
"凉山",
"成都",
"巴中",
"广安",
"自贡",
"甘孜",
"资阳",
"宜宾",
"雅安",
"内江",
"南充",
"绵阳",
"泸州",
"凉山",
"乐山",
"广元",
"甘孜",
"德阳",
"达州",
"阿坝",
],
"上海": ["上海"],
"广西": [
"南宁",
"贵港",
"玉林",
"梧州",
"钦州",
"柳州",
"来宾",
"贺州",
"河池",
"桂林",
"防城港",
"崇左",
"北海",
"百色",
],
"西藏": ["拉萨", "山南", "日喀则", "那曲", "林芝", "昌都", "阿里"],
"云南": [
"昆明",
"红河",
"大理",
"玉溪",
"昭通",
"西双版纳",
"文山",
"曲靖",
"普洱",
"怒江",
"临沧",
"丽江",
"红河",
"迪庆",
"德宏",
"大理",
"楚雄",
"保山",
],
"内蒙古": [
"呼和浩特",
"乌兰察布",
"兴安",
"赤峰",
"呼伦贝尔",
"锡林郭勒",
"乌海",
"通辽",
"巴彦淖尔",
"阿拉善",
"鄂尔多斯",
"包头",
],
"海南": [
"海口",
"三沙",
"三亚",
"临高",
"五指山",
"陵水",
"文昌",
"万宁",
"白沙",
"乐东",
"澄迈",
"屯昌",
"定安",
"东方",
"保亭",
"琼中",
"琼海",
"儋州",
"昌江",
],
"重庆": ["重庆"],
"台湾": ["台北", "高雄", "基隆", "台中", "台南", "新竹", "嘉义", "新北", "桃园"],
}

View File

@ -1,13 +1,43 @@
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()
async def get_weather_of_city(city: str) -> str:
code = _check_exists_city(city)
if code == 999:
return "不要查一个省份的天气啊,很累人的!"
elif code == 998:
return "真寻只可以查询国内的天气喔..."
else:
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")
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:]
@ -19,3 +49,51 @@ async def get_weather_of_city(city) -> str:
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

View File

@ -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,28 +14,12 @@ 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
else:
await yiqing.finish(__plugin_usage__)
try:
result = await get_yiqing_data(province, city)
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'}) 查询疫情:"
+ result
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 查询疫情: {msg}"
)
else:
await yiqing.send("查询失败!!!!", at_sender=True)
@ -45,14 +27,3 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
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()

View File

@ -1,34 +0,0 @@
city_list = {
"北京": ["北京"],
"天津": ["天津"],
"山西": ["太原", "阳泉", "晋城", "长治", "临汾", "运城", "忻州", "吕梁", "晋中", "大同", "朔州"],
"河北": ["沧州", "石家庄", "唐山", "保定", "廊坊", "衡水", "邯郸", "邢台", "张家口", "辛集", "秦皇岛", "定州", "承德", "涿州"],
"山东": ["济南", "淄博", "聊城", "德州", "滨州", "济宁", "菏泽", "枣庄", "烟台", "威海", "泰安", "青岛", "临沂", "莱芜", "东营", "潍坊", "日照"],
"河南": ["郑州", "新乡", "鹤壁", "安阳", "焦作", "濮阳", "开封", "驻马店", "商丘", "三门峡", "南阳", "洛阳", "周口", "许昌", "信阳", "漯河", "平顶山", "济源"],
"广东": ["珠海", "中山", "肇庆", "深圳", "清远", "揭阳", "江门", "惠州", "河源", "广州", "佛山", "东莞", "潮州", "汕尾", "梅州", "阳江", "云浮", "韶关", "湛江", "汕头", "茂名"],
"浙江": ["舟山", "温州", "台州", "绍兴", "衢州", "宁波", "丽水", "金华", "嘉兴", "湖州", "杭州"],
"宁夏": ["中卫", "银川", "吴忠", "石嘴山", "固原"],
"江苏": ["镇江", "扬州", "盐城", "徐州", "宿迁", "无锡", "苏州", "南通", "南京", "连云港", "淮安", "常州", "泰州"],
"湖南": ["长沙", "邵阳", "怀化", "株洲", "张家界", "永州", "益阳", "湘西", "娄底", "衡阳", "郴州", "岳阳", "常德", "湘潭"],
"吉林": ["长春", "长春", "通化", "松原", "四平", "辽源", "吉林", "延边", "白山", "白城"],
"福建": ["漳州", "厦门", "福州", "三明", "莆田", "宁德", "南平", "龙岩", "泉州"],
"甘肃": ["张掖", "陇南", "兰州", "嘉峪关", "白银", "武威", "天水", "庆阳", "平凉", "临夏", "酒泉", "金昌", "甘南", "定西"],
"陕西": ["榆林", "西安", "延安", "咸阳", "渭南", "铜川", "商洛", "汉中", "宝鸡", "安康"],
"辽宁": ["营口", "铁岭", "沈阳", "盘锦", "辽阳", "锦州", "葫芦岛", "阜新", "抚顺", "丹东", "大连", "朝阳", "本溪", "鞍山"],
"江西": ["鹰潭", "宜春", "上饶", "萍乡", "南昌", "景德镇", "吉安", "抚州", "新余", "九江", "赣州"],
"黑龙江": ["伊春", "七台河", "牡丹江", "鸡西", "黑河", "鹤岗", "哈尔滨", "大兴安岭", "绥化", "双鸭山", "齐齐哈尔", "佳木斯", "大庆"],
"安徽": ["宣城", "铜陵", "六安", "黄山", "淮南", "合肥", "阜阳", "亳州", "安庆", "池州", "宿州", "芜湖", "马鞍山", "淮北", "滁州", "蚌埠"],
"湖北": ["孝感", "武汉", "十堰", "荆门", "黄冈", "襄阳", "咸宁", "随州", "黄石", "恩施", "鄂州", "荆州", "宜昌", "潜江", "天门", "神农架", "仙桃"],
"青海": ["西宁", "海西", "海东", "玉树", "黄南", "海南", "海北", "果洛"],
"新疆": ["乌鲁木齐", "克州", "阿勒泰", "五家渠", "石河子", "伊犁", "吐鲁番", "塔城", "克拉玛依", "喀什", "和田", "哈密", "昌吉", "博尔塔拉", "阿克苏", "巴音郭楞", "阿拉尔", "图木舒克", "铁门关"],
"贵州": ["铜仁", "黔东南", "贵阳", "安顺", "遵义", "黔西南", "黔南", "六盘水", "毕节"],
"四川": ["遂宁", "攀枝花", "眉山", "凉山", "成都", "巴中", "广安", "自贡", "甘孜", "资阳", "宜宾", "雅安", "内江", "南充", "绵阳", "泸州", "凉山", "乐山", "广元", "甘孜", "德阳", "达州", "阿坝"],
"上海": ["上海"],
"广西": ["南宁", "贵港", "玉林", "梧州", "钦州", "柳州", "来宾", "贺州", "河池", "桂林", "防城港", "崇左", "北海", "百色"],
"西藏": ["拉萨", "山南", "日喀则", "那曲", "林芝", "昌都", "阿里"],
"云南": ["昆明", "红河", "大理", "玉溪", "昭通", "西双版纳", "文山", "曲靖", "普洱", "怒江", "临沧", "丽江", "红河", "迪庆", "德宏", "大理", "楚雄", "保山"],
"内蒙古": ["呼和浩特", "乌兰察布", "兴安", "赤峰", "呼伦贝尔", "锡林郭勒", "乌海", "通辽", "巴彦淖尔", "阿拉善", "鄂尔多斯", "包头"],
"海南": ["海口", "三沙", "三亚", "临高", "五指山", "陵水", "文昌", "万宁", "白沙", "乐东", "澄迈", "屯昌", "定安", "东方", "保亭", "琼中", "琼海", "儋州", "昌江"],
"重庆": ["重庆"],
"台湾": ["台北", "高雄", "基隆", "台中", "台南", "新竹", "嘉义", "新北", "桃园"]
}

View File

@ -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 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"])
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:
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}"
)
break
return result
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

View File

@ -285,6 +285,7 @@ class CreateImg:
"""
说明
检查文本所需宽度是否大于图片宽度
参数
:param word: 文本内容
"""
return self.ttfont.getsize(word)[0] > self.w