2024-04-01 12:29:04 +08:00
|
|
|
|
import base64
|
2024-04-10 23:47:10 +08:00
|
|
|
|
import time
|
2024-03-29 14:58:24 +08:00
|
|
|
|
from typing import Any
|
|
|
|
|
|
2024-04-03 14:59:00 +08:00
|
|
|
|
import nonebot
|
2024-03-31 06:26:01 +08:00
|
|
|
|
import pip
|
2024-04-10 23:47:10 +08:00
|
|
|
|
from nonebot import Bot, get_driver, require
|
2024-04-24 15:07:57 +08:00
|
|
|
|
from nonebot.adapters.onebot.v11 import Message, escape, unescape
|
2024-04-01 12:29:04 +08:00
|
|
|
|
from nonebot.exception import MockApiException
|
2024-04-07 00:35:53 +08:00
|
|
|
|
from nonebot.internal.matcher import Matcher
|
2024-03-30 06:04:17 +08:00
|
|
|
|
from nonebot.permission import SUPERUSER
|
2024-03-24 19:15:49 +08:00
|
|
|
|
|
2024-05-12 02:47:14 +08:00
|
|
|
|
from liteyuki.utils.base.config import get_config, load_from_yaml
|
|
|
|
|
from liteyuki.utils.base.data_manager import StoredConfig, TempConfig, common_db
|
|
|
|
|
from liteyuki.utils.base.language import get_user_lang
|
|
|
|
|
from liteyuki.utils.base.ly_typing import T_Bot, T_MessageEvent
|
|
|
|
|
from liteyuki.utils.message.message import MarkdownMessage as md, broadcast_to_superusers
|
|
|
|
|
from liteyuki.utils.base.reloader import Reloader
|
2024-04-12 01:07:53 +08:00
|
|
|
|
from .api import update_liteyuki
|
2024-03-24 19:15:49 +08:00
|
|
|
|
|
2024-04-23 23:10:58 +08:00
|
|
|
|
require("nonebot_plugin_alconna")
|
|
|
|
|
require("nonebot_plugin_apscheduler")
|
2024-04-24 15:07:57 +08:00
|
|
|
|
from nonebot_plugin_alconna import UniMessage, on_alconna, Alconna, Args, Subcommand, Arparma, MultiVar
|
2024-04-12 01:07:53 +08:00
|
|
|
|
from nonebot_plugin_apscheduler import scheduler
|
2024-03-24 22:04:51 +08:00
|
|
|
|
|
2024-03-30 06:04:17 +08:00
|
|
|
|
driver = get_driver()
|
|
|
|
|
|
2024-05-12 00:18:53 +08:00
|
|
|
|
markdown_image = common_db.where_one(StoredConfig(), default=StoredConfig()).config.get("markdown_image", False)
|
2024-04-01 12:29:04 +08:00
|
|
|
|
|
2024-04-08 17:01:55 +08:00
|
|
|
|
|
2024-04-07 00:35:53 +08:00
|
|
|
|
@on_alconna(
|
2024-04-06 04:23:01 +08:00
|
|
|
|
command=Alconna(
|
|
|
|
|
"liteecho",
|
2024-05-09 16:37:50 +08:00
|
|
|
|
Args["text", str, ""],
|
2024-03-24 19:15:49 +08:00
|
|
|
|
),
|
|
|
|
|
permission=SUPERUSER
|
2024-04-07 00:35:53 +08:00
|
|
|
|
).handle()
|
2024-04-24 15:12:26 +08:00
|
|
|
|
async def _(bot: T_Bot, matcher: Matcher, result: Arparma):
|
|
|
|
|
if result.main_args.get("text"):
|
|
|
|
|
await matcher.finish(Message(unescape(result.main_args.get("text"))))
|
|
|
|
|
else:
|
|
|
|
|
await matcher.finish(f"Hello, Liteyuki!\nBot {bot.self_id}")
|
2024-03-24 19:15:49 +08:00
|
|
|
|
|
2024-04-07 00:35:53 +08:00
|
|
|
|
|
|
|
|
|
@on_alconna(
|
2024-03-31 18:54:04 +08:00
|
|
|
|
aliases={"更新轻雪"},
|
|
|
|
|
command=Alconna(
|
|
|
|
|
"update-liteyuki"
|
2024-03-27 00:05:51 +08:00
|
|
|
|
),
|
|
|
|
|
permission=SUPERUSER
|
2024-04-07 00:35:53 +08:00
|
|
|
|
).handle()
|
2024-03-27 00:05:51 +08:00
|
|
|
|
async def _(bot: T_Bot, event: T_MessageEvent):
|
|
|
|
|
# 使用git pull更新
|
2024-03-27 07:57:04 +08:00
|
|
|
|
ulang = get_user_lang(str(event.user_id))
|
2024-04-12 01:07:53 +08:00
|
|
|
|
success, logs = update_liteyuki()
|
2024-03-27 00:05:51 +08:00
|
|
|
|
reply = "Liteyuki updated!\n"
|
2024-03-27 07:57:04 +08:00
|
|
|
|
reply += f"```\n{logs}\n```\n"
|
2024-04-07 00:35:53 +08:00
|
|
|
|
btn_restart = md.btn_cmd(ulang.get("liteyuki.restart_now"), "reload-liteyuki")
|
2024-03-31 06:26:01 +08:00
|
|
|
|
pip.main(["install", "-r", "requirements.txt"])
|
2024-03-27 07:57:04 +08:00
|
|
|
|
reply += f"{ulang.get('liteyuki.update_restart', RESTART=btn_restart)}"
|
2024-03-31 06:22:53 +08:00
|
|
|
|
await md.send_md(reply, bot, event=event, at_sender=False)
|
2024-03-27 00:05:51 +08:00
|
|
|
|
|
|
|
|
|
|
2024-04-07 00:35:53 +08:00
|
|
|
|
@on_alconna(
|
|
|
|
|
aliases={"重启轻雪"},
|
|
|
|
|
command=Alconna(
|
|
|
|
|
"reload-liteyuki"
|
|
|
|
|
),
|
|
|
|
|
permission=SUPERUSER
|
|
|
|
|
).handle()
|
2024-04-10 23:47:10 +08:00
|
|
|
|
async def _(matcher: Matcher, bot: T_Bot, event: T_MessageEvent):
|
2024-04-07 00:35:53 +08:00
|
|
|
|
await matcher.send("Liteyuki reloading")
|
2024-05-12 00:18:53 +08:00
|
|
|
|
temp_data = common_db.where_one(TempConfig(), default=TempConfig())
|
2024-04-15 18:04:19 +08:00
|
|
|
|
|
|
|
|
|
temp_data.data.update(
|
|
|
|
|
{
|
|
|
|
|
"reload" : True,
|
|
|
|
|
"reload_time" : time.time(),
|
|
|
|
|
"reload_bot_id" : bot.self_id,
|
|
|
|
|
"reload_session_type": event.message_type,
|
|
|
|
|
"reload_session_id" : event.group_id if event.message_type == "group" else event.user_id,
|
|
|
|
|
"delta_time" : 0
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
2024-04-27 02:20:44 +08:00
|
|
|
|
common_db.save(temp_data)
|
2024-04-10 23:47:10 +08:00
|
|
|
|
Reloader.reload(0)
|
2024-03-29 14:58:24 +08:00
|
|
|
|
|
|
|
|
|
|
2024-04-07 00:35:53 +08:00
|
|
|
|
@on_alconna(
|
|
|
|
|
aliases={"配置"},
|
|
|
|
|
command=Alconna(
|
|
|
|
|
"config",
|
|
|
|
|
Subcommand(
|
|
|
|
|
"set",
|
|
|
|
|
Args["key", str]["value", Any],
|
|
|
|
|
alias=["设置"],
|
|
|
|
|
|
|
|
|
|
),
|
|
|
|
|
Subcommand(
|
|
|
|
|
"get",
|
|
|
|
|
Args["key", str, None],
|
2024-04-15 18:04:19 +08:00
|
|
|
|
alias=["查询", "获取"]
|
|
|
|
|
),
|
|
|
|
|
Subcommand(
|
|
|
|
|
"remove",
|
|
|
|
|
Args["key", str],
|
|
|
|
|
alias=["删除"]
|
2024-04-07 00:35:53 +08:00
|
|
|
|
)
|
|
|
|
|
),
|
|
|
|
|
permission=SUPERUSER
|
|
|
|
|
).handle()
|
|
|
|
|
async def _(result: Arparma, event: T_MessageEvent, bot: T_Bot, matcher: Matcher):
|
2024-03-29 14:58:24 +08:00
|
|
|
|
ulang = get_user_lang(str(event.user_id))
|
2024-05-12 00:18:53 +08:00
|
|
|
|
stored_config: StoredConfig = common_db.where_one(StoredConfig(), default=StoredConfig())
|
2024-03-29 14:58:24 +08:00
|
|
|
|
if result.subcommands.get("set"):
|
|
|
|
|
key, value = result.subcommands.get("set").args.get("key"), result.subcommands.get("set").args.get("value")
|
|
|
|
|
try:
|
|
|
|
|
value = eval(value)
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
stored_config.config[key] = value
|
2024-04-27 02:20:44 +08:00
|
|
|
|
common_db.save(stored_config)
|
2024-04-07 00:35:53 +08:00
|
|
|
|
await matcher.finish(f"{ulang.get('liteyuki.config_set_success', KEY=key, VAL=value)}")
|
2024-03-29 14:58:24 +08:00
|
|
|
|
elif result.subcommands.get("get"):
|
|
|
|
|
key = result.subcommands.get("get").args.get("key")
|
|
|
|
|
file_config = load_from_yaml("config.yml")
|
|
|
|
|
reply = f"{ulang.get('liteyuki.current_config')}"
|
|
|
|
|
if key:
|
|
|
|
|
reply += f"```dotenv\n{key}={file_config.get(key, stored_config.config.get(key))}\n```"
|
|
|
|
|
else:
|
|
|
|
|
reply = f"{ulang.get('liteyuki.current_config')}"
|
|
|
|
|
reply += f"\n{ulang.get('liteyuki.static_config')}\n```dotenv"
|
|
|
|
|
for k, v in file_config.items():
|
|
|
|
|
reply += f"\n{k}={v}"
|
|
|
|
|
reply += "\n```"
|
|
|
|
|
if len(stored_config.config) > 0:
|
|
|
|
|
reply += f"\n{ulang.get('liteyuki.stored_config')}\n```dotenv"
|
|
|
|
|
for k, v in stored_config.config.items():
|
2024-04-15 18:04:19 +08:00
|
|
|
|
reply += f"\n{k}={v} {type(v)}"
|
2024-03-29 14:58:24 +08:00
|
|
|
|
reply += "\n```"
|
2024-03-31 06:22:53 +08:00
|
|
|
|
await md.send_md(reply, bot, event=event)
|
2024-04-15 18:04:19 +08:00
|
|
|
|
elif result.subcommands.get("remove"):
|
|
|
|
|
key = result.subcommands.get("remove").args.get("key")
|
|
|
|
|
if key in stored_config.config:
|
|
|
|
|
stored_config.config.pop(key)
|
2024-04-27 02:20:44 +08:00
|
|
|
|
common_db.save(stored_config)
|
2024-04-15 18:04:19 +08:00
|
|
|
|
await matcher.finish(f"{ulang.get('liteyuki.config_remove_success', KEY=key)}")
|
|
|
|
|
else:
|
|
|
|
|
await matcher.finish(f"{ulang.get('liteyuki.invalid_command', TEXT=key)}")
|
2024-03-30 06:04:17 +08:00
|
|
|
|
|
|
|
|
|
|
2024-04-07 00:35:53 +08:00
|
|
|
|
@on_alconna(
|
|
|
|
|
aliases={"切换图片模式"},
|
|
|
|
|
command=Alconna(
|
|
|
|
|
"switch-image-mode"
|
|
|
|
|
),
|
|
|
|
|
permission=SUPERUSER
|
|
|
|
|
).handle()
|
|
|
|
|
async def _(event: T_MessageEvent, matcher: Matcher):
|
2024-04-01 12:29:04 +08:00
|
|
|
|
global markdown_image
|
2024-04-01 11:46:47 +08:00
|
|
|
|
# 切换图片模式,False以图片形式发送,True以markdown形式发送
|
2024-04-01 11:37:29 +08:00
|
|
|
|
ulang = get_user_lang(str(event.user_id))
|
2024-05-12 00:18:53 +08:00
|
|
|
|
stored_config: StoredConfig = common_db.where_one(StoredConfig(), default=StoredConfig())
|
2024-04-01 11:46:47 +08:00
|
|
|
|
stored_config.config["markdown_image"] = not stored_config.config.get("markdown_image", False)
|
2024-04-01 12:29:04 +08:00
|
|
|
|
markdown_image = stored_config.config["markdown_image"]
|
2024-04-27 02:20:44 +08:00
|
|
|
|
common_db.save(stored_config)
|
2024-04-07 00:35:53 +08:00
|
|
|
|
await matcher.finish(ulang.get("liteyuki.image_mode_on" if stored_config.config["markdown_image"] else "liteyuki.image_mode_off"))
|
2024-04-01 12:29:04 +08:00
|
|
|
|
|
|
|
|
|
|
2024-04-07 00:35:53 +08:00
|
|
|
|
@on_alconna(
|
|
|
|
|
command=Alconna(
|
|
|
|
|
"liteyuki-docs",
|
|
|
|
|
),
|
|
|
|
|
aliases={"轻雪文档"},
|
|
|
|
|
).handle()
|
|
|
|
|
async def _(matcher: Matcher):
|
2024-04-12 01:07:53 +08:00
|
|
|
|
await matcher.finish("https://bot.liteyuki.icu/usage")
|
2024-04-01 12:29:04 +08:00
|
|
|
|
|
2024-04-08 17:01:55 +08:00
|
|
|
|
|
2024-04-21 14:15:12 +08:00
|
|
|
|
@on_alconna(
|
|
|
|
|
command=Alconna(
|
|
|
|
|
"/api",
|
|
|
|
|
Args["api", str]["args", MultiVar(str), ()],
|
|
|
|
|
),
|
|
|
|
|
permission=SUPERUSER
|
|
|
|
|
).handle()
|
|
|
|
|
async def _(result: Arparma, bot: T_Bot, event: T_MessageEvent, matcher: Matcher):
|
|
|
|
|
"""
|
|
|
|
|
调用API
|
|
|
|
|
Args:
|
|
|
|
|
result:
|
|
|
|
|
bot:
|
|
|
|
|
event:
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
api_name = result.main_args.get("api")
|
|
|
|
|
args: tuple[str] = result.main_args.get("args", ()) # 类似于url参数,但每个参数间用空格分隔,空格是%20
|
|
|
|
|
args_dict = {}
|
2024-04-24 15:07:57 +08:00
|
|
|
|
|
2024-04-21 14:15:12 +08:00
|
|
|
|
for arg in args:
|
|
|
|
|
key, value = arg.split("=", 1)
|
2024-04-24 15:07:57 +08:00
|
|
|
|
args_dict[key] = unescape(value.replace("%20", " "))
|
2024-04-21 14:15:12 +08:00
|
|
|
|
|
|
|
|
|
if api_name in need_user_id and "user_id" not in args_dict:
|
|
|
|
|
args_dict["user_id"] = str(event.user_id)
|
|
|
|
|
if api_name in need_group_id and "group_id" not in args_dict and event.message_type == "group":
|
|
|
|
|
args_dict["group_id"] = str(event.group_id)
|
|
|
|
|
|
2024-04-24 15:07:57 +08:00
|
|
|
|
if "message" in args_dict:
|
|
|
|
|
args_dict["message"] = Message(args_dict["message"])
|
|
|
|
|
|
2024-04-21 14:15:12 +08:00
|
|
|
|
try:
|
|
|
|
|
result = await bot.call_api(api_name, **args_dict)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
result = str(e)
|
|
|
|
|
|
|
|
|
|
args_show = "\n".join("- %s: %s" % (k, v) for k, v in args_dict.items())
|
2024-04-24 15:07:57 +08:00
|
|
|
|
print(f"API: {api_name}\n\nArgs: \n{args_show}\n\nResult: {result}")
|
2024-04-21 14:15:12 +08:00
|
|
|
|
await matcher.finish(f"API: {api_name}\n\nArgs: \n{args_show}\n\nResult: {result}")
|
|
|
|
|
|
|
|
|
|
|
2024-04-07 00:35:53 +08:00
|
|
|
|
# system hook
|
2024-04-08 17:01:55 +08:00
|
|
|
|
@Bot.on_calling_api # 图片模式检测
|
2024-04-01 12:29:04 +08:00
|
|
|
|
async def test_for_md_image(bot: T_Bot, api: str, data: dict):
|
2024-04-12 00:32:08 +08:00
|
|
|
|
# 截获大图发送,转换为markdown发送
|
2024-04-01 23:56:03 +08:00
|
|
|
|
if api in ["send_msg", "send_private_msg", "send_group_msg"] and markdown_image and data.get("user_id") != bot.self_id:
|
2024-04-01 12:29:04 +08:00
|
|
|
|
if api == "send_msg" and data.get("message_type") == "private" or api == "send_private_msg":
|
|
|
|
|
session_type = "private"
|
|
|
|
|
session_id = data.get("user_id")
|
|
|
|
|
elif api == "send_msg" and data.get("message_type") == "group" or api == "send_group_msg":
|
|
|
|
|
session_type = "group"
|
|
|
|
|
session_id = data.get("group_id")
|
|
|
|
|
else:
|
|
|
|
|
return
|
|
|
|
|
if len(data.get("message", [])) == 1 and data["message"][0].get("type") == "image":
|
|
|
|
|
file: str = data["message"][0].data.get("file")
|
|
|
|
|
# file:// http:// base64://
|
|
|
|
|
if file.startswith("http"):
|
|
|
|
|
result = await md.send_md(await md.image_async(file), bot, message_type=session_type, session_id=session_id)
|
|
|
|
|
elif file.startswith("file"):
|
|
|
|
|
file = file.replace("file://", "")
|
|
|
|
|
result = await md.send_image(open(file, "rb").read(), bot, message_type=session_type, session_id=session_id)
|
|
|
|
|
elif file.startswith("base64"):
|
|
|
|
|
file_bytes = base64.b64decode(file.replace("base64://", ""))
|
|
|
|
|
result = await md.send_image(file_bytes, bot, message_type=session_type, session_id=session_id)
|
|
|
|
|
else:
|
|
|
|
|
return
|
|
|
|
|
raise MockApiException(result=result)
|
2024-04-01 11:46:47 +08:00
|
|
|
|
|
2024-04-01 11:37:29 +08:00
|
|
|
|
|
2024-03-30 06:04:17 +08:00
|
|
|
|
@driver.on_startup
|
|
|
|
|
async def on_startup():
|
2024-05-12 00:18:53 +08:00
|
|
|
|
temp_data = common_db.where_one(TempConfig(), default=TempConfig())
|
2024-04-12 00:32:08 +08:00
|
|
|
|
# 储存重启信息
|
2024-04-10 23:47:10 +08:00
|
|
|
|
if temp_data.data.get("reload", False):
|
|
|
|
|
delta_time = time.time() - temp_data.data.get("reload_time", 0)
|
|
|
|
|
temp_data.data["delta_time"] = delta_time
|
2024-04-27 02:20:44 +08:00
|
|
|
|
common_db.save(temp_data) # 更新数据
|
2024-03-30 06:04:17 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@driver.on_shutdown
|
|
|
|
|
async def on_shutdown():
|
2024-04-02 20:32:28 +08:00
|
|
|
|
pass
|
2024-04-10 23:47:10 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@driver.on_bot_connect
|
|
|
|
|
async def _(bot: T_Bot):
|
2024-05-12 00:18:53 +08:00
|
|
|
|
temp_data = common_db.where_one(TempConfig(), default=TempConfig())
|
2024-04-12 00:32:08 +08:00
|
|
|
|
# 用于重启计时
|
2024-04-10 23:47:10 +08:00
|
|
|
|
if temp_data.data.get("reload", False):
|
|
|
|
|
temp_data.data["reload"] = False
|
|
|
|
|
reload_bot_id = temp_data.data.get("reload_bot_id", 0)
|
|
|
|
|
if reload_bot_id != bot.self_id:
|
|
|
|
|
return
|
|
|
|
|
reload_session_type = temp_data.data.get("reload_session_type", "private")
|
|
|
|
|
reload_session_id = temp_data.data.get("reload_session_id", 0)
|
|
|
|
|
delta_time = temp_data.data.get("delta_time", 0)
|
2024-04-27 02:20:44 +08:00
|
|
|
|
common_db.save(temp_data) # 更新数据
|
2024-04-10 23:47:10 +08:00
|
|
|
|
await bot.call_api(
|
|
|
|
|
"send_msg",
|
|
|
|
|
message_type=reload_session_type,
|
|
|
|
|
user_id=reload_session_id,
|
|
|
|
|
group_id=reload_session_id,
|
|
|
|
|
message="Liteyuki reloaded in %.2f s" % delta_time
|
|
|
|
|
)
|
2024-04-12 01:07:53 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 每天4点更新
|
|
|
|
|
@scheduler.scheduled_job("cron", hour=4)
|
|
|
|
|
async def every_day_update():
|
2024-04-12 07:17:42 +08:00
|
|
|
|
if get_config("auto_update", default=True):
|
2024-04-12 01:07:53 +08:00
|
|
|
|
result, logs = update_liteyuki()
|
2024-04-27 21:38:37 +08:00
|
|
|
|
pip.main(["install", "-r", "requirements.txt"])
|
2024-04-12 01:07:53 +08:00
|
|
|
|
if result:
|
2024-04-12 01:15:05 +08:00
|
|
|
|
await broadcast_to_superusers(f"Liteyuki updated: ```\n{logs}\n```")
|
2024-04-12 01:07:53 +08:00
|
|
|
|
nonebot.logger.info(f"Liteyuki updated: {logs}")
|
2024-04-15 18:04:19 +08:00
|
|
|
|
Reloader.reload(5)
|
2024-04-12 01:07:53 +08:00
|
|
|
|
else:
|
2024-04-12 01:15:05 +08:00
|
|
|
|
nonebot.logger.info(logs)
|
2024-04-21 14:15:12 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 安全的需要用户id的api
|
|
|
|
|
need_user_id = (
|
|
|
|
|
"send_private_msg",
|
|
|
|
|
"send_msg",
|
|
|
|
|
"set_group_card",
|
|
|
|
|
"set_group_special_title",
|
|
|
|
|
"get_stranger_info",
|
|
|
|
|
"get_group_member_info"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
need_group_id = (
|
|
|
|
|
"send_group_msg",
|
|
|
|
|
"send_msg",
|
|
|
|
|
"set_group_card",
|
|
|
|
|
"set_group_name",
|
|
|
|
|
"set_group_special_title",
|
|
|
|
|
"get_group_member_info",
|
|
|
|
|
"get_group_member_list",
|
|
|
|
|
"get_group_honor_info"
|
|
|
|
|
)
|