nonebot-plugin-shitbot 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nonebot_plugin_shitbot/__init__.py +21 -0
- nonebot_plugin_shitbot/aux.py +71 -0
- nonebot_plugin_shitbot/command.py +154 -0
- nonebot_plugin_shitbot/commands/__init__.py +27 -0
- nonebot_plugin_shitbot/commands/advrandpic_cmd.py +129 -0
- nonebot_plugin_shitbot/commands/autoreply_cmd.py +71 -0
- nonebot_plugin_shitbot/commands/autoreply_main_cmd.py +67 -0
- nonebot_plugin_shitbot/commands/convert_cmd.py +371 -0
- nonebot_plugin_shitbot/commands/help_cmd.py +92 -0
- nonebot_plugin_shitbot/commands/md2pic_cmd.py +195 -0
- nonebot_plugin_shitbot/commands/perm_cmd.py +392 -0
- nonebot_plugin_shitbot/commands/pixiv_cmd.py +144 -0
- nonebot_plugin_shitbot/commands/randpic_cmd.py +75 -0
- nonebot_plugin_shitbot/commands/session_cmd.py +79 -0
- nonebot_plugin_shitbot/commands/shitpost_cmd.py +189 -0
- nonebot_plugin_shitbot/config.py +186 -0
- nonebot_plugin_shitbot/config.yaml +23 -0
- nonebot_plugin_shitbot/css/github-markdown-dark-dimmed.css +1220 -0
- nonebot_plugin_shitbot/default_config.yaml +23 -0
- nonebot_plugin_shitbot/docs/help/advrandpic.md +61 -0
- nonebot_plugin_shitbot/docs/help/convert.md +37 -0
- nonebot_plugin_shitbot/docs/help/help.md +17 -0
- nonebot_plugin_shitbot/docs/help/imgs/md2picex1.png +0 -0
- nonebot_plugin_shitbot/docs/help/imgs/md2picex2.png +0 -0
- nonebot_plugin_shitbot/docs/help/index.md +22 -0
- nonebot_plugin_shitbot/docs/help/md2pic.md +57 -0
- nonebot_plugin_shitbot/docs/help/perm.md +110 -0
- nonebot_plugin_shitbot/docs/help/pixiv.md +42 -0
- nonebot_plugin_shitbot/docs/help/randpic.md +34 -0
- nonebot_plugin_shitbot/docs/help/session.md +38 -0
- nonebot_plugin_shitbot/docs/help/shitpost.md +39 -0
- nonebot_plugin_shitbot/docs//346/235/203/351/231/220/347/263/273/347/273/237.md +220 -0
- nonebot_plugin_shitbot/handlers.py +150 -0
- nonebot_plugin_shitbot/msgutils.py +442 -0
- nonebot_plugin_shitbot/parser.py +284 -0
- nonebot_plugin_shitbot/permissions.py +198 -0
- nonebot_plugin_shitbot/scripts/p2png.sh +38 -0
- nonebot_plugin_shitbot/scripts/png2fr.sh +19 -0
- nonebot_plugin_shitbot/scripts/png2v.sh +24 -0
- nonebot_plugin_shitbot/session.py +76 -0
- nonebot_plugin_shitbot/tasks.py +25 -0
- nonebot_plugin_shitbot-0.1.0.dist-info/METADATA +17 -0
- nonebot_plugin_shitbot-0.1.0.dist-info/RECORD +46 -0
- nonebot_plugin_shitbot-0.1.0.dist-info/WHEEL +5 -0
- nonebot_plugin_shitbot-0.1.0.dist-info/licenses/LICENSE +661 -0
- nonebot_plugin_shitbot-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from os import environ
|
|
2
|
+
|
|
3
|
+
# During unit tests, skip importing the heavy handler/command modules.
|
|
4
|
+
# These modules pull in the entire NoneBot stack and external plugins
|
|
5
|
+
# (e.g. nonebot_plugin_htmlrender → get_driver()). Pure-logic modules
|
|
6
|
+
# like parser.py should remain importable without a running NoneBot.
|
|
7
|
+
if not environ.get("PYTEST_RUNNING"):
|
|
8
|
+
from nonebot.plugin import PluginMetadata
|
|
9
|
+
|
|
10
|
+
from . import handlers # noqa: F401
|
|
11
|
+
from .config import ShitBotConfig
|
|
12
|
+
|
|
13
|
+
__plugin_meta__ = PluginMetadata(
|
|
14
|
+
name="shitbot",
|
|
15
|
+
description="个人自用自己手搓框架的多功能bot, 还在开发中",
|
|
16
|
+
usage="发送/help 查看帮助信息",
|
|
17
|
+
type="application",
|
|
18
|
+
homepage="https://github.com/Cmd-GZ/nonebot-plugin-shitbot",
|
|
19
|
+
config=ShitBotConfig,
|
|
20
|
+
supported_adapters={"~onebot.v11"},
|
|
21
|
+
)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
from nonebot.log import logger
|
|
7
|
+
|
|
8
|
+
from .config import config
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def validate_schema(data: Any, schema: Any) -> bool:
|
|
12
|
+
if schema is Any:
|
|
13
|
+
return True
|
|
14
|
+
if schema is None:
|
|
15
|
+
return False
|
|
16
|
+
if isinstance(schema, type):
|
|
17
|
+
return isinstance(data, schema)
|
|
18
|
+
if isinstance(schema, dict):
|
|
19
|
+
if not isinstance(data, dict):
|
|
20
|
+
return False
|
|
21
|
+
return all(
|
|
22
|
+
key in data and validate_schema(data[key], subschema)
|
|
23
|
+
for key, subschema in schema.items()
|
|
24
|
+
)
|
|
25
|
+
if isinstance(schema, list):
|
|
26
|
+
if not isinstance(data, list):
|
|
27
|
+
return False
|
|
28
|
+
length = len(schema)
|
|
29
|
+
if length < 1:
|
|
30
|
+
return False
|
|
31
|
+
return all(
|
|
32
|
+
validate_schema(item, schema[i if i < length else -1])
|
|
33
|
+
for i, item in enumerate(data)
|
|
34
|
+
)
|
|
35
|
+
return False
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
async def rm_path(path: Path):
|
|
39
|
+
if not path.exists():
|
|
40
|
+
return
|
|
41
|
+
if path.is_dir():
|
|
42
|
+
shutil.rmtree(path)
|
|
43
|
+
if path.is_file():
|
|
44
|
+
path.unlink()
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
async def rm_cache(group_id: str, user_id: str, pid: str):
|
|
48
|
+
cache_path = config.cache / group_id / user_id / pid
|
|
49
|
+
await rm_path(cache_path)
|
|
50
|
+
logger.info(f"已删除缓存: {cache_path}")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
async def stuff_download(
|
|
54
|
+
client: httpx.AsyncClient,
|
|
55
|
+
url: str | httpx.URL,
|
|
56
|
+
output_path: Path,
|
|
57
|
+
*,
|
|
58
|
+
referer: str | None = None,
|
|
59
|
+
):
|
|
60
|
+
try:
|
|
61
|
+
headers = {"Referer": referer} if referer is not None else {}
|
|
62
|
+
async with client.stream(
|
|
63
|
+
"GET", url, headers=headers, follow_redirects=True
|
|
64
|
+
) as resp:
|
|
65
|
+
resp.raise_for_status()
|
|
66
|
+
with open(output_path, "wb") as f:
|
|
67
|
+
async for chunk in resp.aiter_bytes():
|
|
68
|
+
f.write(chunk)
|
|
69
|
+
except Exception as e:
|
|
70
|
+
logger.error(f"下载 {url} 失败: {e}")
|
|
71
|
+
raise
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from nonebot.adapters.onebot.v11 import Bot, Message, MessageEvent
|
|
6
|
+
|
|
7
|
+
from .msgutils import send_msg
|
|
8
|
+
from .parser import BotArgParser
|
|
9
|
+
from .permissions import permissions
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from .session import BotSession
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# Base class of all the commands
|
|
16
|
+
class BotCommand:
|
|
17
|
+
# class fields:
|
|
18
|
+
# _name: command name
|
|
19
|
+
# _sentinel: used to prevent from calling __init__ directly
|
|
20
|
+
# fields:
|
|
21
|
+
# _bot: bot
|
|
22
|
+
# _session: the command's session
|
|
23
|
+
# _argv: current arguments of the command, which is also represented as the command's state
|
|
24
|
+
# _parser: arguments parser used to parse arguments
|
|
25
|
+
# _pid: command's id in its session
|
|
26
|
+
_argv: list[str] | None
|
|
27
|
+
_sentinel = object()
|
|
28
|
+
_name = "otherwise"
|
|
29
|
+
|
|
30
|
+
# Use make() instead of this
|
|
31
|
+
def __init__(self, bot: Bot, session: BotSession, *, _pid: int, _internal=None):
|
|
32
|
+
if _internal is not self._sentinel:
|
|
33
|
+
raise TypeError("Please use BotCommand.make() instead of BotCommand()")
|
|
34
|
+
self._bot = bot
|
|
35
|
+
self._session = session
|
|
36
|
+
self._argv = None
|
|
37
|
+
self._parser = self._init_parser()
|
|
38
|
+
self._pid = _pid
|
|
39
|
+
session.commands[_pid] = self
|
|
40
|
+
|
|
41
|
+
@classmethod
|
|
42
|
+
def make(
|
|
43
|
+
cls, bot: Bot, session: BotSession, *, _pid: int | None = None
|
|
44
|
+
) -> BotCommand | None:
|
|
45
|
+
if _pid is None:
|
|
46
|
+
_pid = session.curpid
|
|
47
|
+
if session.commands.get(_pid):
|
|
48
|
+
return None
|
|
49
|
+
return cls(bot, session, _pid=_pid, _internal=cls._sentinel)
|
|
50
|
+
|
|
51
|
+
@classmethod
|
|
52
|
+
def get_name(cls):
|
|
53
|
+
return cls._name
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def bot(self):
|
|
57
|
+
return self._bot
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def session(self):
|
|
61
|
+
return self._session
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def name(self):
|
|
65
|
+
return self._name
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
def argv(self):
|
|
69
|
+
return self._argv
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def pid(self):
|
|
73
|
+
return self._pid
|
|
74
|
+
|
|
75
|
+
def _init_parser(self):
|
|
76
|
+
return BotArgParser()
|
|
77
|
+
|
|
78
|
+
async def _send_format_error(self):
|
|
79
|
+
tip = f"命令格式错误:\n{self._parser.err}\n"
|
|
80
|
+
tip += f"输入 /help {self.name} 查看使用方法."
|
|
81
|
+
await self.send_msg(tip)
|
|
82
|
+
|
|
83
|
+
# Judge if the arguments are legal based on the parser and send msg if it's illegal
|
|
84
|
+
async def _legal_case(self, argv: list[str]):
|
|
85
|
+
if self._parser.is_valid(argv):
|
|
86
|
+
return True
|
|
87
|
+
await self._send_format_error()
|
|
88
|
+
return False
|
|
89
|
+
|
|
90
|
+
async def _guard_state(self):
|
|
91
|
+
if self._argv is not None:
|
|
92
|
+
if (
|
|
93
|
+
self._session is None
|
|
94
|
+
or (command := self._session.commands.get(self._pid)) is None
|
|
95
|
+
):
|
|
96
|
+
return False
|
|
97
|
+
tip = "错误:会话被占用\n"
|
|
98
|
+
tip += f"命令 {command.name} 正在运行,进行下一步前请先终止它或等待其完成。"
|
|
99
|
+
await self.send_msg(tip)
|
|
100
|
+
return False
|
|
101
|
+
return True
|
|
102
|
+
|
|
103
|
+
async def send_msg(
|
|
104
|
+
self,
|
|
105
|
+
msg: str | Message,
|
|
106
|
+
*,
|
|
107
|
+
group_id: str | None = None,
|
|
108
|
+
user_id: str | None = None,
|
|
109
|
+
):
|
|
110
|
+
if not self.session:
|
|
111
|
+
return
|
|
112
|
+
gid, uid = group_id, user_id
|
|
113
|
+
if gid is None:
|
|
114
|
+
gid = self.session.group_id
|
|
115
|
+
if uid is None:
|
|
116
|
+
uid = self.session.user_id
|
|
117
|
+
if gid == "public":
|
|
118
|
+
return
|
|
119
|
+
if gid == "private":
|
|
120
|
+
gid = None
|
|
121
|
+
uid = int(uid)
|
|
122
|
+
else:
|
|
123
|
+
gid = int(gid)
|
|
124
|
+
uid = None
|
|
125
|
+
await send_msg(bot=self.bot, group_id=gid, user_id=uid, msg=msg)
|
|
126
|
+
|
|
127
|
+
def _check_perm(self, entry_name: str):
|
|
128
|
+
if not self.session:
|
|
129
|
+
return False
|
|
130
|
+
return permissions.check_permission(
|
|
131
|
+
entry_name, self.session.group_id, self.session.user_id
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
async def roger(self, event: MessageEvent):
|
|
135
|
+
pass
|
|
136
|
+
|
|
137
|
+
# Main function
|
|
138
|
+
async def run(self, args: Message):
|
|
139
|
+
if not self.session:
|
|
140
|
+
self.unlock()
|
|
141
|
+
return
|
|
142
|
+
if not self._check_perm("otherwise"):
|
|
143
|
+
self.unlock()
|
|
144
|
+
return
|
|
145
|
+
await self.send_msg("无效命令,请输入/help获取帮助。")
|
|
146
|
+
self.unlock()
|
|
147
|
+
|
|
148
|
+
# Disconnect with the session, you should call in run() before return
|
|
149
|
+
def unlock(self):
|
|
150
|
+
if self._session is None:
|
|
151
|
+
return
|
|
152
|
+
self._session.commands.pop(self._pid, None)
|
|
153
|
+
self._session.release()
|
|
154
|
+
self._session = None
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from ..command import BotCommand
|
|
2
|
+
from .advrandpic_cmd import BotCommandAdvrandpic
|
|
3
|
+
from .autoreply_cmd import BotCommandAutoreply
|
|
4
|
+
from .autoreply_main_cmd import BotCommandAutoReplyMain
|
|
5
|
+
from .convert_cmd import BotCommandConvert
|
|
6
|
+
from .help_cmd import BotCommandHelp
|
|
7
|
+
from .md2pic_cmd import BotCommandMd2pic
|
|
8
|
+
from .perm_cmd import BotCommandPerm
|
|
9
|
+
from .pixiv_cmd import BotCommandPixiv
|
|
10
|
+
from .randpic_cmd import BotCommandRandpic
|
|
11
|
+
from .session_cmd import BotCommandSession
|
|
12
|
+
from .shitpost_cmd import BotCommandShitpost
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"BotCommand",
|
|
16
|
+
"BotCommandAdvrandpic",
|
|
17
|
+
"BotCommandAutoReplyMain",
|
|
18
|
+
"BotCommandAutoreply",
|
|
19
|
+
"BotCommandConvert",
|
|
20
|
+
"BotCommandHelp",
|
|
21
|
+
"BotCommandMd2pic",
|
|
22
|
+
"BotCommandPerm",
|
|
23
|
+
"BotCommandPixiv",
|
|
24
|
+
"BotCommandRandpic",
|
|
25
|
+
"BotCommandSession",
|
|
26
|
+
"BotCommandShitpost",
|
|
27
|
+
]
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
from nonebot.adapters.onebot.v11 import Bot, Message, MessageSegment
|
|
7
|
+
from nonebot.log import logger
|
|
8
|
+
|
|
9
|
+
from ..command import BotCommand
|
|
10
|
+
from ..parser import BotArgParser
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from ..session import BotSession
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class BotCommandAdvrandpic(BotCommand):
|
|
17
|
+
_name = "advrandpic"
|
|
18
|
+
|
|
19
|
+
def __init__(self, bot: Bot, session: BotSession, *, _pid: int, _internal=None):
|
|
20
|
+
super().__init__(bot, session, _pid=_pid, _internal=_internal)
|
|
21
|
+
self._r18 = 0
|
|
22
|
+
self._num = 1
|
|
23
|
+
self._tag = None
|
|
24
|
+
self._size = "regular"
|
|
25
|
+
|
|
26
|
+
def _init_parser(self):
|
|
27
|
+
parser = BotArgParser()
|
|
28
|
+
parser.set_rule(max=0)
|
|
29
|
+
parser.add_opt(
|
|
30
|
+
"-r", required=True, choice=["off", "on", "only"], default=["off"]
|
|
31
|
+
)
|
|
32
|
+
parser.add_opt(
|
|
33
|
+
"-s", required=True, choice=["original", "regular"], default=["regular"]
|
|
34
|
+
)
|
|
35
|
+
parser.add_opt("-t", required=True)
|
|
36
|
+
parser.add_opt("-n", required=True, type=int, default=[1])
|
|
37
|
+
return parser
|
|
38
|
+
|
|
39
|
+
async def run(self, args: Message):
|
|
40
|
+
if not self.session:
|
|
41
|
+
return
|
|
42
|
+
|
|
43
|
+
new_argv = args.extract_plain_text().strip().split()
|
|
44
|
+
if not await self._legal_case(new_argv):
|
|
45
|
+
if self._argv is None:
|
|
46
|
+
self.unlock()
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
if not await self._guard_state():
|
|
50
|
+
return
|
|
51
|
+
|
|
52
|
+
self._argv = new_argv
|
|
53
|
+
self._parser.parse_argv(self._argv)
|
|
54
|
+
|
|
55
|
+
r18 = self._parser.opts_value["-r"][0]
|
|
56
|
+
|
|
57
|
+
if r18 == "off":
|
|
58
|
+
self._r18 = 0
|
|
59
|
+
if r18 == "on":
|
|
60
|
+
self._r18 = 2
|
|
61
|
+
if r18 == "only":
|
|
62
|
+
self._r18 = 1
|
|
63
|
+
|
|
64
|
+
tags = self._parser.opts_value["-t"]
|
|
65
|
+
if len(tags) > 0:
|
|
66
|
+
self._tag = tags[0].split("&")
|
|
67
|
+
|
|
68
|
+
self._num = self._parser.opts_value["-n"][0]
|
|
69
|
+
self._num = max(self._num, 1)
|
|
70
|
+
self._num = min(self._num, 10)
|
|
71
|
+
if not self._check_perm("multisetu"):
|
|
72
|
+
self._num = 1
|
|
73
|
+
|
|
74
|
+
self._size = self._parser.opts_value["-s"][0]
|
|
75
|
+
|
|
76
|
+
if not self._check_perm("advrandpic"):
|
|
77
|
+
await self.send_msg("权限不足")
|
|
78
|
+
self.unlock()
|
|
79
|
+
return
|
|
80
|
+
|
|
81
|
+
if self._r18 and not self._check_perm("nsfw"):
|
|
82
|
+
await self.send_msg("权限不足")
|
|
83
|
+
self.unlock()
|
|
84
|
+
return
|
|
85
|
+
|
|
86
|
+
api = "https://api.lolicon.app/setu/v2"
|
|
87
|
+
payload: dict[str, Any] = {
|
|
88
|
+
"r18": self._r18,
|
|
89
|
+
"num": self._num,
|
|
90
|
+
"size": self._size,
|
|
91
|
+
}
|
|
92
|
+
if self._tag is not None:
|
|
93
|
+
payload["tag"] = self._tag
|
|
94
|
+
headers = {"Content-Type": "application/json"}
|
|
95
|
+
|
|
96
|
+
async with httpx.AsyncClient() as client:
|
|
97
|
+
response = await client.post(api, headers=headers, json=payload)
|
|
98
|
+
if response.status_code != 200:
|
|
99
|
+
logger.error(f"api调用失败, 状态码{response.status_code}")
|
|
100
|
+
self.unlock()
|
|
101
|
+
return
|
|
102
|
+
|
|
103
|
+
data = response.json()
|
|
104
|
+
|
|
105
|
+
if len(data["data"]) < self._num:
|
|
106
|
+
await self.send_msg(f"未找到指定数量的图片,仅找到 {len(data['data'])} 张")
|
|
107
|
+
|
|
108
|
+
for pic in data["data"]:
|
|
109
|
+
pid = str(pic["pid"])
|
|
110
|
+
title = pic["title"]
|
|
111
|
+
author = pic["author"]
|
|
112
|
+
url = pic["urls"][self._size]
|
|
113
|
+
text = f"标题: {title}\n作者: {author}\nPID: {pid}"
|
|
114
|
+
try:
|
|
115
|
+
msg = Message(
|
|
116
|
+
[
|
|
117
|
+
MessageSegment("text", {"text": text}),
|
|
118
|
+
MessageSegment("image", {"url": url}),
|
|
119
|
+
]
|
|
120
|
+
)
|
|
121
|
+
msg[0].data["summary"] = "我的新自拍喵[图片]"
|
|
122
|
+
await self.send_msg(msg)
|
|
123
|
+
logger.info("发送图片成功")
|
|
124
|
+
except Exception as e:
|
|
125
|
+
logger.error(f"发送图片失败: {e}")
|
|
126
|
+
text += f"\n图片发送失败, 大概率被河蟹了, 请尝试私聊使用该命令\n{e}"
|
|
127
|
+
await self.send_msg(text)
|
|
128
|
+
|
|
129
|
+
self.unlock()
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from nonebot.adapters.onebot.v11 import Bot, Message
|
|
4
|
+
|
|
5
|
+
from ..command import BotCommand
|
|
6
|
+
from ..parser import BotArgParser
|
|
7
|
+
from ..session import BotSession
|
|
8
|
+
from .autoreply_main_cmd import BotCommandAutoReplyMain
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class BotCommandAutoreply(BotCommand):
|
|
12
|
+
def __init__(self, bot: Bot, session: BotSession, *, _pid: int, _internal=None):
|
|
13
|
+
super().__init__(bot, session, _pid=_pid, _internal=_internal)
|
|
14
|
+
|
|
15
|
+
def _init_parser(self):
|
|
16
|
+
parser = BotArgParser()
|
|
17
|
+
parser.set_rule(max=0, need_subcmd=True)
|
|
18
|
+
start = parser.add_subparser("start")
|
|
19
|
+
stop = parser.add_subparser("stop")
|
|
20
|
+
start.set_rule(max=0)
|
|
21
|
+
stop.set_rule(max=0)
|
|
22
|
+
return parser
|
|
23
|
+
|
|
24
|
+
async def run(self, args: Message):
|
|
25
|
+
if not self.session:
|
|
26
|
+
return
|
|
27
|
+
new_argv = args.extract_plain_text().strip().split()
|
|
28
|
+
|
|
29
|
+
if not await self._legal_case(new_argv):
|
|
30
|
+
if self._argv is None:
|
|
31
|
+
self.unlock()
|
|
32
|
+
return
|
|
33
|
+
|
|
34
|
+
if not await self._guard_state():
|
|
35
|
+
return
|
|
36
|
+
|
|
37
|
+
self._argv = new_argv
|
|
38
|
+
self._parser.parse_argv(self._argv)
|
|
39
|
+
subcmd = self._parser.subcmd
|
|
40
|
+
|
|
41
|
+
if not self._check_perm("autoreplymanager"):
|
|
42
|
+
await self.send_msg("权限不足")
|
|
43
|
+
self.unlock()
|
|
44
|
+
return
|
|
45
|
+
|
|
46
|
+
if subcmd == "start":
|
|
47
|
+
autoreply_session = BotSession.make("public", "autoreply")
|
|
48
|
+
main_command = BotCommandAutoReplyMain.make(
|
|
49
|
+
self.bot, autoreply_session, _pid=autoreply_session.curpid
|
|
50
|
+
)
|
|
51
|
+
if main_command is None:
|
|
52
|
+
await self.send_msg("警告: 自动回复正在运行中")
|
|
53
|
+
await self.send_msg("自动回复已开启")
|
|
54
|
+
self.unlock()
|
|
55
|
+
|
|
56
|
+
elif subcmd == "stop":
|
|
57
|
+
|
|
58
|
+
async def _exe():
|
|
59
|
+
autoreply_session = BotSession.get_obj("public", "autoreply")
|
|
60
|
+
if autoreply_session is None:
|
|
61
|
+
await self.send_msg("警告: 自动回复未开启")
|
|
62
|
+
return
|
|
63
|
+
main_command = autoreply_session.commands.get(autoreply_session.curpid)
|
|
64
|
+
if main_command is None:
|
|
65
|
+
await self.send_msg("警告: 自动回复未开启")
|
|
66
|
+
return
|
|
67
|
+
main_command.unlock()
|
|
68
|
+
|
|
69
|
+
await _exe()
|
|
70
|
+
await self.send_msg("自动回复已关闭")
|
|
71
|
+
self.unlock()
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from nonebot.adapters.onebot.v11 import Bot, Message, MessageEvent, MessageSegment
|
|
6
|
+
|
|
7
|
+
from ..command import BotCommand
|
|
8
|
+
from ..config import config
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from ..session import BotSession
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# Simple auto reply, just for fun :). May be further reconstructed in future.
|
|
15
|
+
class BotCommandAutoReplyMain(BotCommand):
|
|
16
|
+
_name = "autoreply_main"
|
|
17
|
+
|
|
18
|
+
def __init__(self, bot: Bot, session: BotSession, *, _pid: int, _internal=None):
|
|
19
|
+
super().__init__(bot, session, _pid=_pid, _internal=_internal)
|
|
20
|
+
|
|
21
|
+
async def roger(self, event: MessageEvent):
|
|
22
|
+
group_id = str(getattr(event, "group_id", "private"))
|
|
23
|
+
if event.message_type == "private":
|
|
24
|
+
group_id = "private"
|
|
25
|
+
user_id = str(event.user_id)
|
|
26
|
+
|
|
27
|
+
for seg in event.get_message():
|
|
28
|
+
if seg.type != "text":
|
|
29
|
+
continue
|
|
30
|
+
text = seg.data.get("text", "")
|
|
31
|
+
cleaned_text = (
|
|
32
|
+
text.replace("!", "")
|
|
33
|
+
.replace(" ", "")
|
|
34
|
+
.replace("!", "")
|
|
35
|
+
.replace("w", "")
|
|
36
|
+
.replace("我", "")
|
|
37
|
+
)
|
|
38
|
+
if cleaned_text in [
|
|
39
|
+
"csn",
|
|
40
|
+
"草死你",
|
|
41
|
+
"操死你",
|
|
42
|
+
"🌿死你",
|
|
43
|
+
"艹死你",
|
|
44
|
+
"zjsncsn",
|
|
45
|
+
]:
|
|
46
|
+
wcsn_path = config.client_base / "data" / "wcsn.jpg"
|
|
47
|
+
msg = Message(MessageSegment.image(f"file://{wcsn_path}"))
|
|
48
|
+
msg[0].data["sub_type"] = 1
|
|
49
|
+
msg[0].data["summary"] = "喵呜~"
|
|
50
|
+
await self.send_msg(msg, group_id=group_id, user_id=user_id)
|
|
51
|
+
return
|
|
52
|
+
cleaned = text.replace("?", "").replace(" ", "").replace("?", "")
|
|
53
|
+
if cleaned in ["这是你吗", "zsnm", "是你吗"]:
|
|
54
|
+
zsnm_path = config.client_base / "data" / "zsnm.jpg"
|
|
55
|
+
msg = Message(
|
|
56
|
+
[
|
|
57
|
+
MessageSegment.image(f"file://{zsnm_path}"),
|
|
58
|
+
MessageSegment.text("是我。"),
|
|
59
|
+
]
|
|
60
|
+
)
|
|
61
|
+
msg[0].data["sub_type"] = 1
|
|
62
|
+
msg[0].data["summary"] = "喵呜~"
|
|
63
|
+
await self.send_msg(msg, group_id=group_id, user_id=user_id)
|
|
64
|
+
return
|
|
65
|
+
|
|
66
|
+
async def run(self, args: Message):
|
|
67
|
+
return
|