mirror of
https://github.com/suyiiyii/nonebot-bison.git
synced 2026-05-10 10:47:56 +08:00
merge upstream
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import asyncio
|
||||
from asyncio.tasks import Task
|
||||
from datetime import datetime
|
||||
from typing import Optional, Type
|
||||
|
||||
@@ -12,7 +11,7 @@ from nonebot.internal.params import ArgStr
|
||||
from nonebot.internal.rule import Rule
|
||||
from nonebot.log import logger
|
||||
from nonebot.matcher import Matcher
|
||||
from nonebot.params import Depends, EventMessage, EventPlainText, EventToMe, EventType
|
||||
from nonebot.params import Depends, EventPlainText, EventToMe
|
||||
from nonebot.permission import SUPERUSER
|
||||
from nonebot.rule import to_me
|
||||
from nonebot.typing import T_State
|
||||
@@ -245,38 +244,46 @@ def do_del_sub(del_sub: Type[Matcher]):
|
||||
config: Config = Config()
|
||||
user_info = state["target_user_info"]
|
||||
assert isinstance(user_info, User)
|
||||
sub_list = config.list_subscribe(
|
||||
# state.get("_user_id") or event.group_id, "group"
|
||||
user_info.user,
|
||||
user_info.user_type,
|
||||
)
|
||||
res = "订阅的帐号为:\n"
|
||||
state["sub_table"] = {}
|
||||
for index, sub in enumerate(sub_list, 1):
|
||||
state["sub_table"][index] = {
|
||||
"target_type": sub["target_type"],
|
||||
"target": sub["target"],
|
||||
}
|
||||
res += "{} {} {} {}\n".format(
|
||||
index, sub["target_type"], sub["target_name"], sub["target"]
|
||||
try:
|
||||
sub_list = config.list_subscribe(
|
||||
# state.get("_user_id") or event.group_id, "group"
|
||||
user_info.user,
|
||||
user_info.user_type,
|
||||
)
|
||||
platform = platform_manager[sub["target_type"]]
|
||||
if platform.categories:
|
||||
res += " [{}]".format(
|
||||
", ".join(
|
||||
map(lambda x: platform.categories[Category(x)], sub["cats"])
|
||||
)
|
||||
assert sub_list
|
||||
except AssertionError:
|
||||
await del_sub.finish("暂无已订阅账号\n请使用“添加订阅”命令添加订阅")
|
||||
else:
|
||||
res = "订阅的帐号为:\n"
|
||||
state["sub_table"] = {}
|
||||
for index, sub in enumerate(sub_list, 1):
|
||||
state["sub_table"][index] = {
|
||||
"target_type": sub["target_type"],
|
||||
"target": sub["target"],
|
||||
}
|
||||
res += "{} {} {} {}\n".format(
|
||||
index, sub["target_type"], sub["target_name"], sub["target"]
|
||||
)
|
||||
if platform.enable_tag:
|
||||
res += " {}".format(", ".join(sub["tags"]))
|
||||
res += "\n"
|
||||
res += "请输入要删除的订阅的序号"
|
||||
await bot.send(event=event, message=Message(await parse_text(res)))
|
||||
platform = platform_manager[sub["target_type"]]
|
||||
if platform.categories:
|
||||
res += " [{}]".format(
|
||||
", ".join(
|
||||
map(lambda x: platform.categories[Category(x)], sub["cats"])
|
||||
)
|
||||
)
|
||||
if platform.enable_tag:
|
||||
res += " {}".format(", ".join(sub["tags"]))
|
||||
res += "\n"
|
||||
res += "请输入要删除的订阅的序号\n输入'取消'中止"
|
||||
await bot.send(event=event, message=Message(await parse_text(res)))
|
||||
|
||||
@del_sub.receive()
|
||||
async def do_del(event: Event, state: T_State):
|
||||
user_msg = str(event.get_message()).strip()
|
||||
if user_msg == "取消":
|
||||
await del_sub.finish("删除中止")
|
||||
try:
|
||||
index = int(str(event.get_message()).strip())
|
||||
index = int(user_msg)
|
||||
config = Config()
|
||||
user_info = state["target_user_info"]
|
||||
assert isinstance(user_info, User)
|
||||
@@ -317,12 +324,19 @@ del_sub_matcher = on_command(
|
||||
del_sub_matcher.handle()(set_target_user_info)
|
||||
do_del_sub(del_sub_matcher)
|
||||
|
||||
group_manage_matcher = on_command("群管理",rule=to_me(),permission=SUPERUSER,priority=4)
|
||||
group_manage_matcher = on_command("群管理", rule=to_me(), permission=SUPERUSER, priority=4)
|
||||
|
||||
|
||||
@group_manage_matcher.handle()
|
||||
async def send_group_list(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||
await group_manage_matcher.finish(Message("该功能只支持私聊使用,请私聊Bot"))
|
||||
|
||||
|
||||
@group_manage_matcher.handle()
|
||||
async def send_group_list_private(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||
await group_manage_matcher.finish(Message("该功能只支持私聊使用,请私聊Bot"))
|
||||
|
||||
|
||||
@group_manage_matcher.handle()
|
||||
async def send_group_list(bot: Bot, event: PrivateMessageEvent, state: T_State):
|
||||
groups = await bot.call_api("get_group_list")
|
||||
@@ -381,13 +395,13 @@ async def do_dispatch_command(
|
||||
"message",
|
||||
Rule(),
|
||||
permission,
|
||||
None,
|
||||
True,
|
||||
handlers=None,
|
||||
temp=True,
|
||||
priority=0,
|
||||
block=True,
|
||||
plugin=matcher.plugin,
|
||||
module=matcher.module,
|
||||
expire_time=datetime.now() + bot.config.session_expire_timeout,
|
||||
expire_time=datetime.now(),
|
||||
default_state=matcher.state,
|
||||
default_type_updater=matcher.__class__._default_type_updater,
|
||||
default_permission_updater=matcher.__class__._default_permission_updater,
|
||||
@@ -400,34 +414,3 @@ async def do_dispatch_command(
|
||||
do_del_sub(new_matcher)
|
||||
new_matcher_ins = new_matcher()
|
||||
asyncio.create_task(new_matcher_ins.run(bot, event, state))
|
||||
|
||||
|
||||
test_matcher = on_command("testtt")
|
||||
|
||||
|
||||
@test_matcher.handle()
|
||||
async def _handler(bot: Bot, event: Event, matcher: Matcher, state: T_State):
|
||||
permission = await matcher.update_permission(bot, event)
|
||||
new_matcher = Matcher.new(
|
||||
"message",
|
||||
Rule(),
|
||||
permission,
|
||||
None,
|
||||
True,
|
||||
priority=0,
|
||||
block=True,
|
||||
plugin=matcher.plugin,
|
||||
module=matcher.module,
|
||||
expire_time=datetime.now() + bot.config.session_expire_timeout,
|
||||
default_state=matcher.state,
|
||||
default_type_updater=matcher.__class__._default_type_updater,
|
||||
default_permission_updater=matcher.__class__._default_permission_updater,
|
||||
)
|
||||
|
||||
async def h():
|
||||
logger.warning("yes")
|
||||
await new_matcher.send("666")
|
||||
|
||||
new_matcher.handle()(h)
|
||||
new_matcher_ins = new_matcher()
|
||||
await new_matcher_ins.run(bot, event, state)
|
||||
|
||||
@@ -189,3 +189,47 @@ class MonsterSiren(NewMessage):
|
||||
compress=True,
|
||||
override_use_pic=False,
|
||||
)
|
||||
|
||||
|
||||
class TerraHistoricusComic(NewMessage):
|
||||
|
||||
categories = {4: "泰拉记事社漫画"}
|
||||
platform_name = "arknights"
|
||||
name = "明日方舟游戏信息"
|
||||
enable_tag = False
|
||||
enabled = True
|
||||
is_common = False
|
||||
schedule_type = "interval"
|
||||
schedule_kw = {"seconds": 30}
|
||||
has_target = False
|
||||
|
||||
async def get_target_name(self, _: Target) -> str:
|
||||
return "明日方舟游戏信息"
|
||||
|
||||
async def get_sub_list(self, _) -> list[RawPost]:
|
||||
async with httpx.AsyncClient() as client:
|
||||
raw_data = await client.get(
|
||||
"https://terra-historicus.hypergryph.com/api/recentUpdate"
|
||||
)
|
||||
return raw_data.json()["data"]
|
||||
|
||||
def get_id(self, post: RawPost) -> Any:
|
||||
return f'{post["comicCid"]}/{post["episodeCid"]}'
|
||||
|
||||
def get_date(self, _) -> None:
|
||||
return None
|
||||
|
||||
def get_category(self, _) -> Category:
|
||||
return Category(4)
|
||||
|
||||
async def parse(self, raw_post: RawPost) -> Post:
|
||||
url = f'https://terra-historicus.hypergryph.com/comic/{raw_post["comicCid"]}/episode/{raw_post["episodeCid"]}'
|
||||
return Post(
|
||||
"terra-historicus",
|
||||
text=f'{raw_post["title"]} - {raw_post["episodeShortTitle"]}',
|
||||
pics=[raw_post["coverUrl"]],
|
||||
url=url,
|
||||
target_name="泰拉记事社漫画",
|
||||
compress=True,
|
||||
override_use_pic=False,
|
||||
)
|
||||
|
||||
@@ -47,7 +47,7 @@ class Bilibili(NewMessage):
|
||||
)
|
||||
res_dict = json.loads(res.text)
|
||||
if res_dict["code"] == 0:
|
||||
return res_dict["data"]["cards"]
|
||||
return res_dict["data"].get("cards")
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
@@ -123,14 +123,18 @@ class Weibo(NewMessage):
|
||||
"Mobile Safari/537.36",
|
||||
}
|
||||
info = raw_post["mblog"]
|
||||
if info["isLongText"] or info["pic_num"] > 9:
|
||||
retweeted = False
|
||||
if info.get("retweeted_status"):
|
||||
retweeted = True
|
||||
pic_num = info["retweeted_status"]["pic_num"] if retweeted else info["pic_num"]
|
||||
if info["isLongText"] or pic_num > 9:
|
||||
async with httpx.AsyncClient() as client:
|
||||
res = await client.get(
|
||||
"https://m.weibo.cn/detail/{}".format(info["mid"]), headers=header
|
||||
)
|
||||
try:
|
||||
full_json_text = re.search(
|
||||
r'"status": ([\s\S]+),\s+"hotScheme"', res.text
|
||||
r'"status": ([\s\S]+),\s+"call"', res.text
|
||||
).group(1)
|
||||
info = json.loads(full_json_text)
|
||||
except:
|
||||
@@ -140,7 +144,12 @@ class Weibo(NewMessage):
|
||||
)
|
||||
)
|
||||
parsed_text = self._get_text(info["text"])
|
||||
pic_urls = [img["large"]["url"] for img in info.get("pics", [])]
|
||||
raw_pics_list = (
|
||||
info["retweeted_status"].get("pics", [])
|
||||
if retweeted
|
||||
else info.get("pics", [])
|
||||
)
|
||||
pic_urls = [img["large"]["url"] for img in raw_pics_list]
|
||||
detail_url = "https://weibo.com/{}/{}".format(info["user"]["id"], info["bid"])
|
||||
# return parsed_text, detail_url, pic_urls
|
||||
return Post(
|
||||
|
||||
@@ -24,7 +24,7 @@ class Post:
|
||||
pics: list[Union[str, bytes]] = field(default_factory=list)
|
||||
extra_msg: list[Message] = field(default_factory=list)
|
||||
|
||||
_message: Optional[list] = None
|
||||
_message: Optional[list[Message]] = None
|
||||
|
||||
def _use_pic(self):
|
||||
if not self.override_use_pic is None:
|
||||
@@ -107,10 +107,10 @@ class Post:
|
||||
self.pics = self.pics[matrix[0] * matrix[1] :]
|
||||
self.pics.insert(0, target_io.getvalue())
|
||||
|
||||
async def generate_messages(self):
|
||||
async def generate_messages(self) -> list[Message]:
|
||||
if self._message is None:
|
||||
await self._pic_merge()
|
||||
msgs = []
|
||||
msg_segments: list[MessageSegment] = []
|
||||
text = ""
|
||||
if self.text:
|
||||
if self._use_pic():
|
||||
@@ -123,22 +123,24 @@ class Post:
|
||||
if self.target_name:
|
||||
text += " {}".format(self.target_name)
|
||||
if self._use_pic():
|
||||
msgs.append(await parse_text(text))
|
||||
msg_segments.append(await parse_text(text))
|
||||
if not self.target_type == "rss" and self.url:
|
||||
msgs.append(MessageSegment.text(self.url))
|
||||
msg_segments.append(MessageSegment.text(self.url))
|
||||
else:
|
||||
if self.url:
|
||||
text += " \n详情: {}".format(self.url)
|
||||
msgs.append(MessageSegment.text(text))
|
||||
msg_segments.append(MessageSegment.text(text))
|
||||
for pic in self.pics:
|
||||
# if isinstance(pic, bytes):
|
||||
# pic = 'base64://' + base64.b64encode(pic).decode()
|
||||
# msgs.append(Message("[CQ:image,file={url}]".format(url=pic)))
|
||||
msgs.append(MessageSegment.image(pic))
|
||||
msg_segments.append(MessageSegment.image(pic))
|
||||
if self.compress:
|
||||
msgs = [reduce(lambda x, y: x.append(y), msgs, Message())]
|
||||
msgs = [reduce(lambda x, y: x.append(y), msg_segments, Message())]
|
||||
else:
|
||||
msgs = list(
|
||||
map(lambda msg_segment: Message([msg_segment]), msg_segments)
|
||||
)
|
||||
msgs.extend(self.extra_msg)
|
||||
self._message = msgs
|
||||
assert len(self._message) > 0, f"message list empty, {self}"
|
||||
return self._message
|
||||
|
||||
def __str__(self):
|
||||
|
||||
@@ -17,6 +17,18 @@ scheduler = AsyncIOScheduler(timezone="Asia/Shanghai")
|
||||
|
||||
@get_driver().on_startup
|
||||
async def _start():
|
||||
for platform_name, platform in platform_manager.items():
|
||||
if platform.schedule_type in ["cron", "interval", "date"]:
|
||||
logger.info(
|
||||
f"start scheduler for {platform_name} with {platform.schedule_type} {platform.schedule_kw}"
|
||||
)
|
||||
scheduler.add_job(
|
||||
fetch_and_send,
|
||||
platform.schedule_type,
|
||||
**platform.schedule_kw,
|
||||
args=(platform_name,),
|
||||
)
|
||||
|
||||
scheduler.configure({"apscheduler.timezone": "Asia/Shanghai"})
|
||||
scheduler.start()
|
||||
|
||||
@@ -65,19 +77,6 @@ async def fetch_and_send(target_type: str):
|
||||
)
|
||||
|
||||
|
||||
for platform_name, platform in platform_manager.items():
|
||||
if platform.schedule_type in ["cron", "interval", "date"]:
|
||||
logger.info(
|
||||
f"start scheduler for {platform_name} with {platform.schedule_type} {platform.schedule_kw}"
|
||||
)
|
||||
scheduler.add_job(
|
||||
fetch_and_send,
|
||||
platform.schedule_type,
|
||||
**platform.schedule_kw,
|
||||
args=(platform_name,),
|
||||
)
|
||||
|
||||
|
||||
class CustomLogHandler(LoguruHandler):
|
||||
def filter(self, record: logging.LogRecord):
|
||||
return record.msg != (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from email import message
|
||||
import time
|
||||
from email import message
|
||||
from typing import List, Literal, Union
|
||||
|
||||
from nonebot.adapters.onebot.v11.bot import Bot
|
||||
@@ -33,23 +33,19 @@ async def _do_send(
|
||||
elif user_type == "group-forward":
|
||||
await bot.send_group_forward_msg(group_id=user, messages=msg)
|
||||
|
||||
async def _do_send_forward(
|
||||
bot: "Bot", user: str, msgs: list
|
||||
):
|
||||
|
||||
async def _do_send_forward(bot: "Bot", user: str, msgs: list):
|
||||
group_msg = []
|
||||
bot_info = await bot.call_api("get_login_info")#猜测返回list 第一个为user_id,第二个为nickname
|
||||
bot_info = await bot.call_api("get_login_info") # 猜测返回list 第一个为user_id,第二个为nickname
|
||||
for msg in msgs:
|
||||
sub_msg = {
|
||||
"type": "node",
|
||||
"data": {
|
||||
"name": f"{bot_info[0]}",
|
||||
"uin": f"{bot_info[1]}",
|
||||
"content": msg
|
||||
}
|
||||
"data": {"name": f"{bot_info[0]}", "uin": f"{bot_info[1]}", "content": msg},
|
||||
}
|
||||
group_msg.append(sub_msg)
|
||||
await bot.call_api("send_group_forward_msg", group_id=user, message=group_msg)
|
||||
|
||||
|
||||
async def do_send_msgs():
|
||||
global LAST_SEND_TIME
|
||||
if time.time() - LAST_SEND_TIME < 1.5:
|
||||
@@ -81,11 +77,14 @@ async def _send_msgs_dispatch(
|
||||
await _do_send(bot, user, user_type, msg)
|
||||
|
||||
|
||||
async def send_msgs(bot: Bot, user, user_type: Literal["private", "group"], msgs: list):
|
||||
async def send_msgs(
|
||||
bot: Bot, user, user_type: Literal["private", "group"], msgs: list[Message]
|
||||
):
|
||||
if not plugin_config.bison_use_pic_merge or user_type == "private":
|
||||
for msg in msgs:
|
||||
await _send_msgs_dispatch(bot, user, user_type, msg)
|
||||
return
|
||||
msgs = msgs.copy()
|
||||
if plugin_config.bison_use_pic_merge == 1:
|
||||
await _send_msgs_dispatch(bot, user, "group", msgs.pop(0))
|
||||
if msgs:
|
||||
@@ -95,14 +94,28 @@ async def send_msgs(bot: Bot, user, user_type: Literal["private", "group"], msgs
|
||||
group_bot_info = await bot.get_group_member_info(
|
||||
group_id=user, user_id=int(bot.self_id), no_cache=True
|
||||
) # 调用api获取群内bot的相关参数
|
||||
forward_msg = Message(
|
||||
[
|
||||
MessageSegment.node_custom(
|
||||
group_bot_info["user_id"],
|
||||
nickname=group_bot_info["card"] or group_bot_info["nickname"],
|
||||
content=msg,
|
||||
)
|
||||
for msg in msgs
|
||||
]
|
||||
)
|
||||
# forward_msg = Message(
|
||||
# [
|
||||
# MessageSegment.node_custom(
|
||||
# group_bot_info["user_id"],
|
||||
# nickname=group_bot_info["card"] or group_bot_info["nickname"],
|
||||
# content=msg,
|
||||
# )
|
||||
# for msg in msgs
|
||||
# ]
|
||||
# )
|
||||
# FIXME: Because of https://github.com/nonebot/adapter-onebot/issues/9
|
||||
|
||||
forward_msg = [
|
||||
{
|
||||
"type": "node",
|
||||
"data": {
|
||||
"name": group_bot_info["card"] or group_bot_info["nickname"],
|
||||
"uin": group_bot_info["user_id"],
|
||||
"content": msg,
|
||||
},
|
||||
}
|
||||
for msg in msgs
|
||||
]
|
||||
|
||||
await _send_msgs_dispatch(bot, user, "group-forward", forward_msg)
|
||||
|
||||
Reference in New Issue
Block a user