🚚 reorganize config_manager

This commit is contained in:
felinae98
2023-06-07 02:49:05 +08:00
parent 8a20897fe9
commit 6743929ca2
6 changed files with 452 additions and 411 deletions
+130
View File
@@ -0,0 +1,130 @@
import asyncio
from datetime import datetime
from nonebot import on_command
from nonebot.adapters import Bot
from nonebot.adapters.onebot.v11 import MessageEvent
from nonebot.adapters.onebot.v11.event import GroupMessageEvent, PrivateMessageEvent
from nonebot.adapters.onebot.v11.message import Message
from nonebot.adapters.onebot.v11.permission import GROUP_ADMIN, GROUP_OWNER
from nonebot.matcher import Matcher
from nonebot.params import ArgPlainText, ArgStr
from nonebot.permission import SUPERUSER
from nonebot.rule import Rule, to_me
from nonebot.typing import T_State
from nonebot_plugin_saa import TargetQQGroup
from .add_sub import do_add_sub
from .del_sub import do_del_sub
from .query_sub import do_query_sub
from .utils import (
common_platform,
configurable_to_me,
gen_handle_cancel,
set_target_user_info,
)
add_sub_matcher = on_command(
"添加订阅",
rule=configurable_to_me,
permission=GROUP_ADMIN | GROUP_OWNER | SUPERUSER,
priority=5,
block=True,
)
add_sub_matcher.handle()(set_target_user_info)
do_add_sub(add_sub_matcher)
query_sub_matcher = on_command("查询订阅", rule=configurable_to_me, priority=5, block=True)
query_sub_matcher.handle()(set_target_user_info)
do_query_sub(query_sub_matcher)
del_sub_matcher = on_command(
"删除订阅",
rule=configurable_to_me,
permission=GROUP_ADMIN | GROUP_OWNER | SUPERUSER,
priority=5,
block=True,
)
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, block=True
)
group_handle_cancel = gen_handle_cancel(group_manage_matcher, "已取消")
@group_manage_matcher.handle()
async def send_group_list_private(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")
res_text = "请选择需要管理的群:\n"
group_number_idx = {}
for idx, group in enumerate(groups, 1):
group_number_idx[idx] = group["group_id"]
res_text += f'{idx}. {group["group_id"]} - {group["group_name"]}\n'
res_text += "请输入左侧序号\n中止操作请输入'取消'"
# await group_manage_matcher.send(res_text)
state["_prompt"] = res_text
state["group_number_idx"] = group_number_idx
@group_manage_matcher.got(
"group_idx", Message.template("{_prompt}"), [group_handle_cancel]
)
async def do_choose_group_number(state: T_State, group_idx: str = ArgPlainText()):
group_number_idx: dict[int, int] = state["group_number_idx"]
assert group_number_idx
idx = int(group_idx)
if idx not in group_number_idx.keys():
await group_manage_matcher.reject("请输入正确序号")
state["group_idx"] = idx
group_number_idx: dict[int, int] = state["group_number_idx"]
idx: int = state["group_idx"]
group_id = group_number_idx[idx]
state["target_user_info"] = TargetQQGroup(group_id=group_id)
@group_manage_matcher.got(
"command", "请输入需要使用的命令:添加订阅,查询订阅,删除订阅,取消", [group_handle_cancel]
)
async def do_dispatch_command(
bot: Bot,
event: MessageEvent,
state: T_State,
matcher: Matcher,
command: str = ArgStr(),
):
if command not in {"添加订阅", "查询订阅", "删除订阅", "取消"}:
await group_manage_matcher.reject("请输入正确的命令")
permission = await matcher.update_permission(bot, event)
new_matcher = Matcher.new(
"message",
Rule(),
permission,
handlers=None,
temp=True,
priority=0,
block=True,
plugin=matcher.plugin,
module=matcher.module,
expire_time=datetime.now(),
default_state=matcher.state,
default_type_updater=matcher.__class__._default_type_updater,
default_permission_updater=matcher.__class__._default_permission_updater,
)
if command == "查询订阅":
do_query_sub(new_matcher)
elif command == "添加订阅":
do_add_sub(new_matcher)
else:
do_del_sub(new_matcher)
new_matcher_ins = new_matcher()
asyncio.create_task(new_matcher_ins.run(bot, event, state))
+160
View File
@@ -0,0 +1,160 @@
from typing import Type, cast
from nonebot.adapters import Message
from nonebot.adapters.onebot.v11 import Message as OB11Message
from nonebot.adapters.onebot.v11.utils import unescape
from nonebot.matcher import Matcher
from nonebot.params import ArgPlainText
from nonebot.typing import T_State
from nonebot_plugin_saa import PlatformTarget
from ..apis import check_sub_target
from ..config import config
from ..config.db_config import SubscribeDupException
from ..platform import Platform, platform_manager
from ..types import Target
from .utils import common_platform, ensure_user_info, gen_handle_cancel
def do_add_sub(add_sub: Type[Matcher]):
handle_cancel = gen_handle_cancel(add_sub, "已中止订阅")
add_sub.handle()(ensure_user_info(add_sub))
@add_sub.handle()
async def init_promote(state: T_State):
state["_prompt"] = (
"请输入想要订阅的平台,目前支持,请输入冒号左边的名称:\n"
+ "".join(
[
"{}{}\n".format(
platform_name, platform_manager[platform_name].name
)
for platform_name in common_platform
]
)
+ "要查看全部平台请输入:“全部”\n中止订阅过程请输入:“取消”"
)
@add_sub.got("platform", OB11Message.template("{_prompt}"), [handle_cancel])
async def parse_platform(state: T_State, platform: str = ArgPlainText()) -> None:
if not isinstance(state["platform"], Message):
return
if platform == "全部":
message = "全部平台\n" + "\n".join(
[
"{}{}".format(platform_name, platform.name)
for platform_name, platform in platform_manager.items()
]
)
await add_sub.reject(message)
elif platform == "取消":
await add_sub.finish("已中止订阅")
elif platform in platform_manager:
state["platform"] = platform
else:
await add_sub.reject("平台输入错误")
@add_sub.handle()
async def prepare_get_id(matcher: Matcher, state: T_State):
cur_platform = platform_manager[state["platform"]]
if cur_platform.has_target:
state["_prompt"] = (
("1." + cur_platform.parse_target_promot + "\n2.")
if cur_platform.parse_target_promot
else ""
) + "请输入订阅用户的id\n查询id获取方法请回复:“查询”"
else:
matcher.set_arg("raw_id", OB11Message("no id"))
state["id"] = "default"
state["name"] = await check_sub_target(state["platform"], Target(""))
@add_sub.got("raw_id", OB11Message.template("{_prompt}"), [handle_cancel])
async def got_id(state: T_State, raw_id: str = ArgPlainText()):
if state.get("id"):
return
try:
if raw_id == "查询":
url = "https://nonebot-bison.netlify.app/usage/#%E6%89%80%E6%94%AF%E6%8C%81%E5%B9%B3%E5%8F%B0%E7%9A%84-uid"
title = "Bison所支持的平台UID"
content = "查询相关平台的uid格式或获取方式"
image = "https://s3.bmp.ovh/imgs/2022/03/ab3cc45d83bd3dd3.jpg"
getId_share = f"[CQ:share,url={url},title={title},content={content},image={image}]" # 缩短字符串格式长度,以及方便后续修改为消息段格式
await add_sub.reject(OB11Message(getId_share))
platform = platform_manager[state["platform"]]
raw_id = await platform.parse_target(unescape(raw_id))
name = await check_sub_target(state["platform"], raw_id)
if not name:
await add_sub.reject("id输入错误")
state["id"] = raw_id
state["name"] = name
except (Platform.ParseTargetException):
await add_sub.reject("不能从你的输入中提取出id,请检查你输入的内容是否符合预期")
else:
await add_sub.send(
"即将订阅的用户为:{} {} {}\n如有错误请输入“取消”重新订阅".format(
state["platform"], state["name"], state["id"]
)
)
@add_sub.handle()
async def prepare_get_categories(matcher: Matcher, state: T_State):
if not platform_manager[state["platform"]].categories:
matcher.set_arg("raw_cats", OB11Message(""))
state["cats"] = []
return
state["_prompt"] = "请输入要订阅的类别,以空格分隔,支持的类别有:{}".format(
" ".join(list(platform_manager[state["platform"]].categories.values()))
)
@add_sub.got("raw_cats", OB11Message.template("{_prompt}"), [handle_cancel])
async def parser_cats(state: T_State, raw_cats: str = ArgPlainText()):
if "cats" in state.keys():
return
res = []
if platform_manager[state["platform"]].categories:
for cat in raw_cats.split():
if cat not in platform_manager[state["platform"]].reverse_category:
await add_sub.reject("不支持 {}".format(cat))
res.append(platform_manager[state["platform"]].reverse_category[cat])
state["cats"] = res
@add_sub.handle()
async def prepare_get_tags(matcher: Matcher, state: T_State):
if not platform_manager[state["platform"]].enable_tag:
matcher.set_arg("raw_tags", OB11Message(""))
state["tags"] = []
return
state["_prompt"] = '请输入要订阅/屏蔽的标签(不含#号)\n多个标签请使用空格隔开\n订阅所有标签输入"全部标签"\n具体规则回复"详情"'
@add_sub.got("raw_tags", OB11Message.template("{_prompt}"), [handle_cancel])
async def parser_tags(state: T_State, raw_tags: str = ArgPlainText()):
if "tags" in state.keys():
return
if raw_tags == "详情":
await add_sub.reject(
"订阅标签直接输入标签内容\n屏蔽标签请在标签名称前添加~号\n详见https://nonebot-bison.netlify.app/usage/#%E5%B9%B3%E5%8F%B0%E8%AE%A2%E9%98%85%E6%A0%87%E7%AD%BE-tag"
)
if raw_tags in ["全部标签", "全部", "全标签"]:
state["tags"] = []
else:
state["tags"] = raw_tags.split()
@add_sub.handle()
async def add_sub_process(state: T_State):
user = cast(PlatformTarget, state.get("target_user_info"))
assert isinstance(user, PlatformTarget)
try:
await config.add_subscribe(
user=user,
target=state["id"],
target_name=state["name"],
platform_name=state["platform"],
cats=state.get("cats", []),
tags=state.get("tags", []),
)
except SubscribeDupException:
await add_sub.finish(f"添加 {state['name']} 失败: 已存在该订阅")
except Exception as e:
await add_sub.finish(f"添加 {state['name']} 失败: {e}")
await add_sub.finish("添加 {} 成功".format(state["name"]))
+69
View File
@@ -0,0 +1,69 @@
from typing import Type
from nonebot.matcher import Matcher
from nonebot.params import EventPlainText
from nonebot.typing import T_State
from nonebot_plugin_saa import MessageFactory, PlatformTarget
from ..config import config
from ..platform import platform_manager
from ..types import Category
from ..utils import parse_text
from .utils import ensure_user_info, gen_handle_cancel
def do_del_sub(del_sub: Type[Matcher]):
handle_cancel = gen_handle_cancel(del_sub, "删除中止")
del_sub.handle()(ensure_user_info(del_sub))
@del_sub.handle()
async def send_list(state: T_State):
user_info = state["target_user_info"]
assert isinstance(user_info, PlatformTarget)
try:
sub_list = await config.list_subscribe(user_info)
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] = {
"platform_name": sub.target.platform_name,
"target": sub.target.target,
}
res += "{} {} {} {}\n".format(
index,
sub.target.platform_name,
sub.target.target_name,
sub.target.target,
)
platform = platform_manager[sub.target.platform_name]
if platform.categories:
res += " [{}]".format(
", ".join(
map(
lambda x: platform.categories[Category(x)],
sub.categories,
)
)
)
if platform.enable_tag:
res += " {}".format(", ".join(sub.tags))
res += "\n"
res += "请输入要删除的订阅的序号\n输入'取消'中止"
await MessageFactory(await parse_text(res)).send()
@del_sub.receive(parameterless=[handle_cancel])
async def do_del(state: T_State, index_str: str = EventPlainText()):
try:
index = int(index_str)
user_info = state["target_user_info"]
assert isinstance(user_info, PlatformTarget)
await config.del_subscribe(user_info, **state["sub_table"][index])
except Exception as e:
await del_sub.reject("删除错误")
else:
await del_sub.finish("删除成功")
+41
View File
@@ -0,0 +1,41 @@
from typing import Type
from nonebot.matcher import Matcher
from nonebot.typing import T_State
from nonebot_plugin_saa import MessageFactory, PlatformTarget
from ..config import config
from ..platform import platform_manager
from ..types import Category
from ..utils import parse_text
from .utils import ensure_user_info
def do_query_sub(query_sub: Type[Matcher]):
query_sub.handle()(ensure_user_info(query_sub))
@query_sub.handle()
async def _(state: T_State):
user_info = state["target_user_info"]
assert isinstance(user_info, PlatformTarget)
sub_list = await config.list_subscribe(user_info)
res = "订阅的帐号为:\n"
for sub in sub_list:
res += "{} {} {}".format(
# sub["target_type"], sub["target_name"], sub["target"]
sub.target.platform_name,
sub.target.target_name,
sub.target.target,
)
platform = platform_manager[sub.target.platform_name]
if platform.categories:
res += " [{}]".format(
", ".join(
map(lambda x: platform.categories[Category(x)], sub.categories)
)
)
if platform.enable_tag:
res += " {}".format(", ".join(sub.tags))
res += "\n"
await MessageFactory(await parse_text(res)).send()
await query_sub.finish()
+52
View File
@@ -0,0 +1,52 @@
from typing import Annotated, Type
from nonebot.adapters import Event
from nonebot.matcher import Matcher
from nonebot.params import Depends, EventPlainText, EventToMe
from nonebot.rule import Rule
from nonebot.typing import T_State
from nonebot_plugin_saa import extract_target
from ..platform import platform_manager
from ..plugin_config import plugin_config
def _configurable_to_me(to_me: bool = EventToMe()):
if plugin_config.bison_to_me:
return to_me
else:
return True
configurable_to_me = Rule(_configurable_to_me)
common_platform = [
p.platform_name
for p in filter(
lambda platform: platform.enabled and platform.is_common,
platform_manager.values(),
)
]
def gen_handle_cancel(matcher: Type[Matcher], message: str):
async def _handle_cancel(text: Annotated[str, EventPlainText()]):
if text == "取消":
await matcher.finish(message)
return Depends(_handle_cancel)
def ensure_user_info(matcher: Type[Matcher]):
async def _check_user_info(state: T_State):
if not state.get("target_user_info"):
await matcher.finish(
"No target_user_info set, this shouldn't happen, please issue"
)
return _check_user_info
async def set_target_user_info(event: Event, state: T_State):
user = extract_target(event)
state["target_user_info"] = user