Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d594d17bf6 | ||
|
|
4e33bf3a50 | ||
|
|
daa40ae8b8 | ||
|
|
21bdb011e0 | ||
|
|
47f3518b04 | ||
|
|
997ce52d69 | ||
|
|
4bc433f049 | ||
|
|
4d6013ca02 | ||
|
|
f09f2c3162 | ||
|
|
67fdbb824b | ||
|
|
b4ccbb0f80 | ||
|
|
6326d888c8 | ||
|
|
e32f3dd22a | ||
|
|
c7e073baea | ||
|
|
1be99ac64d |
@@ -8,19 +8,12 @@ NICKNAME=["真寻", "小真寻", "绪山真寻", "小寻子"]
|
|||||||
|
|
||||||
SESSION_EXPIRE_TIMEOUT=30
|
SESSION_EXPIRE_TIMEOUT=30
|
||||||
|
|
||||||
ALCONNA_USE_COMMAND_START=True
|
|
||||||
|
|
||||||
# 全局图片统一使用bytes发送,当真寻与协议端不在同一服务器上时为True
|
# 全局图片统一使用bytes发送,当真寻与协议端不在同一服务器上时为True
|
||||||
IMAGE_TO_BYTES = True
|
IMAGE_TO_BYTES = False
|
||||||
|
|
||||||
# 回复消息时自称
|
# 回复消息时自称
|
||||||
SELF_NICKNAME="小真寻"
|
SELF_NICKNAME="小真寻"
|
||||||
|
|
||||||
# 官bot appid:bot账号
|
|
||||||
QBOT_ID_DATA = '{
|
|
||||||
|
|
||||||
}'
|
|
||||||
|
|
||||||
# 数据库配置
|
# 数据库配置
|
||||||
# 示例: "postgres://user:password@127.0.0.1:5432/database"
|
# 示例: "postgres://user:password@127.0.0.1:5432/database"
|
||||||
# 示例: "mysql://user:password@127.0.0.1:3306/database"
|
# 示例: "mysql://user:password@127.0.0.1:3306/database"
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
name: Update Version
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
paths:
|
||||||
|
- zhenxun/**
|
||||||
|
- resources/**
|
||||||
|
- bot.py
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- synchronize
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- dev
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update-version:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
|
||||||
|
- name: Read current version
|
||||||
|
id: read_version
|
||||||
|
run: |
|
||||||
|
version_line=$(grep '__version__' __version__)
|
||||||
|
version=$(echo $version_line | sed -E 's/__version__:\s*v([0-9]+\.[0-9]+\.[0-9]+)(-.+)?/\1/')
|
||||||
|
echo "Current version: $version"
|
||||||
|
echo "current_version=$version" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Check for version file changes
|
||||||
|
id: check_diff
|
||||||
|
run: |
|
||||||
|
if git diff --name-only HEAD~1 HEAD | grep -q '__version__'; then
|
||||||
|
echo "Version file has changes"
|
||||||
|
echo "version_changed=true" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "Version file has no changes"
|
||||||
|
echo "version_changed=false" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Get commit hash
|
||||||
|
id: get_commit_hash
|
||||||
|
run: echo "commit_hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Update version file
|
||||||
|
if: steps.check_diff.outputs.version_changed == 'false'
|
||||||
|
run: |
|
||||||
|
current_version="${{ steps.read_version.outputs.current_version }}"
|
||||||
|
commit_hash="${{ steps.get_commit_hash.outputs.commit_hash }}"
|
||||||
|
new_version="v${current_version}-${commit_hash}"
|
||||||
|
echo "Updating version to: $new_version"
|
||||||
|
echo "__version__: $new_version" > __version__
|
||||||
|
git config --global user.name "${{ github.event.pull_request.user.login }}"
|
||||||
|
git config --global user.email "${{ github.event.pull_request.user.login }}@users.noreply.github.com"
|
||||||
|
git add __version__
|
||||||
|
git remote set-url origin https://github.com/${{ github.event.pull_request.head.repo.full_name }}.git
|
||||||
|
git commit -m "chore(version): Update version to $new_version"
|
||||||
|
git push origin HEAD:${{ github.event.pull_request.head.ref }}
|
||||||
|
|
||||||
|
- name: Check updated version
|
||||||
|
if: steps.check_diff.outputs.version_changed == 'false'
|
||||||
|
run: cat __version__
|
||||||
@@ -13,19 +13,18 @@
|
|||||||
"getbbox",
|
"getbbox",
|
||||||
"hibiapi",
|
"hibiapi",
|
||||||
"httpx",
|
"httpx",
|
||||||
"jsdelivr",
|
|
||||||
"kaiheila",
|
"kaiheila",
|
||||||
"lolicon",
|
"lolicon",
|
||||||
"nonebot",
|
"nonebot",
|
||||||
"onebot",
|
"onebot",
|
||||||
"pixiv",
|
"pixiv",
|
||||||
"qbot",
|
|
||||||
"Setu",
|
"Setu",
|
||||||
"tobytes",
|
"tobytes",
|
||||||
"ujson",
|
"ujson",
|
||||||
"unban",
|
"unban",
|
||||||
"userinfo",
|
"userinfo",
|
||||||
"zhenxun"
|
"zhenxun",
|
||||||
|
"jsdelivr"
|
||||||
],
|
],
|
||||||
"python.analysis.autoImportCompletions": true,
|
"python.analysis.autoImportCompletions": true,
|
||||||
"python.testing.pytestArgs": ["tests"],
|
"python.testing.pytestArgs": ["tests"],
|
||||||
|
|||||||
@@ -68,7 +68,7 @@
|
|||||||
|
|
||||||
### 1. 体验一下?
|
### 1. 体验一下?
|
||||||
|
|
||||||
这是一个免费的,版本为 dev 的 zhenxun,你可以通过 [napcat](https://github.com/NapNeko/NapCatQQ) 或 [拉格朗日](https://github.com/LagrangeDev/Lagrange.Core) 以及 [matcha](https://github.com/A-kirami/matcha) 等直接连接用于体验与测试
|
这是一个免费的,版本为 dev 的 zhenxun,你可以通过 napcat 或拉格朗日等直接连接用于体验与测试
|
||||||
(球球了测试君!)
|
(球球了测试君!)
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -95,14 +95,13 @@ AccessToken: PUBLIC_ZHENXUN_TEST
|
|||||||
<details>
|
<details>
|
||||||
<summary> <strong> WebUI </strong>后台示例图 </summary>
|
<summary> <strong> WebUI </strong>后台示例图 </summary>
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||

|

|
||||||

|

|
||||||

|

|
||||||

|

|
||||||

|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
@@ -320,7 +319,7 @@ python bot.py
|
|||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>爱发电 以及 感谢投喂 </summary>
|
<summary>爱发电 以及 感谢投喂 </summary>
|
||||||
<img width="365px" height="450px" src="https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs_image/afd.jpg">
|
<img width="365px" height="450px" src="https://user-images.githubusercontent.com/45528451/175059389-cfeb8174-fa07-4939-80ab-a039087a50f6.png">
|
||||||
|
|
||||||
### 感谢名单
|
### 感谢名单
|
||||||
|
|
||||||
@@ -370,7 +369,6 @@ python bot.py
|
|||||||
[哇](https://afdian.net/u/9b266244f23911eca19052540025c377)
|
[哇](https://afdian.net/u/9b266244f23911eca19052540025c377)
|
||||||
[yajiwa](https://github.com/yajiwa)
|
[yajiwa](https://github.com/yajiwa)
|
||||||
[爆金币](https://afdian.net/u/0d78879ef23711ecb22452540025c377)
|
[爆金币](https://afdian.net/u/0d78879ef23711ecb22452540025c377)
|
||||||
...
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
__version__: v0.2.4-fix2
|
__version__: v0.2.4
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 315 KiB |
|
Before Width: | Height: | Size: 352 KiB |
|
Before Width: | Height: | Size: 279 KiB |
|
Before Width: | Height: | Size: 182 KiB |
|
Before Width: | Height: | Size: 228 KiB |
|
Before Width: | Height: | Size: 200 KiB |
|
Before Width: | Height: | Size: 201 KiB |
|
Before Width: | Height: | Size: 193 KiB |
|
After Width: | Height: | Size: 230 KiB |
|
After Width: | Height: | Size: 214 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 188 KiB |
|
After Width: | Height: | Size: 189 KiB |
|
After Width: | Height: | Size: 171 KiB |
|
After Width: | Height: | Size: 60 KiB |
@@ -19,8 +19,6 @@ require("nonebot_plugin_htmlrender")
|
|||||||
from zhenxun.services.log import logger
|
from zhenxun.services.log import logger
|
||||||
from zhenxun.models.sign_user import SignUser
|
from zhenxun.models.sign_user import SignUser
|
||||||
from zhenxun.models.goods_info import GoodsInfo
|
from zhenxun.models.goods_info import GoodsInfo
|
||||||
from zhenxun.utils.platform import PlatformUtils
|
|
||||||
from zhenxun.models.bot_console import BotConsole
|
|
||||||
from zhenxun.models.user_console import UserConsole
|
from zhenxun.models.user_console import UserConsole
|
||||||
from zhenxun.utils.decorator.shop import shop_register
|
from zhenxun.utils.decorator.shop import shop_register
|
||||||
from zhenxun.models.bot_connect_log import BotConnectLog
|
from zhenxun.models.bot_connect_log import BotConnectLog
|
||||||
@@ -35,10 +33,6 @@ async def _(bot: Bot):
|
|||||||
await BotConnectLog.create(
|
await BotConnectLog.create(
|
||||||
bot_id=bot.self_id, platform=bot.adapter, connect_time=datetime.now(), type=1
|
bot_id=bot.self_id, platform=bot.adapter, connect_time=datetime.now(), type=1
|
||||||
)
|
)
|
||||||
if not await BotConsole.exists(bot_id=bot.self_id):
|
|
||||||
await BotConsole.create(
|
|
||||||
bot_id=bot.self_id, platform=PlatformUtils.get_platform(bot)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@driver.on_bot_disconnect
|
@driver.on_bot_disconnect
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ from zhenxun.services.log import logger
|
|||||||
from zhenxun.configs.config import Config
|
from zhenxun.configs.config import Config
|
||||||
from zhenxun.utils.message import MessageUtils
|
from zhenxun.utils.message import MessageUtils
|
||||||
from zhenxun.models.level_user import LevelUser
|
from zhenxun.models.level_user import LevelUser
|
||||||
from zhenxun.models.bot_console import BotConsole
|
|
||||||
from zhenxun.models.plugin_info import PluginInfo
|
from zhenxun.models.plugin_info import PluginInfo
|
||||||
from zhenxun.models.plugin_limit import PluginLimit
|
from zhenxun.models.plugin_limit import PluginLimit
|
||||||
from zhenxun.models.user_console import UserConsole
|
from zhenxun.models.user_console import UserConsole
|
||||||
@@ -235,10 +234,7 @@ class AuthChecker:
|
|||||||
return
|
return
|
||||||
if plugin := await PluginInfo.get_or_none(module_path=module_path):
|
if plugin := await PluginInfo.get_or_none(module_path=module_path):
|
||||||
if plugin.plugin_type == PluginType.HIDDEN:
|
if plugin.plugin_type == PluginType.HIDDEN:
|
||||||
logger.debug(
|
logger.debug("插件为HIDDEN,已跳过...")
|
||||||
f"插件: {plugin.name}:{plugin.module} "
|
|
||||||
"为HIDDEN,已跳过权限检查..."
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
cost_gold = await self.auth_cost(user, plugin, session)
|
cost_gold = await self.auth_cost(user, plugin, session)
|
||||||
@@ -248,7 +244,6 @@ class AuthChecker:
|
|||||||
if not plugin.limit_superuser:
|
if not plugin.limit_superuser:
|
||||||
cost_gold = 0
|
cost_gold = 0
|
||||||
raise IsSuperuserException()
|
raise IsSuperuserException()
|
||||||
await self.auth_bot(plugin, bot.self_id)
|
|
||||||
await self.auth_group(plugin, session, message)
|
await self.auth_group(plugin, session, message)
|
||||||
await self.auth_admin(plugin, session)
|
await self.auth_admin(plugin, session)
|
||||||
await self.auth_plugin(plugin, session, event)
|
await self.auth_plugin(plugin, session, event)
|
||||||
@@ -283,16 +278,6 @@ class AuthChecker:
|
|||||||
if is_ignore:
|
if is_ignore:
|
||||||
raise IgnoredException("权限检测 ignore")
|
raise IgnoredException("权限检测 ignore")
|
||||||
|
|
||||||
async def auth_bot(self, plugin: PluginInfo, bot_id: str):
|
|
||||||
"""机器人权限
|
|
||||||
|
|
||||||
参数:
|
|
||||||
plugin: PluginInfo
|
|
||||||
bot_id: bot_id
|
|
||||||
"""
|
|
||||||
if await BotConsole.is_block_plugin(plugin.module, bot_id):
|
|
||||||
raise IgnoredException("机器人权限检测 ignore")
|
|
||||||
|
|
||||||
async def auth_limit(self, plugin: PluginInfo, session: EventSession):
|
async def auth_limit(self, plugin: PluginInfo, session: EventSession):
|
||||||
"""插件限制
|
"""插件限制
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ async def _(
|
|||||||
if plugin := matcher.plugin:
|
if plugin := matcher.plugin:
|
||||||
if metadata := plugin.metadata:
|
if metadata := plugin.metadata:
|
||||||
extra = metadata.extra
|
extra = metadata.extra
|
||||||
if extra.get("plugin_type") in [PluginType.HIDDEN]:
|
if extra.get("plugin_type") in [PluginType.HIDDEN, PluginType.DEPENDANT]:
|
||||||
return
|
return
|
||||||
user_id = session.id1
|
user_id = session.id1
|
||||||
group_id = session.id3 or session.id2
|
group_id = session.id3 or session.id2
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
from typing import Any
|
|
||||||
|
|
||||||
from nonebot.adapters import Bot
|
|
||||||
|
|
||||||
from zhenxun.services.log import logger
|
|
||||||
from zhenxun.utils.manager.message_manager import MessageManager
|
|
||||||
|
|
||||||
|
|
||||||
@Bot.on_called_api
|
|
||||||
async def handle_api_result(
|
|
||||||
bot: Bot, exception: Exception | None, api: str, data: dict[str, Any], result: Any
|
|
||||||
):
|
|
||||||
if not exception and api == "send_msg":
|
|
||||||
try:
|
|
||||||
if (uid := data.get("user_id")) and (msg_id := result.get("message_id")):
|
|
||||||
MessageManager.add(str(uid), str(msg_id))
|
|
||||||
logger.debug(
|
|
||||||
f"收集消息id,user_id: {uid}, msg_id: {msg_id}", "msg_hook"
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(
|
|
||||||
f"收集消息id发生错误...data: {data}, result: {result}", "msg_hook", e=e
|
|
||||||
)
|
|
||||||
@@ -0,0 +1,321 @@
|
|||||||
|
import os
|
||||||
|
import re
|
||||||
|
import random
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
import ujson as json
|
||||||
|
from nonebot.adapters import Bot
|
||||||
|
from nonebot_plugin_alconna import At
|
||||||
|
from nonebot import on_notice, on_request
|
||||||
|
from nonebot.plugin import PluginMetadata
|
||||||
|
from nonebot.adapters.onebot.v11 import (
|
||||||
|
GroupDecreaseNoticeEvent,
|
||||||
|
GroupIncreaseNoticeEvent,
|
||||||
|
)
|
||||||
|
from nonebot.adapters.onebot.v12 import (
|
||||||
|
GroupMemberDecreaseEvent,
|
||||||
|
GroupMemberIncreaseEvent,
|
||||||
|
)
|
||||||
|
|
||||||
|
from zhenxun.services.log import logger
|
||||||
|
from zhenxun.utils.utils import FreqLimiter
|
||||||
|
from zhenxun.utils.message import MessageUtils
|
||||||
|
from zhenxun.models.fg_request import FgRequest
|
||||||
|
from zhenxun.models.level_user import LevelUser
|
||||||
|
from zhenxun.models.plugin_info import PluginInfo
|
||||||
|
from zhenxun.utils.common_utils import CommonUtils
|
||||||
|
from zhenxun.configs.config import Config, BotConfig
|
||||||
|
from zhenxun.models.group_console import GroupConsole
|
||||||
|
from zhenxun.models.group_member_info import GroupInfoUser
|
||||||
|
from zhenxun.utils.enum import PluginType, RequestHandleType
|
||||||
|
from zhenxun.configs.path_config import DATA_PATH, IMAGE_PATH
|
||||||
|
from zhenxun.configs.utils import Task, RegisterConfig, PluginExtraData
|
||||||
|
|
||||||
|
__plugin_meta__ = PluginMetadata(
|
||||||
|
name="QQ群事件处理",
|
||||||
|
description="群事件处理",
|
||||||
|
usage="",
|
||||||
|
extra=PluginExtraData(
|
||||||
|
author="HibiKier",
|
||||||
|
version="0.1",
|
||||||
|
plugin_type=PluginType.HIDDEN,
|
||||||
|
configs=[
|
||||||
|
RegisterConfig(
|
||||||
|
module="invite_manager",
|
||||||
|
key="message",
|
||||||
|
value=f"请不要未经同意就拉{BotConfig.self_nickname}入群!告辞!",
|
||||||
|
help="强制拉群后进群回复的内容",
|
||||||
|
),
|
||||||
|
RegisterConfig(
|
||||||
|
module="invite_manager",
|
||||||
|
key="flag",
|
||||||
|
value=True,
|
||||||
|
help="强制拉群后进群退出并回复内容",
|
||||||
|
default_value=True,
|
||||||
|
type=bool,
|
||||||
|
),
|
||||||
|
RegisterConfig(
|
||||||
|
module="invite_manager",
|
||||||
|
key="welcome_msg_cd",
|
||||||
|
value=5,
|
||||||
|
help="群欢迎消息cd",
|
||||||
|
default_value=5,
|
||||||
|
type=int,
|
||||||
|
),
|
||||||
|
RegisterConfig(
|
||||||
|
module="_task",
|
||||||
|
key="DEFAULT_GROUP_WELCOME",
|
||||||
|
value=True,
|
||||||
|
help="被动 进群欢迎 进群默认开关状态",
|
||||||
|
default_value=True,
|
||||||
|
type=bool,
|
||||||
|
),
|
||||||
|
RegisterConfig(
|
||||||
|
module="_task",
|
||||||
|
key="DEFAULT_REFUND_GROUP_REMIND",
|
||||||
|
value=True,
|
||||||
|
help="被动 退群提醒 进群默认开关状态",
|
||||||
|
default_value=True,
|
||||||
|
type=bool,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
tasks=[
|
||||||
|
Task(module="group_welcome", name="进群欢迎"),
|
||||||
|
Task(module="refund_group_remind", name="退群提醒"),
|
||||||
|
],
|
||||||
|
).dict(),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
base_config = Config.get("invite_manager")
|
||||||
|
|
||||||
|
|
||||||
|
limit_cd = base_config.get("welcome_msg_cd")
|
||||||
|
|
||||||
|
_flmt = FreqLimiter(limit_cd)
|
||||||
|
|
||||||
|
|
||||||
|
group_increase_handle = on_notice(priority=1, block=False)
|
||||||
|
"""群员增加处理"""
|
||||||
|
group_decrease_handle = on_notice(priority=1, block=False)
|
||||||
|
"""群员减少处理"""
|
||||||
|
add_group = on_request(priority=1, block=False)
|
||||||
|
"""加群同意请求"""
|
||||||
|
|
||||||
|
|
||||||
|
@group_increase_handle.handle()
|
||||||
|
async def _(bot: Bot, event: GroupIncreaseNoticeEvent | GroupMemberIncreaseEvent):
|
||||||
|
superusers = BotConfig.get_superuser("qq")
|
||||||
|
user_id = str(event.user_id)
|
||||||
|
group_id = str(event.group_id)
|
||||||
|
if user_id == bot.self_id:
|
||||||
|
"""新成员为bot本身"""
|
||||||
|
group = await GroupConsole.get_or_none(
|
||||||
|
group_id=group_id, channel_id__isnull=True
|
||||||
|
)
|
||||||
|
if not group or group.group_flag == 0:
|
||||||
|
"""群聊不存在或被强制拉群"""
|
||||||
|
if base_config.get("flag"):
|
||||||
|
"""退出群组"""
|
||||||
|
try:
|
||||||
|
if result_msg := base_config.get("message"):
|
||||||
|
await bot.send_group_msg(
|
||||||
|
group_id=event.group_id, message=result_msg
|
||||||
|
)
|
||||||
|
await bot.set_group_leave(group_id=event.group_id)
|
||||||
|
if superusers:
|
||||||
|
await bot.send_private_msg(
|
||||||
|
user_id=int(superusers[0]),
|
||||||
|
message=f"触发强制入群保护,已成功退出群聊 {group_id}...",
|
||||||
|
)
|
||||||
|
logger.info(
|
||||||
|
"强制拉群或未有群信息,退出群聊成功",
|
||||||
|
"入群检测",
|
||||||
|
group_id=event.group_id,
|
||||||
|
)
|
||||||
|
if req := await FgRequest.get_or_none(
|
||||||
|
group_id=group_id, handle_type__isnull=True
|
||||||
|
):
|
||||||
|
req.handle_type = RequestHandleType.IGNORE
|
||||||
|
await req.save(update_fields=["handle_type"])
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(
|
||||||
|
"强制拉群或未有群信息,退出群聊失败",
|
||||||
|
"入群检测",
|
||||||
|
group_id=event.group_id,
|
||||||
|
e=e,
|
||||||
|
)
|
||||||
|
if superusers:
|
||||||
|
await bot.send_private_msg(
|
||||||
|
user_id=int(superusers[0]),
|
||||||
|
message="触发强制入群保护,"
|
||||||
|
f"退出群聊 {event.group_id} 失败...",
|
||||||
|
)
|
||||||
|
await GroupConsole.filter(group_id=group_id).delete()
|
||||||
|
else:
|
||||||
|
"""允许群组并设置群认证,默认群功能开关"""
|
||||||
|
if group:
|
||||||
|
await GroupConsole.filter(
|
||||||
|
group_id=group_id, channel_id__isnull=True
|
||||||
|
).update(group_flag=1)
|
||||||
|
else:
|
||||||
|
block_plugin = ""
|
||||||
|
if plugin_list := await PluginInfo.filter(
|
||||||
|
default_status=False
|
||||||
|
).all():
|
||||||
|
for plugin in plugin_list:
|
||||||
|
block_plugin += f"{plugin.module},"
|
||||||
|
group_info = await bot.get_group_info(group_id=event.group_id)
|
||||||
|
await GroupConsole.create(
|
||||||
|
group_id=group_info["group_id"],
|
||||||
|
group_name=group_info["group_name"],
|
||||||
|
max_member_count=group_info["max_member_count"],
|
||||||
|
member_count=group_info["member_count"],
|
||||||
|
group_flag=1,
|
||||||
|
block_plugin=block_plugin,
|
||||||
|
platform="qq",
|
||||||
|
)
|
||||||
|
"""刷新群管理员权限"""
|
||||||
|
admin_default_auth = Config.get_config(
|
||||||
|
"admin_bot_manage", "ADMIN_DEFAULT_AUTH"
|
||||||
|
)
|
||||||
|
# 即刻刷新权限
|
||||||
|
for user_info in await bot.get_group_member_list(
|
||||||
|
group_id=event.group_id
|
||||||
|
):
|
||||||
|
"""即刻刷新权限"""
|
||||||
|
if (
|
||||||
|
user_info["role"]
|
||||||
|
in [
|
||||||
|
"owner",
|
||||||
|
"admin",
|
||||||
|
]
|
||||||
|
and not await LevelUser.is_group_flag(
|
||||||
|
user_info["user_id"], group_id
|
||||||
|
)
|
||||||
|
and admin_default_auth is not None
|
||||||
|
):
|
||||||
|
await LevelUser.set_level(
|
||||||
|
user_info["user_id"],
|
||||||
|
user_info["group_id"],
|
||||||
|
admin_default_auth,
|
||||||
|
)
|
||||||
|
logger.debug(
|
||||||
|
f"添加默认群管理员权限: {admin_default_auth}",
|
||||||
|
"入群检测",
|
||||||
|
session=user_info["user_id"],
|
||||||
|
group_id=user_info["group_id"],
|
||||||
|
)
|
||||||
|
if str(user_info["user_id"]) in bot.config.superusers:
|
||||||
|
await LevelUser.set_level(
|
||||||
|
user_info["user_id"], user_info["group_id"], 9
|
||||||
|
)
|
||||||
|
logger.debug(
|
||||||
|
"添加超级用户权限: 9",
|
||||||
|
"入群检测",
|
||||||
|
session=user_info["user_id"],
|
||||||
|
group_id=user_info["group_id"],
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
join_time = datetime.now()
|
||||||
|
user_info = await bot.get_group_member_info(
|
||||||
|
group_id=event.group_id, user_id=event.user_id
|
||||||
|
)
|
||||||
|
await GroupInfoUser.update_or_create(
|
||||||
|
user_id=str(user_info["user_id"]),
|
||||||
|
group_id=str(user_info["group_id"]),
|
||||||
|
defaults={"user_name": user_info["nickname"], "user_join_time": join_time},
|
||||||
|
)
|
||||||
|
logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新成功")
|
||||||
|
|
||||||
|
if _flmt.check(group_id):
|
||||||
|
"""群欢迎消息"""
|
||||||
|
_flmt.start_cd(group_id)
|
||||||
|
path = DATA_PATH / "welcome_message" / "qq" / f"{group_id}"
|
||||||
|
file = path / "text.json"
|
||||||
|
msg_list = []
|
||||||
|
if file.exists():
|
||||||
|
data = json.load((path / "text.json").open(encoding="utf-8"))
|
||||||
|
message = data["message"]
|
||||||
|
msg_split = re.split(r"\[image:\d+\]", message)
|
||||||
|
if data["at"]:
|
||||||
|
msg_list.append(At(flag="user", target=user_id))
|
||||||
|
for i, text in enumerate(msg_split):
|
||||||
|
msg_list.append(text)
|
||||||
|
img_file = path / f"{i}.png"
|
||||||
|
if img_file.exists():
|
||||||
|
msg_list.append(img_file)
|
||||||
|
if not await CommonUtils.task_is_block("group_welcome", group_id):
|
||||||
|
logger.info("发送群欢迎消息...", "入群检测", group_id=group_id)
|
||||||
|
if msg_list:
|
||||||
|
await MessageUtils.build_message(msg_list).send()
|
||||||
|
else:
|
||||||
|
image = (
|
||||||
|
IMAGE_PATH
|
||||||
|
/ "qxz"
|
||||||
|
/ random.choice(os.listdir(IMAGE_PATH / "qxz"))
|
||||||
|
)
|
||||||
|
await MessageUtils.build_message(
|
||||||
|
[
|
||||||
|
"新人快跑啊!!本群现状↓(快使用自定义!)",
|
||||||
|
image,
|
||||||
|
]
|
||||||
|
).send()
|
||||||
|
|
||||||
|
|
||||||
|
@group_decrease_handle.handle()
|
||||||
|
async def _(bot: Bot, event: GroupDecreaseNoticeEvent | GroupMemberDecreaseEvent):
|
||||||
|
if event.sub_type == "kick_me":
|
||||||
|
"""踢出Bot"""
|
||||||
|
group_id = event.group_id
|
||||||
|
operator_id = event.operator_id
|
||||||
|
if user := await GroupInfoUser.get_or_none(
|
||||||
|
user_id=str(event.operator_id), group_id=str(event.group_id)
|
||||||
|
):
|
||||||
|
operator_name = user.user_name
|
||||||
|
else:
|
||||||
|
operator_name = "None"
|
||||||
|
group = await GroupConsole.filter(group_id=str(group_id)).first()
|
||||||
|
group_name = group.group_name if group else ""
|
||||||
|
if superusers := BotConfig.get_superuser("qq"):
|
||||||
|
coffee = int(superusers[0])
|
||||||
|
await bot.send_private_msg(
|
||||||
|
user_id=coffee,
|
||||||
|
message=f"****呜..一份踢出报告****\n"
|
||||||
|
f"我被 {operator_name}({operator_id})\n"
|
||||||
|
f"踢出了 {group_name}({group_id})\n"
|
||||||
|
f"日期:{str(datetime.now()).split('.')[0]}",
|
||||||
|
)
|
||||||
|
if group:
|
||||||
|
await group.delete()
|
||||||
|
return
|
||||||
|
if str(event.user_id) == bot.self_id:
|
||||||
|
"""踢出Bot"""
|
||||||
|
await GroupConsole.filter(group_id=str(event.group_id)).delete()
|
||||||
|
return
|
||||||
|
if user := await GroupInfoUser.get_or_none(
|
||||||
|
user_id=str(event.user_id), group_id=str(event.group_id)
|
||||||
|
):
|
||||||
|
user_name = user.user_name
|
||||||
|
else:
|
||||||
|
user_name = f"{event.user_id}"
|
||||||
|
await GroupInfoUser.filter(
|
||||||
|
user_id=str(event.user_id), group_id=str(event.group_id)
|
||||||
|
).delete()
|
||||||
|
logger.info(
|
||||||
|
f"名称: {user_name} 退出群聊",
|
||||||
|
"group_decrease_handle",
|
||||||
|
session=event.user_id,
|
||||||
|
group_id=event.group_id,
|
||||||
|
)
|
||||||
|
result = ""
|
||||||
|
if event.sub_type == "leave":
|
||||||
|
result = f"{user_name}离开了我们..."
|
||||||
|
if event.sub_type == "kick":
|
||||||
|
operator = await bot.get_group_member_info(
|
||||||
|
user_id=event.operator_id, group_id=event.group_id
|
||||||
|
)
|
||||||
|
operator_name = operator["card"] or operator["nickname"]
|
||||||
|
result = f"{user_name} 被 {operator_name} 送走了."
|
||||||
|
if not await CommonUtils.task_is_block("refund_group_remind", str(event.group_id)):
|
||||||
|
await group_decrease_handle.send(f"{result}")
|
||||||
@@ -113,7 +113,7 @@ class GroupManager:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def add_bot(
|
async def add_bot(
|
||||||
cls, bot: Bot, operator_id: str, group_id: str, group: GroupConsole
|
cls, bot: Bot, operator_id: str, group_id: str, group: GroupConsole | None
|
||||||
):
|
):
|
||||||
"""拉入bot
|
"""拉入bot
|
||||||
|
|
||||||
@@ -123,11 +123,7 @@ class GroupManager:
|
|||||||
group_id: 群组id
|
group_id: 群组id
|
||||||
group: GroupConsole
|
group: GroupConsole
|
||||||
"""
|
"""
|
||||||
if (
|
if base_config.get("flag") and operator_id not in bot.config.superusers:
|
||||||
base_config.get("flag")
|
|
||||||
and operator_id not in bot.config.superusers
|
|
||||||
and group.group_flag != 1
|
|
||||||
):
|
|
||||||
"""退出群组"""
|
"""退出群组"""
|
||||||
try:
|
try:
|
||||||
if result_msg := base_config.get("message"):
|
if result_msg := base_config.get("message"):
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ async def _(
|
|||||||
elif isinstance(result, UniMessage):
|
elif isinstance(result, UniMessage):
|
||||||
await result.finish(reply_to=True)
|
await result.finish(reply_to=True)
|
||||||
except GoodsNotFound:
|
except GoodsNotFound:
|
||||||
await MessageUtils.build_message(f"没有找到道具 {name.result} 或道具数量不足...").send(
|
await MessageUtils.build_message(f"没有找到道具 {name} 或道具数量不足...").send(
|
||||||
reply_to=True
|
reply_to=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
import os
|
|
||||||
import time
|
|
||||||
|
|
||||||
from nonebot.rule import to_me
|
|
||||||
from nonebot.utils import run_sync
|
|
||||||
from nonebot.permission import SUPERUSER
|
|
||||||
from nonebot.plugin import PluginMetadata
|
|
||||||
from nonebot_plugin_session import EventSession
|
|
||||||
from nonebot_plugin_apscheduler import scheduler
|
|
||||||
from nonebot_plugin_alconna import Alconna, on_alconna
|
|
||||||
|
|
||||||
from zhenxun.services.log import logger
|
|
||||||
from zhenxun.utils.enum import PluginType
|
|
||||||
from zhenxun.utils.message import MessageUtils
|
|
||||||
from zhenxun.configs.path_config import TEMP_PATH
|
|
||||||
from zhenxun.configs.utils import PluginExtraData
|
|
||||||
from zhenxun.utils.utils import ResourceDirManager
|
|
||||||
|
|
||||||
__plugin_meta__ = PluginMetadata(
|
|
||||||
name="Bot管理",
|
|
||||||
description="指定bot对象的功能/被动开关和状态",
|
|
||||||
usage="""
|
|
||||||
清理临时数据
|
|
||||||
""".strip(),
|
|
||||||
extra=PluginExtraData(
|
|
||||||
author="",
|
|
||||||
version="0.1",
|
|
||||||
plugin_type=PluginType.SUPERUSER,
|
|
||||||
).dict(),
|
|
||||||
)
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
from nonebot.rule import Rule
|
|
||||||
from nonebot.adapters import Bot, Event
|
|
||||||
from nonebot_plugin_uninfo import Uninfo
|
|
||||||
from nonebot.plugin import PluginMetadata
|
|
||||||
from nonebot_plugin_alconna.uniseg.tools import reply_fetch
|
|
||||||
from nonebot_plugin_alconna import Alconna, Arparma, on_alconna
|
|
||||||
|
|
||||||
from zhenxun.services.log import logger
|
|
||||||
from zhenxun.utils.message import MessageUtils
|
|
||||||
from zhenxun.utils.platform import PlatformUtils
|
|
||||||
from zhenxun.configs.utils import PluginExtraData
|
|
||||||
from zhenxun.utils.manager.message_manager import MessageManager
|
|
||||||
|
|
||||||
__plugin_meta__ = PluginMetadata(
|
|
||||||
name="消息撤回",
|
|
||||||
description="撤回自己触发的消息撤回,不允许撤回其他人触发消息的撤回哦",
|
|
||||||
usage="""
|
|
||||||
引用消息 撤回
|
|
||||||
""".strip(),
|
|
||||||
extra=PluginExtraData(author="HibiKier", version="0.1", menu_type="其他").dict(),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def reply_check() -> Rule:
|
|
||||||
"""
|
|
||||||
检查是否存在回复消息
|
|
||||||
|
|
||||||
返回:
|
|
||||||
Rule: Rule
|
|
||||||
"""
|
|
||||||
|
|
||||||
async def _rule(bot: Bot, event: Event, session: Uninfo):
|
|
||||||
if event.get_type() == "message":
|
|
||||||
return (
|
|
||||||
bool(await reply_fetch(event, bot))
|
|
||||||
and PlatformUtils.get_platform(session) == "qq"
|
|
||||||
)
|
|
||||||
return False
|
|
||||||
|
|
||||||
return Rule(_rule)
|
|
||||||
|
|
||||||
|
|
||||||
_matcher = on_alconna(Alconna("撤回"), priority=5, block=True, rule=reply_check())
|
|
||||||
|
|
||||||
|
|
||||||
@_matcher.handle()
|
|
||||||
async def _(bot: Bot, event: Event, session: Uninfo, arparma: Arparma):
|
|
||||||
if reply := await reply_fetch(event, bot):
|
|
||||||
if (
|
|
||||||
MessageManager.check(session.user.id, reply.id)
|
|
||||||
or session.user.id in bot.config.superusers
|
|
||||||
):
|
|
||||||
try:
|
|
||||||
await bot.delete_msg(message_id=reply.id)
|
|
||||||
logger.info("撤回消息", arparma.header_result, session=session)
|
|
||||||
except Exception:
|
|
||||||
await MessageUtils.build_message("撤回失败,可能消息已过期...").send()
|
|
||||||
else:
|
|
||||||
await MessageUtils.build_message(
|
|
||||||
"权限不足,不是你触发的消息不要胡乱撤回哦..."
|
|
||||||
).send()
|
|
||||||
@@ -288,6 +288,13 @@ class ConfigsManager:
|
|||||||
config.value = value
|
config.value = value
|
||||||
config.default_value = default_value
|
config.default_value = default_value
|
||||||
else:
|
else:
|
||||||
|
_module = None
|
||||||
|
if ":" in module:
|
||||||
|
module_split = module.split(":")
|
||||||
|
if len(module_split) < 2:
|
||||||
|
raise ValueError(f"module: {module} 填写错误")
|
||||||
|
_module = module_split[-1]
|
||||||
|
module = module_split[0]
|
||||||
key = key.upper()
|
key = key.upper()
|
||||||
if not self._data.get(module):
|
if not self._data.get(module):
|
||||||
self._data[module] = ConfigGroup(module=module)
|
self._data[module] = ConfigGroup(module=module)
|
||||||
@@ -304,6 +311,7 @@ class ConfigsManager:
|
|||||||
key: str,
|
key: str,
|
||||||
value: Any,
|
value: Any,
|
||||||
auto_save: bool = False,
|
auto_save: bool = False,
|
||||||
|
save_simple_data: bool = True,
|
||||||
):
|
):
|
||||||
"""设置配置值
|
"""设置配置值
|
||||||
|
|
||||||
@@ -312,16 +320,15 @@ class ConfigsManager:
|
|||||||
key: 配置名称
|
key: 配置名称
|
||||||
value: 值
|
value: 值
|
||||||
auto_save: 自动保存.
|
auto_save: 自动保存.
|
||||||
|
save_simple_data: 保存至config.yaml.
|
||||||
"""
|
"""
|
||||||
key = key.upper()
|
|
||||||
if module in self._data:
|
if module in self._data:
|
||||||
if self._data[module].configs.get(key):
|
data = self._data[module].configs.get(key)
|
||||||
|
if data and data != value:
|
||||||
self._data[module].configs[key].value = value
|
self._data[module].configs[key].value = value
|
||||||
else:
|
self._simple_data[module][key] = value
|
||||||
self.add_plugin_config(module, key, value)
|
|
||||||
self._simple_data[module][key] = value
|
|
||||||
if auto_save:
|
if auto_save:
|
||||||
self.save(save_simple_data=True)
|
self.save(save_simple_data=save_simple_data)
|
||||||
|
|
||||||
def get_config(self, module: str, key: str, default: Any = None) -> Any:
|
def get_config(self, module: str, key: str, default: Any = None) -> Any:
|
||||||
"""获取指定配置值
|
"""获取指定配置值
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
from tortoise import fields
|
|
||||||
|
|
||||||
from zhenxun.services.db_context import Model
|
|
||||||
|
|
||||||
|
|
||||||
class BotConsole(Model):
|
|
||||||
id = fields.IntField(pk=True, generated=True, auto_increment=True)
|
|
||||||
"""自增id"""
|
|
||||||
bot_id = fields.CharField(255, unique=True, description="bot_id")
|
|
||||||
"""bot_id"""
|
|
||||||
status = fields.BooleanField(default=True, description="Bot状态")
|
|
||||||
"""Bot状态"""
|
|
||||||
block_plugin = fields.TextField(default="", description="禁用插件")
|
|
||||||
"""禁用插件"""
|
|
||||||
block_task = fields.TextField(default="", description="禁用被动技能")
|
|
||||||
"""禁用被动技能"""
|
|
||||||
create_time = fields.DatetimeField(auto_now_add=True, description="创建时间")
|
|
||||||
"""创建时间"""
|
|
||||||
platform = fields.CharField(255, null=True, description="平台")
|
|
||||||
"""平台"""
|
|
||||||
|
|
||||||
class Meta: # type: ignore
|
|
||||||
table = "bot_console"
|
|
||||||
table_description = "Bot数据表"
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def get_bot_status(cls, bot_id: str) -> bool:
|
|
||||||
result = await cls.get_or_none(bot_id=bot_id)
|
|
||||||
return result.status if result else False
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def set_block_plugin(cls, bot_id: str, module: str):
|
|
||||||
bot_data, _ = await cls.get_or_create(bot_id=bot_id)
|
|
||||||
if f"<{module}," not in bot_data.block_plugin:
|
|
||||||
bot_data.block_plugin += f"<{module},"
|
|
||||||
await bot_data.save(update_fields=["block_plugin"])
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def set_unblock_plugin(cls, bot_id: str, module: str):
|
|
||||||
bot_data, _ = await cls.get_or_create(bot_id=bot_id)
|
|
||||||
if f"<{module}," in bot_data.block_plugin:
|
|
||||||
bot_data.block_plugin = bot_data.block_plugin.replace(f"<{module},", "")
|
|
||||||
await bot_data.save(update_fields=["block_plugin"])
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def set_block_task(cls, bot_id: str, task: str):
|
|
||||||
bot_data, _ = await cls.get_or_create(bot_id=bot_id)
|
|
||||||
if f"<{task}," not in bot_data.block_task:
|
|
||||||
bot_data.block_plugin += f"<{task},"
|
|
||||||
await bot_data.save(update_fields=["block_task"])
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def is_block_plugin(cls, bot_id: str, task: str) -> bool:
|
|
||||||
bot_data, _ = await cls.get_or_create(bot_id=bot_id)
|
|
||||||
return f"<{task}," in bot_data.block_plugin
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def is_block_task(cls, bot_id: str, task: str) -> bool:
|
|
||||||
bot_data, _ = await cls.get_or_create(bot_id=bot_id)
|
|
||||||
return f"<{task}," in bot_data.block_task
|
|
||||||
@@ -37,8 +37,8 @@ class GroupConsole(Model):
|
|||||||
default="", description="超级用户禁用插件"
|
default="", description="超级用户禁用插件"
|
||||||
)
|
)
|
||||||
"""超级用户禁用插件"""
|
"""超级用户禁用插件"""
|
||||||
block_task = fields.TextField(default="", description="禁用被动技能")
|
block_task = fields.TextField(default="", description="禁用插件")
|
||||||
"""禁用被动技能"""
|
"""禁用插件"""
|
||||||
superuser_block_task = fields.TextField(default="", description="超级用户禁用被动")
|
superuser_block_task = fields.TextField(default="", description="超级用户禁用被动")
|
||||||
"""超级用户禁用被动"""
|
"""超级用户禁用被动"""
|
||||||
platform = fields.CharField(255, default="qq", description="所属平台")
|
platform = fields.CharField(255, default="qq", description="所属平台")
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ from ._build_image import BuildImage
|
|||||||
|
|
||||||
|
|
||||||
class RowStyle(BaseModel):
|
class RowStyle(BaseModel):
|
||||||
|
|
||||||
font: FreeTypeFont | str | Path | None = "HYWenHei-85W.ttf"
|
font: FreeTypeFont | str | Path | None = "HYWenHei-85W.ttf"
|
||||||
"""字体"""
|
"""字体"""
|
||||||
font_size: int = 20
|
font_size: int = 20
|
||||||
@@ -22,6 +23,7 @@ class RowStyle(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class ImageTemplate:
|
class ImageTemplate:
|
||||||
|
|
||||||
color_list = ["#C2CEFE", "#FFA94C", "#3FE6A0", "#D1D4F5"] # noqa: RUF012
|
color_list = ["#C2CEFE", "#FFA94C", "#3FE6A0", "#D1D4F5"] # noqa: RUF012
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -86,7 +88,7 @@ class ImageTemplate:
|
|||||||
head_text: str,
|
head_text: str,
|
||||||
tip_text: str | None,
|
tip_text: str | None,
|
||||||
column_name: list[str],
|
column_name: list[str],
|
||||||
data_list: list[list[str | int | tuple[Path | BuildImage, int, int]]],
|
data_list: list[list[str | tuple[Path | BuildImage, int, int]]],
|
||||||
row_space: int = 35,
|
row_space: int = 35,
|
||||||
column_space: int = 30,
|
column_space: int = 30,
|
||||||
padding: int = 5,
|
padding: int = 5,
|
||||||
@@ -135,7 +137,7 @@ class ImageTemplate:
|
|||||||
async def table(
|
async def table(
|
||||||
cls,
|
cls,
|
||||||
column_name: list[str],
|
column_name: list[str],
|
||||||
data_list: list[list[str | int | tuple[Path | BuildImage, int, int]]],
|
data_list: list[list[str | tuple[Path | BuildImage, int, int]]],
|
||||||
row_space: int = 25,
|
row_space: int = 25,
|
||||||
column_space: int = 10,
|
column_space: int = 10,
|
||||||
padding: int = 5,
|
padding: int = 5,
|
||||||
@@ -161,7 +163,7 @@ class ImageTemplate:
|
|||||||
c = []
|
c = []
|
||||||
for lst in data_list:
|
for lst in data_list:
|
||||||
if len(lst) > i:
|
if len(lst) > i:
|
||||||
c.append(str(lst[i]))
|
c.append(lst[i])
|
||||||
else:
|
else:
|
||||||
c.append("")
|
c.append("")
|
||||||
column_data.append(c)
|
column_data.append(c)
|
||||||
@@ -174,7 +176,7 @@ class ImageTemplate:
|
|||||||
if isinstance(s, tuple):
|
if isinstance(s, tuple):
|
||||||
w = s[1]
|
w = s[1]
|
||||||
else:
|
else:
|
||||||
w, _ = BuildImage.get_text_size(str(s), font)
|
w, _ = BuildImage.get_text_size(s, font)
|
||||||
if w > _temp["width"]:
|
if w > _temp["width"]:
|
||||||
_temp["width"] = w
|
_temp["width"] = w
|
||||||
build_data_list.append(_temp)
|
build_data_list.append(_temp)
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
|
GITHUB_REPO_URL_PATTERN = re.compile(
|
||||||
|
r"^https://github.com/(?P<owner>[^/]+)/(?P<repo>[^/]+)(/tree/(?P<branch>[^/]+))?$"
|
||||||
|
)
|
||||||
|
"""github仓库地址正则"""
|
||||||
|
|
||||||
|
JSD_PACKAGE_API_FORMAT = (
|
||||||
|
"https://data.jsdelivr.com/v1/packages/gh/{owner}/{repo}@{branch}"
|
||||||
|
)
|
||||||
|
"""jsdelivr包地址格式"""
|
||||||
|
|
||||||
|
GIT_API_TREES_FORMAT = (
|
||||||
|
"https://api.github.com/repos/{owner}/{repo}/git/trees/{branch}?recursive=1"
|
||||||
|
)
|
||||||
|
"""git api trees地址格式"""
|
||||||
|
|
||||||
|
CACHED_API_TTL = 300
|
||||||
|
"""缓存api ttl"""
|
||||||
|
|
||||||
|
RAW_CONTENT_FORMAT = "https://raw.githubusercontent.com/{owner}/{repo}/{branch}/{path}"
|
||||||
|
"""raw content格式"""
|
||||||
|
|
||||||
|
ARCHIVE_URL_FORMAT = "https://github.com/{owner}/{repo}/archive/refs/heads/{branch}.zip"
|
||||||
|
"""archive url格式"""
|
||||||
|
|
||||||
|
RELEASE_ASSETS_FORMAT = (
|
||||||
|
"https://github.com/{owner}/{repo}/releases/download/{version}/{filename}"
|
||||||
|
)
|
||||||
|
"""release assets格式"""
|
||||||
|
|
||||||
|
RELEASE_SOURCE_FORMAT = (
|
||||||
|
"https://codeload.github.com/{owner}/{repo}/legacy.{compress}/refs/tags/{version}"
|
||||||
|
)
|
||||||
|
"""release 源码格式"""
|
||||||
@@ -390,7 +390,7 @@ def get_img_hash(image_file: str | Path) -> str:
|
|||||||
return str(hash_value)
|
return str(hash_value)
|
||||||
|
|
||||||
|
|
||||||
async def get_download_image_hash(url: str, mark: str, use_proxy: bool = False) -> str:
|
async def get_download_image_hash(url: str, mark: str) -> str:
|
||||||
"""下载图片获取哈希值
|
"""下载图片获取哈希值
|
||||||
|
|
||||||
参数:
|
参数:
|
||||||
@@ -402,7 +402,7 @@ async def get_download_image_hash(url: str, mark: str, use_proxy: bool = False)
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
if await AsyncHttpx.download_file(
|
if await AsyncHttpx.download_file(
|
||||||
url, TEMP_PATH / f"compare_download_{mark}_img.jpg", use_proxy=use_proxy
|
url, TEMP_PATH / f"compare_download_{mark}_img.jpg"
|
||||||
):
|
):
|
||||||
img_hash = get_img_hash(TEMP_PATH / f"compare_download_{mark}_img.jpg")
|
img_hash = get_img_hash(TEMP_PATH / f"compare_download_{mark}_img.jpg")
|
||||||
return str(img_hash)
|
return str(img_hash)
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
from typing import ClassVar
|
|
||||||
|
|
||||||
|
|
||||||
class MessageManager:
|
|
||||||
data: ClassVar[dict[str, list[str]]] = {}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def add(cls, uid: str, msg_id: str):
|
|
||||||
if uid not in cls.data:
|
|
||||||
cls.data[uid] = []
|
|
||||||
cls.data[uid].append(msg_id)
|
|
||||||
cls.remove_check(uid)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def check(cls, uid: str, msg_id: str) -> bool:
|
|
||||||
return msg_id in cls.data.get(uid, [])
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def remove_check(cls, uid: str):
|
|
||||||
if len(cls.data[uid]) > 200:
|
|
||||||
cls.data[uid] = cls.data[uid][100:]
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get(cls, uid: str) -> list[str]:
|
|
||||||
if uid in cls.data:
|
|
||||||
return cls.data[uid]
|
|
||||||
return []
|
|
||||||
@@ -4,17 +4,7 @@ from pathlib import Path
|
|||||||
import nonebot
|
import nonebot
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from nonebot.adapters.onebot.v11 import Message, MessageSegment
|
from nonebot.adapters.onebot.v11 import Message, MessageSegment
|
||||||
from nonebot_plugin_alconna import (
|
from nonebot_plugin_alconna import At, Text, AtAll, Image, Video, Voice, UniMessage
|
||||||
At,
|
|
||||||
Text,
|
|
||||||
AtAll,
|
|
||||||
Image,
|
|
||||||
Video,
|
|
||||||
Voice,
|
|
||||||
Reference,
|
|
||||||
CustomNode,
|
|
||||||
UniMessage,
|
|
||||||
)
|
|
||||||
|
|
||||||
from zhenxun.services.log import logger
|
from zhenxun.services.log import logger
|
||||||
from zhenxun.configs.config import BotConfig
|
from zhenxun.configs.config import BotConfig
|
||||||
@@ -99,36 +89,6 @@ class MessageUtils:
|
|||||||
message_list += cls.__build_message(_data) # type: ignore
|
message_list += cls.__build_message(_data) # type: ignore
|
||||||
return UniMessage(message_list)
|
return UniMessage(message_list)
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def alc_forward_msg(
|
|
||||||
cls,
|
|
||||||
msg_list: list,
|
|
||||||
uin: str,
|
|
||||||
name: str,
|
|
||||||
) -> UniMessage:
|
|
||||||
"""生成自定义合并消息
|
|
||||||
|
|
||||||
参数:
|
|
||||||
msg_list: 消息列表
|
|
||||||
uin: 发送者 QQ
|
|
||||||
name: 自定义名称
|
|
||||||
|
|
||||||
返回:
|
|
||||||
list[dict]: 转发消息
|
|
||||||
"""
|
|
||||||
node_list = []
|
|
||||||
for _message in msg_list:
|
|
||||||
if isinstance(_message, list):
|
|
||||||
for i in range(len(_message.copy())):
|
|
||||||
if isinstance(_message[i], Path):
|
|
||||||
_message[i] = Image(
|
|
||||||
raw=BuildImage.open(_message[i]).pic2bytes()
|
|
||||||
)
|
|
||||||
node_list.append(
|
|
||||||
CustomNode(uid=uin, name=name, content=UniMessage(_message))
|
|
||||||
)
|
|
||||||
return UniMessage(Reference(nodes=node_list))
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def custom_forward_msg(
|
def custom_forward_msg(
|
||||||
cls,
|
cls,
|
||||||
@@ -178,7 +138,7 @@ class MessageUtils:
|
|||||||
if isinstance(r, Text):
|
if isinstance(r, Text):
|
||||||
s += str(r)
|
s += str(r)
|
||||||
elif isinstance(r, Image):
|
elif isinstance(r, Image):
|
||||||
if v := r.url or r.path or r.raw:
|
if v := r.url or r.path:
|
||||||
s += MessageSegment.image(v)
|
s += MessageSegment.image(v)
|
||||||
elif isinstance(r_list, Image):
|
elif isinstance(r_list, Image):
|
||||||
if v := r_list.url or r_list.path:
|
if v := r_list.url or r_list.path:
|
||||||
|
|||||||
@@ -27,14 +27,14 @@ def admin_check(a: int | str, key: str | None = None) -> Rule:
|
|||||||
if PlatformUtils.is_qbot(session):
|
if PlatformUtils.is_qbot(session):
|
||||||
"""官bot接口,放弃所有权限检查"""
|
"""官bot接口,放弃所有权限检查"""
|
||||||
return False
|
return False
|
||||||
if session.group:
|
if session.id and session.group:
|
||||||
level = a
|
level = a
|
||||||
if isinstance(a, str) and key:
|
if isinstance(a, str) and key:
|
||||||
level = Config.get_config(a, key)
|
level = Config.get_config(a, key)
|
||||||
if level is not None:
|
if level is not None:
|
||||||
return bool(
|
return bool(
|
||||||
await LevelUser.check_level(
|
await LevelUser.check_level(
|
||||||
session.user.id, session.group.id, int(level)
|
session.id, session.group.id, int(level)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -189,7 +189,6 @@ def change_pixiv_image_links(
|
|||||||
url = (
|
url = (
|
||||||
url.replace("i.pximg.net", nginx_url)
|
url.replace("i.pximg.net", nginx_url)
|
||||||
.replace("i.pixiv.cat", nginx_url)
|
.replace("i.pixiv.cat", nginx_url)
|
||||||
.replace("i.pixiv.re", nginx_url)
|
|
||||||
.replace("_webp", "")
|
.replace("_webp", "")
|
||||||
)
|
)
|
||||||
return url
|
return url
|
||||||
|
|||||||