Config提供type字段确定配置项类型

This commit is contained in:
HibiKier 2023-02-26 22:17:26 +08:00
parent a63fda8a0d
commit 8133b61ebd
53 changed files with 1589 additions and 1000 deletions

View File

@ -331,6 +331,10 @@ PS: **ARM平台** 请使用全量版 同时 **如果你的机器 RAM < 1G 可能
## 更新
### 2023/2/26
* Config提供`type`字段确定配置项类型
### 2023/2/25
* 修复ys查询尘歌壶背景尺寸与内容不匹配的问题 [@pull/1270](https://github.com/HibiKier/zhenxun_bot/pull/1275)

View File

@ -1,8 +1,8 @@
from pathlib import Path
from configs.config import Config
import nonebot
from configs.config import Config
Config.add_plugin_config(
"admin_bot_manage:custom_welcome_message",
@ -11,6 +11,7 @@ Config.add_plugin_config(
name="群管理员操作",
help_="设置群欢迎消息权限",
default_value=2,
type=int,
)
Config.add_plugin_config(
@ -19,6 +20,7 @@ Config.add_plugin_config(
2,
help_="开关群功能权限",
default_value=2,
type=int,
)
Config.add_plugin_config(
@ -26,7 +28,8 @@ Config.add_plugin_config(
"ADMIN_DEFAULT_AUTH",
5,
help_="默认群管理员权限",
default_value=5
default_value=5,
type=int,
)
nonebot.load_plugins(str(Path(__file__).parent.resolve()))

View File

@ -1,5 +1,6 @@
import shutil
from pathlib import Path
from typing import List
import nonebot
from nonebot import on_message
@ -20,15 +21,11 @@ __plugin_task__ = {"zwa": "早晚安"}
Config.add_plugin_config(
"_task",
"DEFAULT_ZWA",
True,
help_="被动 早晚安 进群默认开关状态",
default_value=True,
"_task", "DEFAULT_ZWA", True, help_="被动 早晚安 进群默认开关状态", default_value=True, type=bool
)
Config.add_plugin_config(
"_backup", "BACKUP_FLAG", True, help_="是否开启文件备份", default_value=True
"_backup", "BACKUP_FLAG", True, help_="是否开启文件备份", default_value=True, type=bool
)
Config.add_plugin_config(
@ -45,6 +42,7 @@ Config.add_plugin_config(
name="文件备份",
help_="备份的文件夹或文件",
default_value=[],
type=List[str],
)

View File

@ -56,6 +56,7 @@ __plugin_configs__ = {
"value": 5,
"help": "ban/unban所需要的管理员权限等级",
"default_value": 5,
"type": int
}
}

View File

@ -1,14 +1,15 @@
from nonebot.adapters.onebot.v11 import Bot, Message, MessageEvent
from nonebot import on_command
from nonebot.permission import SUPERUSER
from nonebot.params import CommandArg
from utils.utils import get_message_img
from services.log import logger
from utils.message_builder import image
from utils.manager import group_manager
from configs.config import Config
import asyncio
from nonebot import on_command
from nonebot.adapters.onebot.v11 import Bot, Message, MessageEvent
from nonebot.params import CommandArg
from nonebot.permission import SUPERUSER
from configs.config import Config
from services.log import logger
from utils.manager import group_manager
from utils.message_builder import image
from utils.utils import get_message_img
__zx_plugin_name__ = "广播 [Superuser]"
__plugin_usage__ = """
@ -28,6 +29,7 @@ Config.add_plugin_config(
True,
help_="被动 广播 进群默认开关状态",
default_value=True,
type=bool,
)
broadcast = on_command("广播-", priority=1, permission=SUPERUSER, block=True)

View File

@ -15,7 +15,13 @@ __plugin_author__ = "HibiKier"
Config.add_plugin_config(
"chat_history", "FLAG", True, help_="是否开启消息自从存储", name="消息存储", default_value=True
"chat_history",
"FLAG",
True,
help_="是否开启消息自从存储",
name="消息存储",
default_value=True,
type=bool,
)

View File

@ -31,10 +31,10 @@ Config.add_plugin_config(
"invite_manager", "message", f"请不要未经同意就拉{NICKNAME}入群!告辞!", help_="强制拉群后进群回复的内容.."
)
Config.add_plugin_config(
"invite_manager", "flag", True, help_="被强制拉群后是否直接退出", default_value=True
"invite_manager", "flag", True, help_="被强制拉群后是否直接退出", default_value=True, type=bool
)
Config.add_plugin_config(
"invite_manager", "welcome_msg_cd", 5, help_="群欢迎消息cd", default_value=5
"invite_manager", "welcome_msg_cd", 5, help_="群欢迎消息cd", default_value=5, type=int
)
Config.add_plugin_config(
"_task",
@ -42,6 +42,7 @@ Config.add_plugin_config(
True,
help_="被动 进群欢迎 进群默认开关状态",
default_value=True,
type=bool,
)
Config.add_plugin_config(
"_task",
@ -49,10 +50,11 @@ Config.add_plugin_config(
True,
help_="被动 退群提醒 进群默认开关状态",
default_value=True,
type=bool,
)
_flmt = FreqLimiter(Config.get_config("invite_manager", "welcome_msg_cd"))
_flmt = FreqLimiter(Config.get_config("invite_manager", "welcome_msg_cd") or 5)
# 群员增加处理

View File

@ -1,13 +1,13 @@
from configs.config import Config
Config.add_plugin_config(
"hook",
"CHECK_NOTICE_INFO_CD",
300,
name="基础hook配置",
help_="群检测个人权限检测等各种检测提示信息cd",
default_value=300
default_value=300,
type=int,
)
Config.add_plugin_config(
@ -15,7 +15,8 @@ Config.add_plugin_config(
"MALICIOUS_BAN_TIME",
30,
help_="恶意命令触发检测触发后ban的时长分钟",
default_value=30
default_value=30,
type=int,
)
Config.add_plugin_config(
@ -23,14 +24,10 @@ Config.add_plugin_config(
"MALICIOUS_CHECK_TIME",
5,
help_="恶意命令触发检测规定时间内(秒)",
default_value=5
default_value=5,
type=int,
)
Config.add_plugin_config(
"hook",
"MALICIOUS_BAN_COUNT",
6,
help_="恶意命令触发检测最大触发次数",
default_value=6
"hook", "MALICIOUS_BAN_COUNT", 6, help_="恶意命令触发检测最大触发次数", default_value=6, type=int
)

View File

@ -1,14 +1,26 @@
import random
from types import ModuleType
from typing import Any
from typing import Any, Dict
from configs.config import Config
from services import logger
from utils.manager import (plugin_data_manager, plugins2block_manager,
plugins2cd_manager, plugins2count_manager,
plugins2settings_manager, plugins_manager)
from utils.manager.models import (Plugin, PluginBlock, PluginCd, PluginCount,
PluginData, PluginSetting, PluginType)
from utils.manager import (
plugin_data_manager,
plugins2block_manager,
plugins2cd_manager,
plugins2count_manager,
plugins2settings_manager,
plugins_manager,
)
from utils.manager.models import (
Plugin,
PluginBlock,
PluginCd,
PluginCount,
PluginData,
PluginSetting,
PluginType,
)
from utils.utils import get_matchers
@ -21,104 +33,115 @@ def get_attr(module: ModuleType, name: str, default: Any = None) -> Any:
:param name: name
:param default: default
"""
return getattr(module, name) if hasattr(module, name) else default
return getattr(module, name, None) or default
def init_plugin_info():
for matcher in [x for x in get_matchers(True) if x.plugin]:
for matcher in [x for x in get_matchers(True)]:
try:
plugin = matcher.plugin
metadata = plugin.metadata
extra = metadata.extra if metadata else {}
if hasattr(plugin, "module"):
module = plugin.module
plugin_model = matcher.plugin_name
plugin_name = (
metadata.name
if metadata and metadata.name
else get_attr(module, "__zx_plugin_name__", matcher.plugin_name)
)
if not plugin_name:
logger.warning(f"配置文件 模块:{plugin_model} 获取 plugin_name 失败...")
continue
if "[Admin]" in plugin_name:
plugin_type = PluginType.ADMIN
plugin_name = plugin_name.replace("[Admin]", "").strip()
elif "[Hidden]" in plugin_name:
plugin_type = PluginType.HIDDEN
plugin_name = plugin_name.replace("[Hidden]", "").strip()
elif "[Superuser]" in plugin_name:
plugin_type = PluginType.SUPERUSER
plugin_name = plugin_name.replace("[Superuser]", "").strip()
else:
plugin_type = PluginType.NORMAL
plugin_usage = (
metadata.usage
if metadata and metadata.usage
else get_attr(module, "__plugin_usage__")
)
plugin_des = (
metadata.description
if metadata and metadata.description
else get_attr(module, "__plugin_des__")
)
menu_type = get_attr(module, "__plugin_type__") or ("normal",)
plugin_setting = get_attr(module, "__plugin_settings__")
if plugin_setting:
plugin_setting = PluginSetting(**plugin_setting)
plugin_setting.plugin_type = menu_type
plugin_superuser_usage = get_attr(module, "__plugin_super_usage__")
plugin_task = get_attr(module, "__plugin_task__")
plugin_version = extra.get("__plugin_version__") or get_attr(
module, "__plugin_version__"
)
plugin_author = extra.get("__plugin_author__") or get_attr(
module, "__plugin_author__"
)
plugin_cd = get_attr(module, "__plugin_cd_limit__")
if plugin_cd:
plugin_cd = PluginCd(**plugin_cd)
plugin_block = get_attr(module, "__plugin_block_limit__")
if plugin_block:
plugin_block = PluginBlock(**plugin_block)
plugin_count = get_attr(module, "__plugin_count_limit__")
if plugin_count:
plugin_count = PluginCount(**plugin_count)
plugin_resources = get_attr(module, "__plugin_resources__")
plugin_configs = get_attr(module, "__plugin_configs__")
if settings := plugins2settings_manager.get(plugin_model):
plugin_setting = settings
if plugin_cd_limit := plugins2cd_manager.get(plugin_model):
plugin_cd = plugin_cd_limit
if plugin_block_limit := plugins2block_manager.get(plugin_model):
plugin_block = plugin_block_limit
if plugin_count_limit := plugins2count_manager.get(plugin_model):
plugin_count = plugin_count_limit
if plugin_cfg := Config.get(plugin_model):
plugin_configs = plugin_cfg
plugin_status = plugins_manager.get(plugin_model)
if not plugin_status:
plugin_status = Plugin(plugin_name=plugin_model)
plugin_status.author = plugin_author
plugin_status.version = plugin_version
plugin_data = PluginData(
model=plugin_model,
name=plugin_name.strip(),
plugin_type=plugin_type,
usage=plugin_usage,
superuser_usage=plugin_superuser_usage,
des=plugin_des,
task=plugin_task,
menu_type=menu_type,
plugin_setting=plugin_setting,
plugin_cd=plugin_cd,
plugin_block=plugin_block,
plugin_count=plugin_count,
plugin_resources=plugin_resources,
plugin_configs=plugin_configs,
plugin_status=plugin_status,
)
plugin_data_manager.add_plugin_info(plugin_data)
if (plugin := matcher.plugin) and matcher.plugin_name:
metadata = plugin.metadata
extra = metadata.extra if metadata else {}
if hasattr(plugin, "module"):
module = plugin.module
plugin_model = matcher.plugin_name
plugin_name = (
metadata.name
if metadata and metadata.name
else get_attr(module, "__zx_plugin_name__", matcher.plugin_name)
)
if not plugin_name:
logger.warning(f"配置文件 模块:{plugin_model} 获取 plugin_name 失败...")
continue
if "[Admin]" in plugin_name:
plugin_type = PluginType.ADMIN
plugin_name = plugin_name.replace("[Admin]", "").strip()
elif "[Hidden]" in plugin_name:
plugin_type = PluginType.HIDDEN
plugin_name = plugin_name.replace("[Hidden]", "").strip()
elif "[Superuser]" in plugin_name:
plugin_type = PluginType.SUPERUSER
plugin_name = plugin_name.replace("[Superuser]", "").strip()
else:
plugin_type = PluginType.NORMAL
plugin_usage = (
metadata.usage
if metadata and metadata.usage
else get_attr(module, "__plugin_usage__")
)
plugin_des = (
metadata.description
if metadata and metadata.description
else get_attr(module, "__plugin_des__")
)
menu_type = get_attr(module, "__plugin_type__") or ("normal",)
plugin_setting = get_attr(module, "__plugin_settings__")
if plugin_setting:
plugin_setting = PluginSetting(**plugin_setting)
plugin_setting.plugin_type = menu_type
plugin_superuser_usage = get_attr(module, "__plugin_super_usage__")
plugin_task = get_attr(module, "__plugin_task__")
plugin_version = extra.get("__plugin_version__") or get_attr(
module, "__plugin_version__"
)
plugin_author = extra.get("__plugin_author__") or get_attr(
module, "__plugin_author__"
)
plugin_cd = get_attr(module, "__plugin_cd_limit__")
if plugin_cd:
plugin_cd = PluginCd(**plugin_cd)
plugin_block = get_attr(module, "__plugin_block_limit__")
if plugin_block:
plugin_block = PluginBlock(**plugin_block)
plugin_count = get_attr(module, "__plugin_count_limit__")
if plugin_count:
plugin_count = PluginCount(**plugin_count)
plugin_resources = get_attr(module, "__plugin_resources__")
plugin_configs = get_attr(module, "__plugin_configs__")
if settings := plugins2settings_manager.get(plugin_model):
plugin_setting = settings
if plugin_cd_limit := plugins2cd_manager.get(plugin_model):
plugin_cd = plugin_cd_limit
if plugin_block_limit := plugins2block_manager.get(plugin_model):
plugin_block = plugin_block_limit
if plugin_count_limit := plugins2count_manager.get(plugin_model):
plugin_count = plugin_count_limit
if plugin_cfg := Config.get(plugin_model):
if plugin_configs:
for config_name in plugin_configs:
config: Dict[str, Any] = plugin_configs[config_name] # type: ignore
Config.add_plugin_config(
plugin_model,
config_name,
config.get("value"),
help_=config.get("help"),
default_value=config.get("default_value"),
type=config.get("type") or str,
)
plugin_configs = plugin_cfg.configs
plugin_status = plugins_manager.get(plugin_model)
if not plugin_status:
plugin_status = Plugin(plugin_name=plugin_model)
plugin_status.author = plugin_author
plugin_status.version = plugin_version
plugin_data = PluginData(
model=plugin_model,
name=plugin_name.strip(),
plugin_type=plugin_type,
usage=plugin_usage,
superuser_usage=plugin_superuser_usage,
des=plugin_des,
task=plugin_task,
menu_type=menu_type,
plugin_setting=plugin_setting,
plugin_cd=plugin_cd,
plugin_block=plugin_block,
plugin_count=plugin_count,
plugin_resources=plugin_resources,
plugin_configs=plugin_configs, # type: ignore
plugin_status=plugin_status,
)
plugin_data_manager.add_plugin_info(plugin_data)
except Exception as e:
logger.error(f"构造插件数据失败 {matcher.plugin_name} - {type(e)}{e}")
logger.error(f"构造插件数据失败 {matcher.plugin_name}", e=e)

View File

@ -1,13 +1,14 @@
from pathlib import Path
from ruamel.yaml import round_trip_load, round_trip_dump, YAML
from utils.manager import admin_manager, plugins_manager, plugin_data_manager
from ruamel import yaml
from ruamel.yaml import YAML, round_trip_dump, round_trip_load
from configs.config import Config
from configs.path_config import DATA_PATH
from services.log import logger
from utils.manager import admin_manager, plugin_data_manager, plugins_manager
from utils.text_utils import prompt2cn
from utils.utils import get_matchers
from configs.path_config import DATA_PATH
from ruamel import yaml
_yaml = YAML(typ="safe")
@ -20,47 +21,60 @@ def init_plugins_config():
_data = Config.get_data()
# 优先使用 metadata 数据
for matcher in get_matchers(True):
if plugin_data := plugin_data_manager.get(matcher.plugin_name):
# 插件配置版本更新或为Version为None或不在存储配置内当使用metadata时必定更新
if plugin_data.plugin_configs and (
isinstance(plugin_data.plugin_status.version, str)
or (
plugin_data.plugin_status.version is None
if matcher.plugin_name:
if plugin_data := plugin_data_manager.get(matcher.plugin_name):
# 插件配置版本更新或为Version为None或不在存储配置内当使用metadata时必定更新
version = plugin_data.plugin_status.version
config = _data.get(matcher.plugin_name)
plugin = plugins_manager.get(matcher.plugin_name)
if plugin_data.plugin_configs and (
isinstance(version, str)
or (
_data.get(matcher.plugin_name)
and _data[matcher.plugin_name].keys()
!= plugin_data.plugin_configs.keys()
version is None
or (
config
and config.configs.keys()
!= plugin_data.plugin_configs.keys()
)
or version > int(plugin.version or 0)
or matcher.plugin_name not in _data.keys()
)
or plugin_data.plugin_status.version
> plugins_manager.get(matcher.plugin_name).version
or matcher.plugin_name not in _data.keys()
)
):
plugin_configs = plugin_data.plugin_configs
for key in plugin_configs:
if isinstance(plugin_data.plugin_configs[key], dict):
):
plugin_configs = plugin_data.plugin_configs
for key in plugin_configs:
if isinstance(plugin_data.plugin_configs[key], dict):
Config.add_plugin_config(
matcher.plugin_name,
key,
plugin_configs[key].get("value"),
help_=plugin_configs[key].get("help"),
default_value=plugin_configs[key].get("default_value"),
_override=True,
type=plugin_configs[key].get("type") or str,
)
else:
config = plugin_configs[key]
Config.add_plugin_config(
matcher.plugin_name,
key,
config.value,
name=config.name,
help_=config.help,
default_value=config.default_value,
_override=True,
type=config.type or str,
)
elif plugin_configs := _data.get(matcher.plugin_name):
for key in plugin_configs.configs:
Config.add_plugin_config(
matcher.plugin_name,
key,
plugin_configs[key].get("value"),
help_=plugin_configs[key].get("help"),
default_value=plugin_configs[key].get("default_value"),
plugin_configs.configs[key].value,
help_=plugin_configs.configs[key].help,
default_value=plugin_configs.configs[key].default_value,
_override=True,
type=plugin_configs.configs[key].type,
)
else:
Config.add_plugin_config(
matcher.plugin_name, key, plugin_configs[key]
)
elif plugin_configs := _data.get(matcher.plugin_name):
for key in plugin_configs:
Config.add_plugin_config(
matcher.plugin_name,
key,
plugin_configs[key]["value"],
help_=plugin_configs[key]["help"],
default_value=plugin_configs[key]["default_value"],
_override=True,
)
if not Config.is_empty():
Config.save()
_data = round_trip_load(open(plugins2config_file, encoding="utf8"))
@ -96,7 +110,7 @@ def _replace_config():
# 数据替换
for plugin in Config.keys():
_tmp_data[plugin] = {}
for k in Config[plugin].keys():
for k in Config[plugin].configs.keys():
try:
if _data.get(plugin) and k in _data[plugin].keys():
Config.set_config(plugin, k, _data[plugin][k])
@ -126,14 +140,14 @@ def _replace_config():
rst = ""
plugin_name = None
try:
plugin_data = Config.get(plugin)
for x in list(Config.get(plugin).keys()):
try:
_x = plugin_data[x].get("name")
if _x:
plugin_name = _x
except AttributeError:
pass
if config_group := Config.get(plugin):
for key in list(config_group.configs.keys()):
try:
if config := config_group.configs[key]:
if config.name:
plugin_name = config.name
except AttributeError:
pass
except (KeyError, AttributeError):
plugin_name = None
if not plugin_name:
@ -149,7 +163,7 @@ def _replace_config():
)
rst += plugin_name + "\n"
for k in _data[plugin].keys():
rst += f'{k}: {Config[plugin][k]["help"]}' + "\n"
rst += f"{k}: {Config[plugin].configs[k].help}" + "\n"
_data[plugin].yaml_set_start_comment(rst[:-1], indent=2)
with open(Path() / "configs" / "config.yaml", "w", encoding="utf8") as wf:
round_trip_dump(_data, wf, Dumper=yaml.RoundTripDumper, allow_unicode=True)

View File

@ -25,7 +25,12 @@ __zx_plugin_name__ = "好友群聊处理请求 [Hidden]"
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_configs__ = {
"AUTO_ADD_FRIEND": {"value": False, "help": "是否自动同意好友添加", "default_value": False}
"AUTO_ADD_FRIEND": {
"value": False,
"help": "是否自动同意好友添加",
"default_value": False,
"type": bool,
}
}
friend_req = on_request(priority=5, block=True)

View File

@ -1,5 +1,5 @@
import random
from typing import Any, Tuple
from typing import Any, List, Tuple
from nonebot import on_command, on_regex
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
@ -39,6 +39,7 @@ __plugin_configs__ = {
"value": ["", "", "", ""],
"help": "昵称所屏蔽的关键词,已设置的昵称会被替换为 *,未设置的昵称会在设置时提示",
"default_value": None,
"type": List[str],
}
}

View File

@ -10,33 +10,18 @@ driver: Driver = nonebot.get_driver()
Config.add_plugin_config(
"shop", "IMPORT_DEFAULT_SHOP_GOODS", True, help_="导入商店自带的三个商品", default_value=True
"shop",
"IMPORT_DEFAULT_SHOP_GOODS",
True,
help_="导入商店自带的三个商品",
default_value=True,
type=bool,
)
nonebot.load_plugins(str(Path(__file__).parent.resolve()))
@shop_register(
name=("好感度双倍加持卡Ⅰ", "好感度双倍加持卡Ⅱ", "好感度双倍加持卡Ⅲ"),
price=(30, 150, 250),
des=(
"下次签到双倍好感度概率 + 10%(谁才是真命天子?)(同类商品将覆盖)",
"下次签到双倍好感度概率 + 20%(平平庸庸)(同类商品将覆盖)",
"下次签到双倍好感度概率 + 30%(金币才是真命天子!)(同类商品将覆盖)",
),
load_status=bool(Config.get_config("shop", "IMPORT_DEFAULT_SHOP_GOODS")),
icon=(
"favorability_card_1.png",
"favorability_card_2.png",
"favorability_card_3.png",
),
**{"好感度双倍加持卡_prob": 0.1, "好感度双倍加持卡Ⅱ_prob": 0.2, "好感度双倍加持卡Ⅲ_prob": 0.3},
)
async def sign_card(user_id: int, group_id: int):
pass
@driver.on_bot_connect
async def _():
await shop_register.load_register()

View File

@ -30,8 +30,8 @@ __plugin_cmd__ = [
__plugin_version__ = 0.2
__plugin_author__ = "HibiKier"
__plugin_configs__ = {
"AUTO_RELOAD": {"value": False, "help": "自动重载配置文件", "default_value": False},
"AUTO_RELOAD_TIME": {"value": 180, "help": "控制自动重载配置文件时长", "default_value": 180},
"AUTO_RELOAD": {"value": False, "help": "自动重载配置文件", "default_value": False, "type": bool},
"AUTO_RELOAD_TIME": {"value": 180, "help": "控制自动重载配置文件时长", "default_value": 180, "type": int},
}

View File

@ -1,11 +1,53 @@
import copy
from pathlib import Path
from typing import Any, Optional, Union
from typing import Any, Callable, Dict, Optional, Type, Union
import cattrs
from pydantic import BaseModel
from ruamel import yaml
from ruamel.yaml import YAML
from ruamel.yaml.scanner import ScannerError
from services.log import logger
class Config(BaseModel):
"""
配置项
"""
value: Any
"""配置项值"""
name: Optional[str]
"""插件名称"""
help: Optional[str]
"""配置注解"""
default_value: Optional[Any] = None
"""默认值"""
level_module: Optional[str]
"""受权限模块"""
type: Any = None
"""参数类型"""
arg_parser: Optional[Callable] = None
"""参数解析"""
class ConfigGroup(BaseModel):
"""
配置组
"""
module: str
"""模块名"""
configs: Dict[str, Config] = {}
"""配置项列表"""
class NoSuchConfig(Exception):
pass
class ConfigsManager:
"""
@ -13,35 +55,25 @@ class ConfigsManager:
"""
def __init__(self, file: Path):
self._data: dict = {}
self._data: Dict[str, ConfigGroup] = {}
self._simple_data: dict = {}
self._admin_level_data = []
self._simple_file = Path() / "configs" / "config.yaml"
_yaml = YAML()
if file:
file.parent.mkdir(exist_ok=True, parents=True)
self.file = file
_yaml = YAML()
if file.exists():
with open(file, "r", encoding="utf8") as f:
self._data = _yaml.load(f)
if not self._data:
self.file.unlink()
raise ValueError(
"配置文件为空!\n"
"***********************************************************\n"
"****** 配置文件 plugins2config.yaml 为空,已删除,请重启 ******\n"
"***********************************************************"
)
if self._simple_file.exists():
try:
with open(self._simple_file, "r", encoding="utf8") as f:
self._simple_data = _yaml.load(f)
except ScannerError as e:
raise ScannerError(
f"{e}\n**********************************************\n"
f"****** 可能为config.yaml配置文件填写不规范 ******\n"
f"**********************************************"
)
self.load_data()
if self._simple_file.exists():
try:
with open(self._simple_file, "r", encoding="utf8") as f:
self._simple_data = _yaml.load(f)
except ScannerError as e:
raise ScannerError(
f"{e}\n**********************************************\n"
f"****** 可能为config.yaml配置文件填写不规范 ******\n"
f"**********************************************"
)
def add_plugin_config(
self,
@ -52,6 +84,8 @@ class ConfigsManager:
name: Optional[str] = None,
help_: Optional[str] = None,
default_value: Optional[Any] = None,
type: Optional[Type] = str,
arg_parser: Optional[Callable] = None,
_override: bool = False,
):
"""
@ -62,41 +96,49 @@ class ConfigsManager:
:param name: 插件名称
:param help_: 配置注解
:param default_value: 默认值
:param _override: 覆盖
:param _override: 强制覆盖值
"""
if (
not (module in self._data.keys() and self._data[module].get(key))
or _override
):
if not module or not key:
raise ValueError("add_plugin_config: module和key不能为为空")
if module in self._data and (config := self._data[module].configs.get(key)):
config.help = help_
config.arg_parser = arg_parser
config.type = type
if _override:
config.value = value
config.name = name
config.default_value = default_value
else:
_module = None
if ":" in module:
module = module.split(":")
_module = module[-1]
module = module[0]
module_split = module.split(":")
if len(module_split) < 2:
raise ValueError(f"module: {module} 填写错误")
_module = module_split[-1]
module = module_split[0]
if "[LEVEL]" in key and _module:
key = key.replace("[LEVEL]", "").strip()
self._admin_level_data.append((_module, value))
if self._data.get(module) is None:
self._data[module] = {}
key = key.upper()
self._data[module][key] = {
"value": value,
"name": name.strip() if isinstance(name, str) else name,
"help": help_.strip() if isinstance(help_, str) else help_,
"default_value": default_value,
"level_module": _module,
}
if not self._data.get(module):
self._data[module] = ConfigGroup(module=module)
self._data[module].configs[key] = Config(
value=value,
name=name,
help=help_,
default_value=default_value,
level_module=_module,
type=type,
)
def remove_plugin_config(self, module: str):
"""
为插件删除一个配置
:param module: 模块名
"""
if module in self._data.keys():
del self._data[module]
self.save()
def set_config(self, module: str, key: str, value: Any, auto_save: bool = False, save_simple_data: bool = True):
def set_config(
self,
module: str,
key: str,
value: Any,
auto_save: bool = False,
save_simple_data: bool = True,
):
"""
设置配置值
:param module: 模块名
@ -105,40 +147,16 @@ class ConfigsManager:
:param auto_save: 自动保存
:param save_simple_data: 保存至config.yaml
"""
if module in self._data.keys():
if module in self._data:
if (
self._data[module].get(key) is not None
and self._data[module][key] != value
self._data[module].configs.get(key)
and self._data[module].configs[key] != value
):
self._data[module][key]["value"] = value
self._data[module].configs[key].value = value
self._simple_data[module][key] = value
if auto_save:
self.save(save_simple_data=save_simple_data)
def set_help(self, module: str, key: str, help_: str):
"""
设置配置注释
:param module: 模块名
:param key: 配置名称
:param help_: 注释文本
"""
if module in self._data.keys():
if self._data[module].get(key) is not None:
self._data[module][key]["help"] = help_
self.save()
def set_default_value(self, module: str, key: str, value: Any):
"""
设置配置默认值
:param module: 模块名
:param key: 配置名称
:param value:
"""
if module in self._data.keys():
if self._data[module].get(key) is not None:
self._data[module][key]["default_value"] = value
self.save()
def get_config(
self, module: str, key: str, default: Optional[Any] = None
) -> Optional[Any]:
@ -148,37 +166,68 @@ class ConfigsManager:
:param key: 配置名称
:param default: 没有key值内容的默认返回值
"""
logger.debug(
f"尝试获取配置 MODULE: [<u><y>{module}</y></u>] | KEY: [<u><y>{key}</y></u>]"
)
key = key.upper()
value = None
if module in self._data.keys():
for key in [key, f"{key} [LEVEL]"]:
if self._data[module].get(key) is not None:
if self._data[module][key]["value"] is None:
return self._data[module][key]["default_value"]
return self._data[module][key]["value"]
if default is not None:
return default
return None
config = self._data[module].configs.get(key)
if not config:
config = self._data[module].configs.get(f"{key} [LEVEL]")
if not config:
raise NoSuchConfig(f"未查询到配置项 MODULE: [ {module} ] | KEY: [ {key} ]")
if config.arg_parser:
value = config.arg_parser(value or config.default_value)
else:
try:
if config.value is not None:
value = (
cattrs.structure(config.value, config.type)
if config.type
else config.value
)
else:
if config.default_value is not None:
value = (
cattrs.structure(config.default_value, config.type)
if config.type
else config.default_value
)
except Exception as e:
logger.warning(
f"配置项类型转换 MODULE: [<u><y>{module}</y></u>] | KEY: [<u><y>{key}</y></u>]",
e=e,
)
value = config.value or config.default_value
if not value:
value = default
logger.debug(
f"获取配置 MODULE: [<u><y>{module}</y></u>] | KEY: [<u><y>{key}</y></u>] -> [<u><c>{value}</c></u>]"
)
return value
def get_level2module(self, module: str, key: str) -> Optional[str]:
"""
获取指定key所绑定的module一般为权限等级
获取指定key所绑定的module,一般为权限等级
:param module: 模块名
:param key: 配置名称
:return:
"""
if self._data.get(module) is not None:
if self._data[module].get(key) is not None:
return self._data[module][key].get("level_module")
if config := self._data[module].configs.get(key):
return config.level_module
def get(self, key: str):
def get(self, key: str) -> Optional[ConfigGroup]:
"""
获取插件配置数据
:param key: 名称
"""
if key in self._data.keys():
return self._data[key]
return self._data.get(key)
def save(self, path: Union[str, Path] = None, save_simple_data: bool = False):
def save(
self, path: Optional[Union[str, Path]] = None, save_simple_data: bool = False
):
"""
保存数据
:param path: 路径
@ -193,10 +242,17 @@ class ConfigsManager:
Dumper=yaml.RoundTripDumper,
allow_unicode=True,
)
path = path if path else self.file
path = path or self.file
data = {}
for module in self._data:
data[module] = {}
for config in self._data[module].configs:
value = self._data[module].configs[config].dict()
del value["type"]
data[module][config] = value
with open(path, "w", encoding="utf8") as f:
yaml.dump(
self._data, f, indent=2, Dumper=yaml.RoundTripDumper, allow_unicode=True
data, f, indent=2, Dumper=yaml.RoundTripDumper, allow_unicode=True
)
def reload(self):
@ -209,16 +265,46 @@ class ConfigsManager:
self._simple_data = _yaml.load(f)
for key in self._simple_data.keys():
for k in self._simple_data[key].keys():
self._data[key][k]["value"] = self._simple_data[key][k]
self._data[key].configs[k].value = self._simple_data[key][k]
self.save()
def load_data(self):
"""
加载数据
Raises:
ValueError: _description_
"""
if self.file.exists():
_yaml = YAML()
with open(self.file, "r", encoding="utf8") as f:
temp_data = _yaml.load(f)
if not temp_data:
self.file.unlink()
raise ValueError(
"配置文件为空!\n"
"***********************************************************\n"
"****** 配置文件 plugins2config.yaml 为空,已删除,请重启 ******\n"
"***********************************************************"
)
count = 0
for module in temp_data:
config_group = ConfigGroup(module=module)
for config in temp_data[module]:
config_group.configs[config] = Config(**temp_data[module][config])
count += 1
self._data[module] = config_group
logger.info(
f"加载配置完成,共加载 <u><y>{len(temp_data)}</y></u> 个配置组及对应 <u><y>{count}</y></u> 个配置项"
)
def get_admin_level_data(self):
"""
获取管理插件等级
"""
return self._admin_level_data
def get_data(self):
def get_data(self) -> Dict[str, ConfigGroup]:
return copy.deepcopy(self._data)
def is_empty(self) -> bool:

View File

@ -1,3 +1,5 @@
from typing import List
from nonebot import on_message
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
from nonebot.rule import to_me
@ -22,12 +24,18 @@ __plugin_settings__ = {
"cmd": ["Ai", "ai", "AI", "aI"],
}
__plugin_configs__ = {
"TL_KEY": {"value": [], "help": "图灵Key"},
"ALAPI_AI_CHECK": {"value": False, "help": "是否检测青云客骂娘回复", "default_value": False},
"TL_KEY": {"value": [], "help": "图灵Key", "type": List[str]},
"ALAPI_AI_CHECK": {
"value": False,
"help": "是否检测青云客骂娘回复",
"default_value": False,
"type": bool,
},
"TEXT_FILTER": {
"value": ["", "口交"],
"help": "文本过滤器,将敏感词更改为*",
"default_value": [],
"type": List[str],
},
}
Config.add_plugin_config(

View File

@ -1,14 +1,11 @@
from configs.config import Config
from pathlib import Path
import nonebot
from configs.config import Config
Config.add_plugin_config(
"alapi",
"ALAPI_TOKEN",
None,
help_="在https://admin.alapi.cn/user/login登录后获取token"
"alapi", "ALAPI_TOKEN", None, help_="在https://admin.alapi.cn/user/login登录后获取token"
)
nonebot.load_plugins("plugins/alapi")
nonebot.load_plugins(str(Path(__file__).parent.resolve()))

View File

@ -55,16 +55,19 @@ __plugin_configs__ = {
"value": 5,
"help": "群内bilibili订阅需要管理的权限",
"default_value": 5,
"type": int,
},
"LIVE_MSG_AT_ALL": {
"value": False,
"help": "直播提醒是否AT全体仅在真寻是管理员时生效",
"default_value": False,
"type": bool,
},
"UP_MSG_AT_ALL": {
"value": False,
"help": "UP动态投稿提醒是否AT全体仅在真寻是管理员时生效",
"default_value": False,
"type": bool,
},
}

View File

@ -1,5 +1,5 @@
from datetime import datetime
from typing import Any, Tuple
from typing import Any, List, Tuple
from nonebot import on_command, on_message, on_regex
from nonebot.adapters.onebot.v11 import (
@ -56,7 +56,13 @@ __plugin_settings__ = {
Config.add_plugin_config(
"black_word", "CYCLE_DAYS", 30, name="敏感词检测与惩罚", help_="黑名单词汇记录周期", default_value=30
"black_word",
"CYCLE_DAYS",
30,
name="敏感词检测与惩罚",
help_="黑名单词汇记录周期",
default_value=30,
type=int,
)
Config.add_plugin_config(
@ -65,10 +71,11 @@ Config.add_plugin_config(
[5, 1, 1, 1, 1],
help_="各个级别惩罚的容忍次数依次为1, 2, 3, 4, 5",
default_value=[5, 1, 1, 1, 1],
type=List[int],
)
Config.add_plugin_config(
"black_word", "AUTO_PUNISH", True, help_="是否启动自动惩罚机制", default_value=True
"black_word", "AUTO_PUNISH", True, help_="是否启动自动惩罚机制", default_value=True, type=bool
)
# Config.add_plugin_config(
@ -81,6 +88,7 @@ Config.add_plugin_config(
360,
help_="Union[int, List[int, int]]Ban时长分钟四级惩罚可以为指定数字或指定列表区间(随机),例如 [30, 360]",
default_value=360,
type=int,
)
Config.add_plugin_config(
@ -89,6 +97,7 @@ Config.add_plugin_config(
7,
help_="Union[int, List[int, int]]Ban时长三级惩罚可以为指定数字或指定列表区间(随机),例如 [7, 30]",
default_value=360,
type=int,
)
Config.add_plugin_config(
@ -105,6 +114,7 @@ Config.add_plugin_config(
True,
help_="自动提级机制,当周期内处罚次数大于某一特定值就提升惩罚等级",
default_value=True,
type=bool,
)
Config.add_plugin_config(
@ -113,6 +123,7 @@ Config.add_plugin_config(
3,
help_="在CYCLE_DAYS周期内触发指定惩罚次数后提升惩罚等级",
default_value=3,
type=int,
)
Config.add_plugin_config(
@ -121,6 +132,7 @@ Config.add_plugin_config(
False,
help_="当未检测到已收录的敏感词时开启ALAPI文本检测并将疑似文本发送给超级用户",
default_value=False,
type=bool,
)
Config.add_plugin_config(
@ -129,6 +141,7 @@ Config.add_plugin_config(
True,
help_="当文本包含任意敏感词时停止向下级插件传递即不触发ai",
default_value=True,
type=bool,
)
message_matcher = on_message(priority=1, block=False)

View File

@ -1,13 +1,16 @@
from nonebot import on_command
from .data_source import get_bt_info
from services.log import logger
from nonebot.adapters.onebot.v11 import PrivateMessageEvent, Message
from nonebot.adapters.onebot.v11.permission import PRIVATE
from asyncio.exceptions import TimeoutError
from utils.utils import is_number
from nonebot.params import CommandArg, ArgStr
from nonebot import on_command
from nonebot.adapters.onebot.v11 import Message, PrivateMessageEvent
from nonebot.adapters.onebot.v11.permission import PRIVATE
from nonebot.params import ArgStr, CommandArg
from nonebot.typing import T_State
from services.log import logger
from utils.utils import is_number
from .data_source import get_bt_info
__zx_plugin_name__ = "磁力搜索"
__plugin_usage__ = """
usage
@ -34,6 +37,7 @@ __plugin_configs__ = {
"value": 10,
"help": "单次BT搜索返回最大消息数量",
"default_value": 10,
"type": int,
}
}

View File

@ -1,16 +1,18 @@
from nonebot.adapters.onebot.v11 import Bot, MessageEvent
from nonebot.permission import SUPERUSER
from nonebot import on_command
from .data_source import check_update, get_latest_version_data
from services.log import logger
from utils.utils import scheduler, get_bot
from pathlib import Path
from configs.config import NICKNAME, Config
from nonebot.rule import to_me
from nonebot.params import ArgStr
import platform
import os
import platform
from pathlib import Path
from nonebot import on_command
from nonebot.adapters.onebot.v11 import Bot, MessageEvent
from nonebot.params import ArgStr
from nonebot.permission import SUPERUSER
from nonebot.rule import to_me
from configs.config import NICKNAME, Config
from services.log import logger
from utils.utils import get_bot, scheduler
from .data_source import check_update, get_latest_version_data
__zx_plugin_name__ = "自动更新 [Superuser]"
__plugin_usage__ = """
@ -29,12 +31,14 @@ __plugin_configs__ = {
"value": True,
"help": "真寻是否检测版本状态",
"default": True,
"type": bool,
},
"AUTO_UPDATE_ZHENXUN": {
"value": False,
"help": "真寻是否自动检查更新",
"default": False,
}
"type": bool,
},
}
update_zhenxun = on_command("检查更新真寻", permission=SUPERUSER, priority=1, block=True)
@ -66,9 +70,7 @@ async def _(bot: Bot, event: MessageEvent):
)
else:
if code == 200:
await bot.send_private_msg(
user_id=event.user_id, message=f"更新完毕,请重启真寻...."
)
await bot.send_private_msg(user_id=event.user_id, message=f"更新完毕,请重启真寻....")
@restart.got("flag", prompt=f"确定是否重启{NICKNAME}?确定请回复[是|好|确定](重启失败咱们将失去联系,请谨慎!)")
@ -78,6 +80,7 @@ async def _(flag: str = ArgStr("flag")):
open("is_restart", "w")
if str(platform.system()).lower() == "windows":
import sys
python = sys.executable
os.execl(python, python, *sys.argv)
else:
@ -109,8 +112,7 @@ async def _():
bot = get_bot()
await bot.send_private_msg(
user_id=int(list(bot.config.superusers)[0]),
message=f"检测到真寻版本更新\n"
f"当前版本:{_version},最新版本:{latest_version}",
message=f"检测到真寻版本更新\n" f"当前版本:{_version},最新版本:{latest_version}",
)
if Config.get_config("check_zhenxun_update", "AUTO_UPDATE_ZHENXUN"):
try:

View File

@ -1,15 +1,16 @@
from typing import Tuple, Any
import time
from typing import Any, Tuple
from nonebot import on_regex
from nonebot.params import RegexGroup
from configs.path_config import TEMP_PATH
from nonebot.adapters.onebot.v11 import Bot, MessageEvent
import time
from utils.http_utils import AsyncHttpx
from utils.message_builder import image
from services.log import logger
from utils.manager import withdraw_message_manager
from nonebot.params import RegexGroup
from configs.config import Config
from configs.path_config import TEMP_PATH
from services.log import logger
from utils.http_utils import AsyncHttpx
from utils.manager import withdraw_message_manager
from utils.message_builder import image
__zx_plugin_name__ = "coser"
__plugin_usage__ = """
@ -35,6 +36,7 @@ __plugin_configs__ = {
"value": (0, 1),
"help": "自动撤回参1延迟撤回色图时间(秒)0 为关闭 | 参2监控聊天类型0(私聊) 1(群聊) 2(群聊+私聊)",
"default_value": (0, 1),
"type": Tuple[int, int],
},
}
@ -49,7 +51,7 @@ url = "https://picture.yinux.workers.dev"
async def _(event: MessageEvent, reg_group: Tuple[Any, ...] = RegexGroup()):
num = reg_group[0] or 1
for _ in range(int(num)):
path = TEMP_PATH / f'cos_cc{int(time.time())}.jpeg'
path = TEMP_PATH / f"cos_cc{int(time.time())}.jpeg"
try:
await AsyncHttpx.download_file(url, path)
msg_id = await coser.send(image(path))

View File

@ -1,9 +1,11 @@
import nonebot
from pathlib import Path
import nonebot
from nonebot.log import logger
from pydantic import BaseModel, Extra, ValidationError
from configs.config import Config as AConfig
from configs.path_config import IMAGE_PATH, DATA_PATH
from configs.path_config import DATA_PATH, IMAGE_PATH
try:
import ujson as json
@ -147,9 +149,20 @@ for game_flag, game_name in zip(
"FGO_FLAG",
"ONMYOJI_FLAG",
"PCR_TAI",
"BA_FLAG"
"BA_FLAG",
],
[
"明日方舟",
"原神",
"赛马娘",
"坎公骑冠剑",
"公主连结",
"碧蓝航线",
"命运-冠位指定FGO",
"阴阳师",
"pcr台服卡池",
"碧蓝档案",
],
["明日方舟", "原神", "赛马娘", "坎公骑冠剑", "公主连结", "碧蓝航线", "命运-冠位指定FGO", "阴阳师", "pcr台服卡池", "碧蓝档案"],
):
AConfig.add_plugin_config(
"draw_card",
@ -158,9 +171,10 @@ for game_flag, game_name in zip(
name="游戏抽卡",
help_=f"{game_name} 抽卡开关",
default_value=True,
type=bool,
)
AConfig.add_plugin_config(
"draw_card", "SEMAPHORE", 5, help_=f"异步数据下载数量限制", default_value=5
"draw_card", "SEMAPHORE", 5, help_=f"异步数据下载数量限制", default_value=5, type=int
)

View File

@ -1,11 +1,13 @@
from nonebot import on_regex
from services.log import logger
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, MessageEvent
from nonebot.typing import T_State
from utils.utils import scheduler, get_bot
from .data_source import get_epic_free
from utils.manager import group_manager
from configs.config import Config
from services.log import logger
from utils.manager import group_manager
from utils.utils import get_bot, scheduler
from .data_source import get_epic_free
__zx_plugin_name__ = "epic免费游戏"
__plugin_usage__ = """
@ -31,6 +33,7 @@ Config.add_plugin_config(
True,
help_="被动 epic免费游戏 进群默认开关状态",
default_value=True,
type=bool,
)
epic = on_regex("^epic$", priority=5, block=True)

View File

@ -1,16 +1,16 @@
from utils.image_utils import get_img_hash
from nonebot.adapters.onebot.v11.permission import GROUP
from configs.path_config import TEMP_PATH
import random
from utils.message_builder import image
from nonebot import on_message
from utils.utils import get_message_img, get_message_text
from nonebot.adapters.onebot.v11 import GroupMessageEvent
from configs.config import Config
from utils.http_utils import AsyncHttpx
from services.log import logger
from configs.config import NICKNAME
from nonebot import on_message
from nonebot.adapters.onebot.v11 import GroupMessageEvent
from nonebot.adapters.onebot.v11.permission import GROUP
from configs.config import NICKNAME, Config
from configs.path_config import TEMP_PATH
from services.log import logger
from utils.http_utils import AsyncHttpx
from utils.image_utils import get_img_hash
from utils.message_builder import image
from utils.utils import get_message_img, get_message_text
__zx_plugin_name__ = "复读"
__plugin_usage__ = """
@ -23,14 +23,15 @@ __plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_task__ = {"fudu": "复读"}
__plugin_configs__ = {
"FUDU_PROBABILITY": {"value": 0.7, "help": "复读概率", "default_value": 0.7}
"FUDU_PROBABILITY": {
"value": 0.7,
"help": "复读概率",
"default_value": 0.7,
"type": float,
}
}
Config.add_plugin_config(
"_task",
"DEFAULT_FUDU",
True,
help_="被动 复读 进群默认开关状态",
default_value=True,
"_task", "DEFAULT_FUDU", True, help_="被动 复读 进群默认开关状态", default_value=True, type=bool
)
@ -90,7 +91,7 @@ async def _(event: GroupMessageEvent):
if not img and not msg:
return
if img:
img_hash = await get_fudu_img_hash(img[0],event.group_id)
img_hash = await get_fudu_img_hash(img[0], event.group_id)
else:
img_hash = ""
add_msg = msg + "|-|" + img_hash
@ -107,7 +108,7 @@ async def _(event: GroupMessageEvent):
) and not _fudu_list.is_repeater(event.group_id):
if random.random() < 0.2:
if msg.endswith("打断施法!"):
await fudu.finish("[[_task|fudu]]打断" + msg)
await fudu.finish("[[_task|fudu]]打断" + msg)
else:
await fudu.finish("[[_task|fudu]]打断施法!")
_fudu_list.set_repeater(event.group_id)

View File

@ -1,7 +1,8 @@
from configs.config import Config
from configs.path_config import IMAGE_PATH
from nonebot import on_command
from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent
from configs.config import Config
from configs.path_config import IMAGE_PATH
from services.log import logger
from utils.manager import group_manager
from utils.message_builder import image
@ -35,6 +36,7 @@ Config.add_plugin_config(
True,
help_="被动 原神黄历提醒 进群默认开关状态",
default_value=True,
type=bool,
)
almanac = on_command("原神黄历", priority=5, block=True)

View File

@ -37,11 +37,13 @@ __plugin_configs__ = {
"value": True,
"help": "当请求连续三次失败时,关闭用户的树脂提醒",
"default_value": True,
"type": bool,
},
"CUSTOM_RESIN_OVERFLOW_REMIND": {
"value": 20,
"help": "自定义树脂溢出指定数量时的提醒,空值是为关闭",
"default_value": None,
"type": int,
},
}

View File

@ -1,8 +1,10 @@
from configs.config import Config
from configs.path_config import IMAGE_PATH
from pathlib import Path
from typing import List, Tuple
import nonebot
from configs.config import Config
from configs.path_config import IMAGE_PATH
Config.add_plugin_config(
"image_management",
@ -11,6 +13,7 @@ Config.add_plugin_config(
name="图库操作",
help_="公开图库列表,可自定义添加 [如果含有send_setu插件请不要添加色图库]",
default_value=[],
type=List[str],
)
Config.add_plugin_config(
@ -20,6 +23,7 @@ Config.add_plugin_config(
name="图库操作",
help_="自动撤回参1延迟撤回发送图库图片的时间(秒)0 为关闭 | 参2监控聊天类型0(私聊) 1(群聊) 2(群聊+私聊)",
default_value=(0, 1),
type=Tuple[int, int],
)
Config.add_plugin_config(
@ -28,6 +32,7 @@ Config.add_plugin_config(
7,
help_="删除图库图片需要的管理员等级",
default_value=7,
type=int,
)
Config.add_plugin_config(
@ -36,6 +41,7 @@ Config.add_plugin_config(
7,
help_="移动图库图片需要的管理员等级",
default_value=7,
type=int,
)
Config.add_plugin_config(
@ -44,6 +50,7 @@ Config.add_plugin_config(
6,
help_="上传图库图片需要的管理员等级",
default_value=6,
type=int,
)
Config.add_plugin_config(
@ -51,11 +58,12 @@ Config.add_plugin_config(
"SHOW_ID",
True,
help_="是否消息显示图片下标id",
default_value=True
default_value=True,
type=bool,
)
(IMAGE_PATH / "image_management").mkdir(parents=True, exist_ok=True)
nonebot.load_plugins("plugins/image_management")
nonebot.load_plugins(str(Path(__file__).parent.resolve()))

View File

@ -13,11 +13,6 @@ from utils.utils import FreqLimiter, cn2py, get_message_text, is_number
from .rule import rule
try:
import ujson as json
except ModuleNotFoundError:
import json
__zx_plugin_name__ = "本地图库"
__plugin_usage__ = f"""
usage
@ -36,16 +31,12 @@ __plugin_settings__ = {
"level": 5,
"default_status": True,
"limit_superuser": False,
"cmd": ["发送图片"] + Config.get_config("image_management", "IMAGE_DIR_LIST"),
"cmd": ["发送图片"] + (Config.get_config("image_management", "IMAGE_DIR_LIST") or []),
}
__plugin_resources__ = {"pa": IMAGE_PATH / "pa"}
Config.add_plugin_config(
"_task",
"DEFAULT_PA",
True,
help_="被动 爬 进群默认开关状态",
default_value=True,
"_task", "DEFAULT_PA", True, help_="被动 爬 进群默认开关状态", default_value=True, type=int
)
_flmt = FreqLimiter(1)

View File

@ -1,19 +1,20 @@
import time
from io import BytesIO
from typing import Any, Dict, Tuple
import imagehash
from PIL import Image
from nonebot import on_message, on_command
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, ActionFailed
from nonebot import on_command, on_message
from nonebot.adapters.onebot.v11 import ActionFailed, Bot, GroupMessageEvent, Message
from nonebot.adapters.onebot.v11.permission import GROUP
from utils.utils import is_number, get_message_img, get_message_text
from configs.path_config import DATA_PATH, TEMP_PATH
from utils.image_utils import get_img_hash
from services.log import logger
from nonebot.params import Command, CommandArg
from PIL import Image
from configs.config import NICKNAME, Config
from configs.path_config import DATA_PATH, TEMP_PATH
from services.log import logger
from utils.http_utils import AsyncHttpx
from nonebot.params import CommandArg, Command
from typing import Tuple, Dict, Any
import time
from utils.image_utils import get_img_hash
from utils.utils import get_message_img, get_message_text, is_number
try:
import ujson as json
@ -38,13 +39,29 @@ __plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {"admin_level": Config.get_config("mute", "MUTE_LEVEL")}
__plugin_configs__ = {
"MUTE_LEVEL [LEVEL]": {"value": 5, "help": "更改禁言设置的管理权限", "default_value": 5},
"MUTE_DEFAULT_COUNT": {"value": 10, "help": "刷屏禁言默认检测次数", "default_value": 10},
"MUTE_DEFAULT_TIME": {"value": 7, "help": "刷屏检测默认规定时间", "default_value": 7},
"MUTE_LEVEL [LEVEL]": {
"value": 5,
"help": "更改禁言设置的管理权限",
"default_value": 5,
"type": int,
},
"MUTE_DEFAULT_COUNT": {
"value": 10,
"help": "刷屏禁言默认检测次数",
"default_value": 10,
"type": int,
},
"MUTE_DEFAULT_TIME": {
"value": 7,
"help": "刷屏检测默认规定时间",
"default_value": 7,
"type": int,
},
"MUTE_DEFAULT_DURATION": {
"value": 10,
"help": "刷屏检测默禁言时长(分钟)",
"default_value": 10,
"type": int,
},
}
@ -75,7 +92,9 @@ def save_data():
async def download_img_and_hash(url) -> str:
return str(imagehash.average_hash(Image.open(BytesIO((await AsyncHttpx.get(url)).content))))
return str(
imagehash.average_hash(Image.open(BytesIO((await AsyncHttpx.get(url)).content)))
)
mute_dict = {}

View File

@ -1,24 +1,27 @@
from typing import Type, Tuple, Any
from nonebot import on_command
from nonebot.matcher import Matcher
from utils.utils import scheduler, is_number
from nonebot.adapters.onebot.v11.permission import GROUP
from nonebot.typing import T_State
from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent, Message
from nonebot.permission import SUPERUSER
import random
from nonebot.plugin import MatcherGroup
from configs.path_config import IMAGE_PATH
from typing import Any, Tuple, Type
from nonebot import on_command
from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message, MessageEvent
from nonebot.adapters.onebot.v11.permission import GROUP
from nonebot.matcher import Matcher
from nonebot.params import CommandArg, RegexGroup
from nonebot.permission import SUPERUSER
from nonebot.plugin import MatcherGroup
from nonebot.typing import T_State
from configs.config import Config
from configs.path_config import IMAGE_PATH
from utils.utils import is_number, scheduler
from .open_cases_c import (
open_case,
total_open_statistics,
group_statistics,
my_knifes_name,
open_shilian_case,
open_case,
open_multiple_case,
total_open_statistics,
)
from .utils import util_get_buff_price, util_get_buff_img, update_count_daily
from configs.config import Config
from .utils import reset_count_daily, util_get_buff_img, util_get_buff_price
__zx_plugin_name__ = "开箱"
__plugin_usage__ = """
@ -73,11 +76,17 @@ __plugin_task__ = {"open_case_reset_remind": "每日开箱重置提醒"}
__plugin_cd_limit__ = {"rst": "着什么急啊,慢慢来!"}
__plugin_resources__ = {f"cases": IMAGE_PATH}
__plugin_configs__ = {
"INITIAL_OPEN_CASE_COUNT": {"value": 20, "help": "初始每日开箱次数", "default_value": 20},
"INITIAL_OPEN_CASE_COUNT": {
"value": 20,
"help": "初始每日开箱次数",
"default_value": 20,
"type": int,
},
"EACH_IMPRESSION_ADD_COUNT": {
"value": 3,
"help": "每 * 点好感度额外增加开箱次数",
"default_value": 3,
"type": int,
},
"COOKIE": {
"value": None,
@ -92,6 +101,7 @@ Config.add_plugin_config(
True,
help_="被动 每日开箱重置提醒 进群默认开关状态",
default_value=True,
type=int,
)
cases_name = ["狂牙大行动", "突围大行动", "命悬一线", "裂空", "光谱"]
@ -101,12 +111,12 @@ cases_matcher_group = MatcherGroup(priority=5, permission=GROUP, block=True)
k_open_case = cases_matcher_group.on_command("开箱")
reload_count = cases_matcher_group.on_command("重置开箱",permission=SUPERUSER)
reload_count = cases_matcher_group.on_command("重置开箱", permission=SUPERUSER)
@reload_count.handle()
async def _(event: GroupMessageEvent):
await update_count_daily()
await reset_count_daily()
@k_open_case.handle()
@ -153,11 +163,13 @@ async def _(event: GroupMessageEvent):
)
open_shilian: Type[Matcher] = cases_matcher_group.on_regex("(.*)连开箱(.*)?")
open_multiple: Type[Matcher] = cases_matcher_group.on_regex("(.*)连开箱(.*)?")
@open_shilian.handle()
async def _(event: GroupMessageEvent, state: T_State, reg_group: Tuple[Any, ...] = RegexGroup()):
@open_multiple.handle()
async def _(
event: GroupMessageEvent, state: T_State, reg_group: Tuple[Any, ...] = RegexGroup()
):
num, case_name = reg_group
if is_number(num) or num_dict.get(num):
try:
@ -165,18 +177,18 @@ async def _(event: GroupMessageEvent, state: T_State, reg_group: Tuple[Any, ...]
except KeyError:
num = int(num)
if num > 30:
await open_shilian.finish("开箱次数不要超过30啊笨蛋", at_sender=True)
await open_multiple.finish("开箱次数不要超过30啊笨蛋", at_sender=True)
if num < 0:
await open_shilian.finish("再负开箱就扣你明天开箱数了!", at_sender=True)
await open_multiple.finish("再负开箱就扣你明天开箱数了!", at_sender=True)
else:
await open_shilian.finish("必须要是数字切不要超过30啊笨蛋中文也可", at_sender=True)
await open_multiple.finish("必须要是数字切不要超过30啊笨蛋中文也可", at_sender=True)
case_name = case_name.replace("武器箱", "").strip()
if not case_name:
case_name = random.choice(cases_name)
elif case_name not in cases_name:
await open_shilian.finish("武器箱未收录!", at_sender=True)
await open_shilian.finish(
await open_shilian_case(event.user_id, event.group_id, case_name, num),
await open_multiple.finish("武器箱未收录!", at_sender=True)
await open_multiple.finish(
await open_multiple_case(event.user_id, event.group_id, case_name, num),
at_sender=True,
)
@ -220,7 +232,9 @@ update_price = on_command("更新开箱价格", priority=1, permission=SUPERUSER
@update_price.handle()
async def _(event: MessageEvent, arg: Message = CommandArg()):
await update_price.send(await util_get_buff_price(arg.extract_plain_text().strip() or "狂牙大行动"))
await update_price.send(
await util_get_buff_price(arg.extract_plain_text().strip() or "狂牙大行动")
)
update_img = on_command("更新开箱图片", priority=1, permission=SUPERUSER, block=True)
@ -228,7 +242,9 @@ update_img = on_command("更新开箱图片", priority=1, permission=SUPERUSER,
@update_img.handle()
async def _(event: MessageEvent, arg: Message = CommandArg()):
await update_img.send(await util_get_buff_img(arg.extract_plain_text().strip() or "狂牙大行动"))
await update_img.send(
await util_get_buff_img(arg.extract_plain_text().strip() or "狂牙大行动")
)
# 重置开箱
@ -238,4 +254,4 @@ async def _(event: MessageEvent, arg: Message = CommandArg()):
minute=1,
)
async def _():
await update_count_daily()
await reset_count_daily()

View File

@ -1,5 +1,9 @@
import random
import pypinyin
from typing import List, Tuple
from services.log import logger
from .models.buff_skin import BuffSkin
BLUE = 0.7981
BLUE_ST = 0.0699
@ -29,152 +33,360 @@ BATTLE_SCARED_S = 0.45
BATTLE_SCARED_E = 0.99999
# 狂牙大行动
KUANGYADAXINGDONG_CASE_KNIFE = ['摩托手套 | 第三特种兵连', '狂牙手套 | 翡翠', '驾驶手套 | 美洲豹女王', '运动手套 | 弹弓', '专业手套 | 老虎精英'
, '专业手套 | 渐变大理石', '运动手套 | 夜行衣', '驾驶手套 | 西装革履', '摩托手套 | 终点线', '摩托手套 | 血压',
'运动手套 | 猩红头巾', '驾驶手套 | 雪豹', '裹手 | 长颈鹿', '驾驶手套 | 绯红列赞', '裹手 | 沙漠头巾',
'专业手套 | 一线特工', '狂牙手套 | 黄色斑纹', '摩托手套 | 小心烟幕弹', '裹手 | 蟒蛇', '裹手 | 警告!',
'狂牙手套 | 精神错乱', '运动手套 | 大型猎物', '狂牙手套 | 针尖', '专业手套 | 陆军少尉长官']
KUANGYADAXINGDONG_CASE_RED = ['M4A1 | 印花集', '格洛克 | 黑色魅影']
KUANGYADAXINGDONG_CASE_PINK = ['FN57 | 童话城堡', 'M4A4 | 赛博', 'USP | 小绿怪']
KUANGYADAXINGDONG_CASE_PURPLE = ['AWP | 亡灵之主', '双持贝瑞塔 | 灾难', '新星 | 一见青心', 'SSG 08 | 抖枪', 'UMP-45 | 金铋辉煌']
KUANGYADAXINGDONG_CASE_BLUE = ['CZ75 | 世仇', 'P90 | 大怪兽RUSH', 'G3SG1 | 血腥迷彩', '加利尔 AR | 破坏者', 'P250 | 污染物',
'M249 | 等高线', 'MP5-SD | 零点行动']
KUANGYADAXINGDONG_CASE_KNIFE = [
"摩托手套 | 第三特种兵连",
"狂牙手套 | 翡翠",
"驾驶手套 | 美洲豹女王",
"运动手套 | 弹弓",
"专业手套 | 老虎精英",
"专业手套 | 渐变大理石",
"运动手套 | 夜行衣",
"驾驶手套 | 西装革履",
"摩托手套 | 终点线",
"摩托手套 | 血压",
"运动手套 | 猩红头巾",
"驾驶手套 | 雪豹",
"裹手 | 长颈鹿",
"驾驶手套 | 绯红列赞",
"裹手 | 沙漠头巾",
"专业手套 | 一线特工",
"狂牙手套 | 黄色斑纹",
"摩托手套 | 小心烟幕弹",
"裹手 | 蟒蛇",
"裹手 | 警告!",
"狂牙手套 | 精神错乱",
"运动手套 | 大型猎物",
"狂牙手套 | 针尖",
"专业手套 | 陆军少尉长官",
]
KUANGYADAXINGDONG_CASE_RED = ["M4A1 | 印花集", "格洛克 | 黑色魅影"]
KUANGYADAXINGDONG_CASE_PINK = ["FN57 | 童话城堡", "M4A4 | 赛博", "USP | 小绿怪"]
KUANGYADAXINGDONG_CASE_PURPLE = [
"AWP | 亡灵之主",
"双持贝瑞塔 | 灾难",
"新星 | 一见青心",
"SSG 08 | 抖枪",
"UMP-45 | 金铋辉煌",
]
KUANGYADAXINGDONG_CASE_BLUE = [
"CZ75 | 世仇",
"P90 | 大怪兽RUSH",
"G3SG1 | 血腥迷彩",
"加利尔 AR | 破坏者",
"P250 | 污染物",
"M249 | 等高线",
"MP5-SD | 零点行动",
]
# 突围大行动
TUWEIDAXINGDONG_CASE_KNIFE = ['蝴蝶刀 | 无涂装', '蝴蝶刀 | 蓝钢', '蝴蝶刀 | 屠夫', '蝴蝶刀 | 森林 DDPAT', '蝴蝶刀 | 北方森林',
'蝴蝶刀 | 狩猎网格', '蝴蝶刀 | 枯焦之色', '蝴蝶刀 | 人工染色', '蝴蝶刀 | 都市伪装', '蝴蝶刀 | 表面淬火',
'蝴蝶刀 | 深红之网', '蝴蝶刀 | 渐变之色', '蝴蝶刀 | 噩梦之夜']
TUWEIDAXINGDONG_CASE_RED = ['P90 | 二西莫夫', 'M4A1 | 次时代']
TUWEIDAXINGDONG_CASE_PINK = ['沙漠之鹰 | 阴谋者', 'FN57 | 狩猎利器', '格洛克 | 水灵']
TUWEIDAXINGDONG_CASE_PURPLE = ['PP-野牛 | 死亡主宰者', 'CZ75 | 猛虎', '新星 | 锦鲤', 'P250 | 超新星']
TUWEIDAXINGDONG_CASE_BLUE = ['MP7 | 都市危机', '内格夫 | 沙漠精英', 'P2000 | 乳白象牙', 'SSG 08 | 无尽深海', 'UMP-45 | 迷之宫']
TUWEIDAXINGDONG_CASE_KNIFE = [
"蝴蝶刀 | 无涂装",
"蝴蝶刀 | 蓝钢",
"蝴蝶刀 | 屠夫",
"蝴蝶刀 | 森林 DDPAT",
"蝴蝶刀 | 北方森林",
"蝴蝶刀 | 狩猎网格",
"蝴蝶刀 | 枯焦之色",
"蝴蝶刀 | 人工染色",
"蝴蝶刀 | 都市伪装",
"蝴蝶刀 | 表面淬火",
"蝴蝶刀 | 深红之网",
"蝴蝶刀 | 渐变之色",
"蝴蝶刀 | 噩梦之夜",
]
TUWEIDAXINGDONG_CASE_RED = ["P90 | 二西莫夫", "M4A1 | 次时代"]
TUWEIDAXINGDONG_CASE_PINK = ["沙漠之鹰 | 阴谋者", "FN57 | 狩猎利器", "格洛克 | 水灵"]
TUWEIDAXINGDONG_CASE_PURPLE = ["PP-野牛 | 死亡主宰者", "CZ75 | 猛虎", "新星 | 锦鲤", "P250 | 超新星"]
TUWEIDAXINGDONG_CASE_BLUE = [
"MP7 | 都市危机",
"内格夫 | 沙漠精英",
"P2000 | 乳白象牙",
"SSG 08 | 无尽深海",
"UMP-45 | 迷之宫",
]
# 命悬一线
MINGXUANYIXIAN_CASE_KNIFE = ['专业手套 | 大腕', '专业手套 | 深红之网', '专业手套 | 渐变之色', '专业手套 | 狩鹿', '九头蛇手套 | 响尾蛇',
'九头蛇手套 | 红树林', '九头蛇手套 | 翡翠色调', '九头蛇手套 | 表面淬火', '摩托手套 | 交运', '摩托手套 | 嘭!',
'摩托手套 | 多边形', '摩托手套 | 玳瑁', '裹手 | 套印', '裹手 | 森林色调', '裹手 | 钴蓝骷髅', '裹手 | 防水布胶带',
'运动手套 | 双栖', '运动手套 | 欧米伽', '运动手套 | 迈阿密风云', '运动手套 | 青铜形态', '驾驶手套 | 墨绿色调',
'驾驶手套 | 王蛇', '驾驶手套 | 蓝紫格子', '驾驶手套 | 超越']
MINGXUANYIXIAN_CASE_RED = ['M4A4 | 黑色魅影', 'MP7 | 血腥运动']
MINGXUANYIXIAN_CASE_PINK = ['AUG | 湖怪鸟', 'AWP | 死神', 'USP | 脑洞大开']
MINGXUANYIXIAN_CASE_PURPLE = ['MAG-7 | SWAG-7', 'UMP-45 | 白狼', '内格夫 | 狮子鱼', '新星 | 狂野六号', '格洛克 | 城里的月光']
MINGXUANYIXIAN_CASE_BLUE = ['FN57 | 焰色反应', 'MP9 | 黑砂', 'P2000 | 都市危机', 'PP-野牛 | 黑夜暴乱', 'R8 左轮手枪 | 稳',
'SG 553 | 阿罗哈', 'XM1014 | 锈蚀烈焰']
MINGXUANYIXIAN_CASE_KNIFE = [
"专业手套 | 大腕",
"专业手套 | 深红之网",
"专业手套 | 渐变之色",
"专业手套 | 狩鹿",
"九头蛇手套 | 响尾蛇",
"九头蛇手套 | 红树林",
"九头蛇手套 | 翡翠色调",
"九头蛇手套 | 表面淬火",
"摩托手套 | 交运",
"摩托手套 | 嘭!",
"摩托手套 | 多边形",
"摩托手套 | 玳瑁",
"裹手 | 套印",
"裹手 | 森林色调",
"裹手 | 钴蓝骷髅",
"裹手 | 防水布胶带",
"运动手套 | 双栖",
"运动手套 | 欧米伽",
"运动手套 | 迈阿密风云",
"运动手套 | 青铜形态",
"驾驶手套 | 墨绿色调",
"驾驶手套 | 王蛇",
"驾驶手套 | 蓝紫格子",
"驾驶手套 | 超越",
]
MINGXUANYIXIAN_CASE_RED = ["M4A4 | 黑色魅影", "MP7 | 血腥运动"]
MINGXUANYIXIAN_CASE_PINK = ["AUG | 湖怪鸟", "AWP | 死神", "USP | 脑洞大开"]
MINGXUANYIXIAN_CASE_PURPLE = [
"MAG-7 | SWAG-7",
"UMP-45 | 白狼",
"内格夫 | 狮子鱼",
"新星 | 狂野六号",
"格洛克 | 城里的月光",
]
MINGXUANYIXIAN_CASE_BLUE = [
"FN57 | 焰色反应",
"MP9 | 黑砂",
"P2000 | 都市危机",
"PP-野牛 | 黑夜暴乱",
"R8 左轮手枪 | 稳",
"SG 553 | 阿罗哈",
"XM1014 | 锈蚀烈焰",
]
LIEKONG_CASE_KNIFE = ['求生匕首 | 无涂装', '求生匕首 | 人工染色', '求生匕首 | 北方森林', '求生匕首 | 夜色', '求生匕首 | 屠夫',
'求生匕首 | 枯焦之色', '求生匕首 | 森林 DDPAT', '求生匕首 | 深红之网', '求生匕首 | 渐变之色', '求生匕首 | 狩猎网格',
'求生匕首 | 蓝钢', '求生匕首 | 表面淬火', '求生匕首 | 都市伪装', '流浪者匕首 | 无涂装', '流浪者匕首 | 人工染色',
'流浪者匕首 | 北方森林', '流浪者匕首 | 夜色', '流浪者匕首 | 屠夫', '流浪者匕首 | 枯焦之色', '流浪者匕首 | 森林 DDPAT',
'流浪者匕首 | 深红之网', '流浪者匕首 | 渐变之色', '流浪者匕首 | 狩猎网格', '流浪者匕首 | 蓝钢', '流浪者匕首 | 表面淬火',
'流浪者匕首 | 都市伪装', '系绳匕首 | 无涂装', '系绳匕首 | 人工染色', '系绳匕首 | 北方森林', '系绳匕首 | 夜色',
'系绳匕首 | 屠夫', '系绳匕首 | 枯焦之色', '系绳匕首 | 森林 DDPAT', '系绳匕首 | 深红之网', '系绳匕首 | 渐变之色',
'系绳匕首 | 狩猎网格', '系绳匕首 | 蓝钢', '系绳匕首 | 表面淬火', '系绳匕首 | 都市伪装', '骷髅匕首 | 无涂装',
'骷髅匕首 | 人工染色', '骷髅匕首 | 北方森林', '骷髅匕首 | 夜色', '骷髅匕首 | 屠夫', '骷髅匕首 | 枯焦之色',
'骷髅匕首 | 森林 DDPAT', '骷髅匕首 | 深红之网', '骷髅匕首 | 渐变之色', '骷髅匕首 | 狩猎网格', '骷髅匕首 | 蓝钢',
'骷髅匕首 | 表面淬火', '骷髅匕首 | 都市伪装']
LIEKONG_CASE_RED = ['AK-47 | 阿努比斯军团', '沙漠之鹰 | 印花集']
LIEKONG_CASE_PINK = ['M4A4 | 齿仙', 'XM1014 | 埋葬之影', '格洛克 | 摩登时代']
LIEKONG_CASE_PURPLE = ['加利尔 AR | 凤凰商号', 'Tec-9 | 兄弟连', 'MP5-SD | 猛烈冲锋', 'MAG-7 | 北冥有鱼', 'MAC-10 | 魅惑']
LIEKONG_CASE_BLUE = ['内格夫 | 飞羽', 'SSG 08 | 主机001', 'SG 553 | 锈蚀之刃', 'PP-野牛 | 神秘碑文', 'P90 | 集装箱', 'P250 | 卡带',
'P2000 | 盘根错节']
LIEKONG_CASE_KNIFE = [
"求生匕首 | 无涂装",
"求生匕首 | 人工染色",
"求生匕首 | 北方森林",
"求生匕首 | 夜色",
"求生匕首 | 屠夫",
"求生匕首 | 枯焦之色",
"求生匕首 | 森林 DDPAT",
"求生匕首 | 深红之网",
"求生匕首 | 渐变之色",
"求生匕首 | 狩猎网格",
"求生匕首 | 蓝钢",
"求生匕首 | 表面淬火",
"求生匕首 | 都市伪装",
"流浪者匕首 | 无涂装",
"流浪者匕首 | 人工染色",
"流浪者匕首 | 北方森林",
"流浪者匕首 | 夜色",
"流浪者匕首 | 屠夫",
"流浪者匕首 | 枯焦之色",
"流浪者匕首 | 森林 DDPAT",
"流浪者匕首 | 深红之网",
"流浪者匕首 | 渐变之色",
"流浪者匕首 | 狩猎网格",
"流浪者匕首 | 蓝钢",
"流浪者匕首 | 表面淬火",
"流浪者匕首 | 都市伪装",
"系绳匕首 | 无涂装",
"系绳匕首 | 人工染色",
"系绳匕首 | 北方森林",
"系绳匕首 | 夜色",
"系绳匕首 | 屠夫",
"系绳匕首 | 枯焦之色",
"系绳匕首 | 森林 DDPAT",
"系绳匕首 | 深红之网",
"系绳匕首 | 渐变之色",
"系绳匕首 | 狩猎网格",
"系绳匕首 | 蓝钢",
"系绳匕首 | 表面淬火",
"系绳匕首 | 都市伪装",
"骷髅匕首 | 无涂装",
"骷髅匕首 | 人工染色",
"骷髅匕首 | 北方森林",
"骷髅匕首 | 夜色",
"骷髅匕首 | 屠夫",
"骷髅匕首 | 枯焦之色",
"骷髅匕首 | 森林 DDPAT",
"骷髅匕首 | 深红之网",
"骷髅匕首 | 渐变之色",
"骷髅匕首 | 狩猎网格",
"骷髅匕首 | 蓝钢",
"骷髅匕首 | 表面淬火",
"骷髅匕首 | 都市伪装",
]
LIEKONG_CASE_RED = ["AK-47 | 阿努比斯军团", "沙漠之鹰 | 印花集"]
LIEKONG_CASE_PINK = ["M4A4 | 齿仙", "XM1014 | 埋葬之影", "格洛克 | 摩登时代"]
LIEKONG_CASE_PURPLE = [
"加利尔 AR | 凤凰商号",
"Tec-9 | 兄弟连",
"MP5-SD | 猛烈冲锋",
"MAG-7 | 北冥有鱼",
"MAC-10 | 魅惑",
]
LIEKONG_CASE_BLUE = [
"内格夫 | 飞羽",
"SSG 08 | 主机001",
"SG 553 | 锈蚀之刃",
"PP-野牛 | 神秘碑文",
"P90 | 集装箱",
"P250 | 卡带",
"P2000 | 盘根错节",
]
GUANGPU_CASE_KNIFE = ['弯刀 | 外表生锈', '弯刀 | 多普勒', '弯刀 | 大马士革钢', '弯刀 | 渐变大理石', '弯刀 | 致命紫罗兰', '弯刀 | 虎牙',
'暗影双匕 | 外表生锈', '暗影双匕 | 多普勒', '暗影双匕 | 大马士革钢', '暗影双匕 | 渐变大理石', '暗影双匕 | 致命紫罗兰',
'暗影双匕 | 虎牙', '猎杀者匕首 | 外表生锈', '猎杀者匕首 | 多普勒', '猎杀者匕首 | 大马士革钢', '猎杀者匕首 | 渐变大理石',
'猎杀者匕首 | 致命紫罗兰', '猎杀者匕首 | 虎牙', '蝴蝶刀 | 外表生锈', '蝴蝶刀 | 多普勒', '蝴蝶刀 | 大马士革钢',
'蝴蝶刀 | 渐变大理石', '蝴蝶刀 | 致命紫罗兰', '蝴蝶刀 | 虎牙', '鲍伊猎刀 | 外表生锈', '鲍伊猎刀 | 多普勒',
'鲍伊猎刀 | 大马士革钢', '鲍伊猎刀 | 渐变大理石', '鲍伊猎刀 | 致命紫罗兰', '鲍伊猎刀 | 虎牙']
GUANGPU_CASE_RED = ['USP | 黑色魅影', 'AK-47 | 血腥运动']
GUANGPU_CASE_PINK = ['M4A1 | 毁灭者 2000', 'CZ75 | 相柳', 'AWP | 浮生如梦']
GUANGPU_CASE_PURPLE = ['加利尔 AR | 深红海啸', 'XM1014 | 四季', 'UMP-45 | 支架', 'MAC-10 | 绝界之行', 'M249 | 翠绿箭毒蛙']
GUANGPU_CASE_BLUE = ['沙漠之鹰 | 锈蚀烈焰', '截短霰弹枪 | 梭鲈', 'SCAR-20 | 蓝图', 'PP-野牛 | 丛林滑流', 'P250 | 涟漪', 'MP7 | 非洲部落',
'FN57 | 毛细血管']
GUANGPU_CASE_KNIFE = [
"弯刀 | 外表生锈",
"弯刀 | 多普勒",
"弯刀 | 大马士革钢",
"弯刀 | 渐变大理石",
"弯刀 | 致命紫罗兰",
"弯刀 | 虎牙",
"暗影双匕 | 外表生锈",
"暗影双匕 | 多普勒",
"暗影双匕 | 大马士革钢",
"暗影双匕 | 渐变大理石",
"暗影双匕 | 致命紫罗兰",
"暗影双匕 | 虎牙",
"猎杀者匕首 | 外表生锈",
"猎杀者匕首 | 多普勒",
"猎杀者匕首 | 大马士革钢",
"猎杀者匕首 | 渐变大理石",
"猎杀者匕首 | 致命紫罗兰",
"猎杀者匕首 | 虎牙",
"蝴蝶刀 | 外表生锈",
"蝴蝶刀 | 多普勒",
"蝴蝶刀 | 大马士革钢",
"蝴蝶刀 | 渐变大理石",
"蝴蝶刀 | 致命紫罗兰",
"蝴蝶刀 | 虎牙",
"鲍伊猎刀 | 外表生锈",
"鲍伊猎刀 | 多普勒",
"鲍伊猎刀 | 大马士革钢",
"鲍伊猎刀 | 渐变大理石",
"鲍伊猎刀 | 致命紫罗兰",
"鲍伊猎刀 | 虎牙",
]
GUANGPU_CASE_RED = ["USP | 黑色魅影", "AK-47 | 血腥运动"]
GUANGPU_CASE_PINK = ["M4A1 | 毁灭者 2000", "CZ75 | 相柳", "AWP | 浮生如梦"]
GUANGPU_CASE_PURPLE = [
"加利尔 AR | 深红海啸",
"XM1014 | 四季",
"UMP-45 | 支架",
"MAC-10 | 绝界之行",
"M249 | 翠绿箭毒蛙",
]
GUANGPU_CASE_BLUE = [
"沙漠之鹰 | 锈蚀烈焰",
"截短霰弹枪 | 梭鲈",
"SCAR-20 | 蓝图",
"PP-野牛 | 丛林滑流",
"P250 | 涟漪",
"MP7 | 非洲部落",
"FN57 | 毛细血管",
]
NO_STA_KNIFE = ['求生匕首 | 北方森林', '求生匕首 | 夜色', '求生匕首 | 枯焦之色', '流浪者匕首 | 夜色', '流浪者匕首 | 枯焦之色', '流浪者匕首 | 森林 DDPAT',
'系绳匕首 | 夜色', '系绳匕首 | 狩猎网格', '骷髅匕首 | 夜色', '骷髅匕首 | 森林 DDPAT', '骷髅匕首 | 狩猎网格']
NO_STA_KNIFE = [
"求生匕首 | 北方森林",
"求生匕首 | 夜色",
"求生匕首 | 枯焦之色",
"流浪者匕首 | 夜色",
"流浪者匕首 | 枯焦之色",
"流浪者匕首 | 森林 DDPAT",
"系绳匕首 | 夜色",
"系绳匕首 | 狩猎网格",
"骷髅匕首 | 夜色",
"骷髅匕首 | 森林 DDPAT",
"骷髅匕首 | 狩猎网格",
]
def get_wear(num: float) -> str:
if num <= FACTORY_NEW_E:
def get_wear(rand: float) -> str:
"""判断磨损度
Args:
rand (float): 随机rand
Returns:
str: 磨损名称
"""
if rand <= FACTORY_NEW_E:
return "崭新出厂"
if MINIMAL_WEAR_S <= num <= MINIMAL_WEAR_E:
if MINIMAL_WEAR_S <= rand <= MINIMAL_WEAR_E:
return "略有磨损"
if FIELD_TESTED_S <= num <= FIELD_TESTED_E:
if FIELD_TESTED_S <= rand <= FIELD_TESTED_E:
return "久经沙场"
if WELL_WORN_S <= num <= WELL_WORN_E:
if WELL_WORN_S <= rand <= WELL_WORN_E:
return "破损不堪"
return "战痕累累"
def get_color_quality(rand: float, case_name: str):
case = ""
mosun = random.random()/2 + random.random()/2
for i in pypinyin.pinyin(case_name, style=pypinyin.NORMAL):
case += ''.join(i)
case = case.upper()
CASE_KNIFE = eval(case + "_CASE_KNIFE")
CASE_RED = eval(case + "_CASE_RED")
CASE_PINK = eval(case + "_CASE_PINK")
CASE_PURPLE = eval(case + "_CASE_PURPLE")
CASE_BLUE = eval(case + "_CASE_BLUE")
if rand <= KNIFE:
skin = "罕见级(金色): " + random.choice(CASE_KNIFE)
if random.random() <= KNIFE_ST and (skin[2:4] != "手套" or skin[:2] != "裹手") and skin.split(':')[1] \
not in NO_STA_KNIFE:
skin_sp = skin.split("|")
skin = skin_sp[0] + "StatTrak™ | " + skin_sp[1]
elif KNIFE < rand <= RED:
skin = "隐秘级(红色): " + random.choice(CASE_RED)
if random.random() <= RED_ST:
skin_sp = skin.split("|")
skin = skin_sp[0] + "StatTrak™ | " + skin_sp[1]
elif RED < rand <= PINK:
skin = "保密级(粉色): " + random.choice(CASE_PINK)
if random.random() <= PINK_ST:
skin_sp = skin.split("|")
skin = skin_sp[0] + "StatTrak™ | " + skin_sp[1]
elif PINK < rand <= PURPLE:
skin = "受限级(紫色): " + random.choice(CASE_PURPLE)
if random.random() <= PURPLE_ST:
skin_sp = skin.split("|")
skin = skin_sp[0] + "StatTrak™ | " + skin_sp[1]
else:
skin = "军规级(蓝色): " + random.choice(CASE_BLUE)
if random.random() <= BLUE_ST:
skin_sp = skin.split("|")
skin = skin_sp[0] + "StatTrak™ | " + skin_sp[1]
if skin.find("") != -1:
cpskin = skin.split(":")[1]
ybskin = cpskin.split("|")
temp_skin = ybskin[0].strip()[:-11] + " | " + ybskin[1].strip()
else:
temp_skin = skin.split(":")[1].strip()
# 崭新 -> 略磨
if temp_skin in [] or temp_skin.find('渐变之色') != -1 or temp_skin.find('多普勒') != -1 or temp_skin.find('虎牙') != -1\
or temp_skin.find('渐变大理石') != -1:
mosun = random.uniform(FACTORY_NEW_S, MINIMAL_WEAR_E) / 2 + random.uniform(FACTORY_NEW_S, MINIMAL_WEAR_E) / 2
# 崭新 -> 久经
if temp_skin in ['沙漠之鹰 | 阴谋者', '新星 | 锦鲤'] or temp_skin.find('屠夫') != -1:
mosun = random.uniform(FACTORY_NEW_S, FIELD_TESTED_E) / 2 + random.uniform(FACTORY_NEW_S, FIELD_TESTED_E) / 2
# 崭新 -> 破损
if temp_skin in ['UMP-45 | 迷之宫', 'P250 | 超新星', '系绳匕首 | 深红之网', 'M249 | 翠绿箭毒蛙', 'AK-47 | 血腥运动']:
mosun = random.uniform(FACTORY_NEW_S, WELL_WORN_E) / 2 + random.uniform(FACTORY_NEW_S, WELL_WORN_E) / 2
# 破损 -> 战痕
if temp_skin in [] or temp_skin.find('外表生锈') != -1:
mosun = random.uniform(WELL_WORN_S, BATTLE_SCARED_E) / 2 + random.uniform(WELL_WORN_S, BATTLE_SCARED_E) / 2
if mosun > MINIMAL_WEAR_E:
for _ in range(2):
if random.random() < 5:
if random.random() < 0.2:
mosun /= 3
else:
mosun /= 2
break
skin += " (" + get_wear(mosun) + ")"
return skin, mosun
def random_color_and_st(rand: float) -> Tuple[str, bool]:
"""获取皮肤品质及是否暗金
# M249StatTrak™ | 等高线
Args:
rand (float): 随机rand
Returns:
Tuple[str, bool]: 品质是否暗金
"""
if rand <= KNIFE:
if random.random() <= KNIFE_ST:
return ("KNIFE", True)
return ("KNIFE", False)
elif KNIFE < rand <= RED:
if random.random() <= RED_ST:
return ("RED", True)
return ("RED", False)
elif RED < rand <= PINK:
if random.random() <= PINK_ST:
return ("PINK", True)
return ("PINK", False)
elif PINK < rand <= PURPLE:
if random.random() <= PURPLE_ST:
return ("PURPLE", True)
return ("PURPLE", False)
else:
if random.random() <= BLUE_ST:
return ("BLUE", True)
return ("BLUE", False)
async def random_skin(num: int, case_name: str) -> List[Tuple[BuffSkin, float]]:
"""
随机抽取皮肤
"""
color_map = {}
for _ in range(num):
rand = random.random()
# 尝试降低磨损
if rand > MINIMAL_WEAR_E:
for _ in range(2):
if random.random() < 0.5:
logger.debug(f"[START]开箱随机磨损触发降低磨损条件: {rand}")
if random.random() < 0.2:
rand /= 3
else:
rand /= 2
logger.debug(f"[END]开箱随机磨损触发降低磨损条件: {rand}")
break
abrasion = get_wear(rand)
logger.debug(f"开箱随机磨损: {rand} | {abrasion}")
color, is_stattrak = random_color_and_st(rand)
if not color_map.get(color):
color_map[color] = {}
if is_stattrak:
if not color_map[color].get(f"{abrasion}_st"):
color_map[color][f"{abrasion}_st"] = []
color_map[color][f"{abrasion}_st"].append(rand)
else:
if not color_map[color].get(abrasion):
color_map[color][f"{abrasion}"] = []
color_map[color][f"{abrasion}"].append(rand)
skin_list = []
for color in color_map:
for abrasion in color_map[color]:
rand_list = color_map[color][abrasion]
is_stattrak = "_st" in abrasion
abrasion = abrasion.replace("_st", "")
skin_list_ = await BuffSkin.random_skin(
len(rand_list), color, abrasion, is_stattrak, case_name
)
skin_list += [(skin, rand) for skin, rand in zip(skin_list_, rand_list)]
return skin_list
# M249StatTrak™ | 等高线

View File

@ -1,2 +0,0 @@
from .open_cases_user import *
from .buff_prices import *

View File

@ -0,0 +1,50 @@
import random
from typing import List, Optional
from tortoise import fields
from tortoise.contrib.postgres.functions import Random
from services.db_context import Model
class BuffSkin(Model):
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
case_name = fields.CharField(255)
"""箱子名称"""
name = fields.CharField(255)
"""武器/手套/刀名称"""
skin_name = fields.CharField(255)
"""皮肤名称"""
is_stattrak = fields.BooleanField(default=False)
"""是否暗金(计数)"""
abrasion = fields.CharField(255)
"""磨损度"""
color = fields.CharField(255)
"""颜色(品质)"""
skin_price = fields.FloatField(default=0)
"""皮肤价格"""
create_time = fields.DatetimeField(auto_add_now=True)
"""创建日期"""
update_time = fields.DatetimeField(auto_add=True)
"""更新日期"""
class Meta:
table = "buff_skin"
table_description = "Buff皮肤数据表"
@classmethod
async def random_skin(
cls,
num: int,
color: str,
abrasion: str,
is_stattrak: bool = False,
case_name: Optional[str] = None,
) -> List["BuffSkin"]:
query = cls
if case_name:
query = query.filter(case_name=case_name)
query = query.filter(abrasion=abrasion, is_stattrak=is_stattrak, color=color)
return await query.annotate(rand=Random()).limit(num) # type:ignore

View File

@ -4,7 +4,6 @@ from services.db_context import Model
class OpenCasesUser(Model):
__tablename__ = "open_cases_users"
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
@ -12,40 +11,47 @@ class OpenCasesUser(Model):
"""用户id"""
group_id = fields.BigIntField()
"""群聊id"""
total_count = fields.IntField(default=0)
total_count: int = fields.IntField(default=0)
"""总开启次数"""
blue_count = fields.IntField(default=0)
blue_count: int = fields.IntField(default=0)
"""蓝色"""
blue_st_count = fields.IntField(default=0)
blue_st_count: int = fields.IntField(default=0)
"""蓝色暗金"""
purple_count = fields.IntField(default=0)
purple_count: int = fields.IntField(default=0)
"""紫色"""
purple_st_count = fields.IntField(default=0)
purple_st_count: int = fields.IntField(default=0)
"""紫色暗金"""
pink_count = fields.IntField(default=0)
pink_count: int = fields.IntField(default=0)
"""粉色"""
pink_st_count = fields.IntField(default=0)
pink_st_count: int = fields.IntField(default=0)
"""粉色暗金"""
red_count = fields.IntField(default=0)
red_count: int = fields.IntField(default=0)
"""紫色"""
red_st_count = fields.IntField(default=0)
red_st_count: int = fields.IntField(default=0)
"""紫色暗金"""
knife_count = fields.IntField(default=0)
knife_count: int = fields.IntField(default=0)
"""金色"""
knife_st_count = fields.IntField(default=0)
knife_st_count: int = fields.IntField(default=0)
"""金色暗金"""
spend_money = fields.IntField(default=0)
spend_money: int = fields.IntField(default=0)
"""花费金币"""
make_money = fields.IntField(default=0)
make_money: float = fields.FloatField(default=0)
"""赚取金币"""
today_open_total = fields.IntField(default=0)
today_open_total: int = fields.IntField(default=0)
"""今日开箱数量"""
open_cases_time_last = fields.DatetimeField()
"""最后开箱日期"""
knifes_name = fields.TextField(default="")
knifes_name: str = fields.TextField(default="")
"""已获取金色"""
class Meta:
table = "open_cases_users"
table_description = "开箱统计数据表"
unique_together = ("user_qq", "group_id")
@classmethod
async def _run_script(cls):
await cls.raw(
"alter table open_cases_users alter COLUMN make_money type float;"
)
"""将make_money字段改为float"""

View File

@ -1,8 +1,10 @@
import asyncio
import random
from datetime import datetime, timedelta
from datetime import datetime
from typing import Union
import pypinyin
from nonebot.adapters.onebot.v11 import Message
from PIL import Image
from configs.config import Config
@ -16,164 +18,147 @@ from utils.utils import cn2py
from .config import *
from .models.buff_prices import BuffPrice
from .models.open_cases_user import OpenCasesUser
from .utils import get_price
RESULT_MESSAGE = {
"BLUE": ["这样看着才舒服", "是自己人,大伙把刀收好", "非常舒适~"],
"PURPLE": ["还行吧,勉强接受一下下", "居然不是蓝色,太假了", "运气-1-1-1-1-1..."],
"PINK": ["开始不适....", "你妈妈买菜必涨价!涨三倍!", "你最近不适合出门,真的"],
"RED": ["已经非常不适", "好兄弟你开的什么箱子啊,一般箱子不是只有蓝色的吗", "开始拿阳寿开箱子了?"],
"KNIFE": ["你的好运我收到了,你可以去喂鲨鱼了", "最近该吃啥就迟点啥吧,哎,好好的一个人怎么就....哎", "众所周知,欧皇寿命极短."],
}
COLOR2NAME = {"BLUE": "军规", "PURPLE": "受限", "PINK": "保密", "RED": "隐秘", "KNIFE": "罕见"}
COLOR2CN = {"BLUE": "", "PURPLE": "", "PINK": "", "RED": "", "KNIFE": ""}
async def open_case(user_qq: int, group: int, case_name: str = "狂牙大行动") -> str:
def add_count(user: OpenCasesUser, skin: BuffSkin):
if skin.color == "BLUE":
if skin.is_stattrak:
user.blue_st_count += 1
else:
user.blue_count += 1
elif skin.color == "PURPLE":
if skin.is_stattrak:
user.purple_st_count += 1
else:
user.purple_count += 1
elif skin.color == "PINK":
if skin.is_stattrak:
user.pink_st_count += 1
else:
user.pink_count += 1
elif skin.color == "RED":
if skin.is_stattrak:
user.red_st_count += 1
else:
user.red_count += 1
elif skin.color == "KNIFE":
if skin.is_stattrak:
user.knife_st_count += 1
else:
user.knife_count += 1
user.today_open_total += 1
user.total_count += 1
user.make_money += skin.skin_price
user.spend_money += 17
async def get_user_max_count(user_qq: int, group_id: int) -> int:
"""获取用户每日最大开箱次数
Args:
user_qq (int): 用户id
group_id (int): 群号
Returns:
int: 最大开箱次数
"""
user, _ = await SignGroupUser.get_or_create(user_qq=user_qq, group_id=group_id)
impression = int(user.impression)
initial_open_case_count = Config.get_config("open_cases", "INITIAL_OPEN_CASE_COUNT")
each_impression_add_count = Config.get_config(
"open_cases", "EACH_IMPRESSION_ADD_COUNT"
)
return int(initial_open_case_count + impression / each_impression_add_count) # type: ignore
async def open_case(
user_qq: int, group_id: int, case_name: str = "狂牙大行动"
) -> Union[str, Message]:
"""开箱
Args:
user_qq (int): 用户id
group_id (int): 群号
case_name (str, optional): 武器箱名称. Defaults to "狂牙大行动".
Returns:
Union[str, Message]: 回复消息
"""
if case_name not in ["狂牙大行动", "突围大行动", "命悬一线", "裂空", "光谱"]:
return "武器箱未收录"
knifes_flag = False
# lan zi fen hong jin price
uplist = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0]
case = ""
for i in pypinyin.pinyin(case_name, style=pypinyin.NORMAL):
case += "".join(i)
user, _ = await SignGroupUser.get_or_create(user_qq=user_qq, group_id=group)
impression = user.impression
rand = random.random()
await OpenCasesUser.get_or_none(user_qq=user_qq, group_id=group)
# user, _ = await OpenCasesUser.get_or_create(user_qq=user_qq, group_id=group)
user = await OpenCasesUser.get_or_none(user_qq=user_qq, group_id=group)
logger.debug(f"尝试开启武器箱: {case_name}", "开箱", user_qq, group_id)
case = cn2py(case_name)
user = await OpenCasesUser.get_or_none(user_qq=user_qq, group_id=group_id)
if not user:
user = await OpenCasesUser.create(
user_qq=user_qq, group_id=group, open_cases_time_last=datetime.now()
user_qq=user_qq, group_id=group_id, open_cases_time_last=datetime.now()
)
max_count = await get_user_max_count(user_qq, group_id)
# 一天次数上限
if user.today_open_total >= int(
Config.get_config("open_cases", "INITIAL_OPEN_CASE_COUNT")
+ int(impression) / Config.get_config("open_cases", "EACH_IMPRESSION_ADD_COUNT")
):
if user.today_open_total >= max_count:
return _handle_is_MAX_COUNT()
skin, mosun = get_color_quality(rand, case_name)
# 调侃
if skin[:2] == "军规":
if skin.find("StatTrak") == -1:
uplist[0] = 1
else:
uplist[1] = 1
ridicule_result = random.choice(["这样看着才舒服", "是自己人,大伙把刀收好", "非常舒适~"])
if skin[:2] == "受限":
if skin.find("StatTrak") == -1:
uplist[2] = 1
else:
uplist[3] = 1
ridicule_result = random.choice(
["还行吧,勉强接受一下下", "居然不是蓝色,太假了", "运气-1-1-1-1-1..."]
skin_list = await random_skin(1, case_name)
if not skin_list:
return "未抽取到任何皮肤..."
skin, rand = skin_list[0]
rand = str(rand)[:11]
add_count(user, skin)
ridicule_result = random.choice(RESULT_MESSAGE[skin.color])
price_result = skin.skin_price
if skin.color == "KNIFE":
user.knifes_name = (
user.knifes_name
+ f"{case}||{skin.name}{'StatTrak™' if skin.is_stattrak else ''} | {skin.skin_name} ({skin.abrasion}) 磨损:{rand} 价格:{skin.skin_price},"
)
if skin[:2] == "保密":
if skin.find("StatTrak") == -1:
uplist[4] = 1
else:
uplist[5] = 1
ridicule_result = random.choice(["开始不适....", "你妈妈买菜必涨价!涨三倍!", "你最近不适合出门,真的"])
if skin[:2] == "隐秘":
if skin.find("StatTrak") == -1:
uplist[6] = 1
else:
uplist[7] = 1
ridicule_result = random.choice(
["已经非常不适", "好兄弟你开的什么箱子啊,一般箱子不是只有蓝色的吗", "开始拿阳寿开箱子了?"]
)
if skin[:2] == "罕见":
knifes_flag = True
if skin.find("StatTrak") == -1:
uplist[8] = 1
else:
uplist[9] = 1
ridicule_result = random.choice(
["你的好运我收到了,你可以去喂鲨鱼了", "最近该吃啥就迟点啥吧,哎,好好的一个人怎么就....哎", "众所周知,欧皇寿命极短."]
)
if skin.find("") != -1:
cskin = skin.split("")
skin = cskin[0].strip() + "" + cskin[1].strip()
skin = skin.split("|")[0].strip() + " | " + skin.split("|")[1].strip()
# 价格
if skin.find("无涂装") == -1:
search_name = skin[9:]
else:
search_name = skin[9 : skin.rfind("(")].strip()
price_result = 0
if data := await BuffPrice.get_or_none(skin_name=search_name):
if data.skin_price != 0:
price_result = data.skin_price
logger.info("数据库查询到价格: ", data.skin_price)
uplist[10] = data.skin_price
else:
price = -1
price_result = "未查询到"
price_list, status = await get_price(skin[9:])
if price_list not in ["访问超时! 请重试或稍后再试!", "访问失败!"]:
for price_l in price_list[1:]:
pcp = price_l.split(":")
if pcp[0] == skin[9:]:
price = float(pcp[1].strip())
break
if price != -1:
logger.info("存储入数据库---->{price}")
uplist[10] = price
price_result = str(price)
data.skin_price = price
data.update_date = datetime.now()
await data.save(update_fields=["skin_price", "update_date"])
# sp = skin.split("|")
# cskin_word = sp[1][:sp[1].find("(") - 1].strip()
if knifes_flag:
await user.update(
knifes_name=user.knifes_name
+ f"{case}||{skin.split(':')[1].strip()} 磨损:{str(mosun)[:11]} 价格:{uplist[10]},"
).apply()
cskin_word = skin.split(":")[1].replace("|", "-").replace("StatTrak™", "")
cskin_word = cskin_word[: cskin_word.rfind("(")].strip()
skin_name = cn2py(cskin_word.replace("|", "-").replace("StatTrak™", "").strip())
img = image(IMAGE_PATH / "cases" / case / f"{skin_name}.png")
# if knifes_flag:
# await user.update(
# knifes_name=user.knifes_name + f"{skin} 磨损:{mosun} 价格:{uplist[10]}"
# ).apply()
if await update_user_total(user, uplist):
logger.info(
f"qq:{user_qq} 群:{group} 开启{case_name}武器箱 获得 {skin} 磨损:{mosun} 价格:{uplist[10]} 数据更新成功"
)
else:
logger.warning(
f"qq:{user_qq} 群:{group} 开启{case_name}武器箱 获得 {skin} 磨损:{mosun} 价格:{uplist[10]} 数据更新失败"
)
user, _ = await OpenCasesUser.get_or_create(user_qq=user_qq, group_id=group)
over_count = (
int(
Config.get_config("open_cases", "INITIAL_OPEN_CASE_COUNT")
+ int(impression)
/ Config.get_config("open_cases", "EACH_IMPRESSION_ADD_COUNT")
)
- user.today_open_total
img_path = (
IMAGE_PATH
/ "cases"
/ case
/ f"{cn2py(skin.name)} - {cn2py(skin.skin_name)}.png"
)
logger.info(
f"开启{case_name}武器箱获得 {skin.name}{'StatTrak™' if skin.is_stattrak else ''} | {skin.skin_name} ({skin.abrasion}) 磨损: [{rand}] 价格: {skin.skin_price}",
"开箱",
user_qq,
group_id,
)
await user.save()
over_count = max_count - user.today_open_total
return (
f"开启{case_name}武器箱.\n剩余开箱次数:{over_count}.\n" + img + "\n" + f"皮肤:{skin}\n"
f"磨损:{mosun:.9f}\n"
f"开启{case_name}武器箱.\n剩余开箱次数:{over_count}.\n"
+ image(img_path)
+ "\n"
+ f"皮肤:[{COLOR2NAME[skin.color]}]{skin.name}{'StatTrak™' if skin.is_stattrak else ''} | {skin.skin_name} ({skin.abrasion})\n"
f"磨损:{rand}\n"
f"价格:{price_result}\n"
f"{ridicule_result}"
f":{ridicule_result}"
)
async def open_shilian_case(user_qq: int, group: int, case_name: str, num: int = 10):
user, _ = await OpenCasesUser.get_or_create(user_qq=user_qq, group_id=group)
sign_user, _ = await SignGroupUser.get_or_create(user_qq=user_qq, group_id=group)
impression = sign_user.impression
max_count = int(
Config.get_config("open_cases", "INITIAL_OPEN_CASE_COUNT")
+ int(impression) / Config.get_config("open_cases", "EACH_IMPRESSION_ADD_COUNT")
)
async def open_multiple_case(
user_qq: int, group_id: int, case_name: str, num: int = 10
):
user, _ = await OpenCasesUser.get_or_create(user_qq=user_qq, group_id=group_id)
max_count = await get_user_max_count(user_qq, group_id)
if user.today_open_total >= max_count:
return _handle_is_MAX_COUNT()
if max_count - user.today_open_total < num:
return (
f"今天开箱次数不足{num}次噢,请单抽试试看(也许单抽运气更好?)"
f"\n剩余开箱次数{max_count - user.today_open_total}"
f"\n剩余开箱次数:{max_count - user.today_open_total}"
)
user.total_count = user.total_count + num
user.spend_money = user.spend_money + 17 * num
user.today_open_total = user.today_open_total + num
await user.save(update_fields=["total_count", "spend_money", "today_open_total"])
if num < 5:
h = 270
elif num % 5 == 0:
@ -181,149 +166,73 @@ async def open_shilian_case(user_qq: int, group: int, case_name: str, num: int =
else:
h = 270 * int(num / 5) + 270
case = cn2py(case_name)
# lan zi fen hong jin
# skin_list = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# lan zi fen hong jin price
uplist = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0]
skin_count = {}
img_list = []
name_list = ["", "蓝(暗金)", "", "紫(暗金)", "", "粉(暗金)", "", "红(暗金)", "", "金(暗金)"]
for _ in range(num):
knifes_flag = False
rand = random.random()
skin, mosun = get_color_quality(rand, case_name)
if skin[:2] == "军规":
if skin.find("StatTrak") == -1:
uplist[0] += 1
else:
uplist[1] += 1
if skin[:2] == "受限":
if skin.find("StatTrak") == -1:
uplist[2] += 1
else:
uplist[3] += 1
if skin[:2] == "保密":
if skin.find("StatTrak") == -1:
uplist[4] += 1
else:
uplist[5] += 1
if skin[:2] == "隐秘":
if skin.find("StatTrak") == -1:
uplist[6] += 1
else:
uplist[7] += 1
if skin[:2] == "罕见":
knifes_flag = True
if skin.find("StatTrak") == -1:
uplist[8] += 1
else:
uplist[9] += 1
if skin.find("") != -1:
cskin = skin.split("")
skin = cskin[0].strip() + "" + cskin[1].strip()
skin = skin.split("|")[0].strip() + " | " + skin.split("|")[1].strip()
# 价格
if skin.find("无涂装") == -1:
search_name = skin[9:]
else:
search_name = skin[9 : skin.rfind("(")].strip()
if dbprice := await BuffPrice.get_or_none(skin_name=search_name):
if dbprice.skin_price != 0:
price_result = dbprice.skin_price
uplist[10] += price_result
else:
price_result = "未查询到"
if knifes_flag:
await user.update(
knifes_name=user.knifes_name
+ f"{case}||{skin.split(':')[1].strip()} 磨损:{str(mosun)[:11]} 价格:{dbprice.skin_price},"
).apply()
cskin_word = skin.split(":")[1].replace("|", "-").replace("StatTrak™", "")
cskin_word = cskin_word[: cskin_word.rfind("(")].strip()
skin_name = ""
for i in pypinyin.pinyin(
cskin_word.replace("|", "-").replace("StatTrak™", "").strip(),
style=pypinyin.NORMAL,
):
skin_name += "".join(i)
wImg = BuildImage(200, 270, 200, 200)
wImg.paste(
alpha2white_pil(
Image.open(IMAGE_PATH / "cases" / case / f"{skin_name}.png").resize(
(200, 200), Image.ANTIALIAS
)
),
(0, 0),
skin_list = await random_skin(num, case_name)
if not skin_list:
return "未抽取到任何皮肤..."
total_price = 0
for skin, rand in skin_list:
total_price += skin.skin_price
rand = str(rand)[:11]
add_count(user, skin)
color_name = COLOR2CN[skin.color]
if skin.is_stattrak:
color_name += "(暗金)"
if not skin_count.get(color_name):
skin_count[color_name] = 0
skin_count[color_name] += 1
if skin.color == "KNIFE":
user.knifes_name = (
user.knifes_name
+ f"{case}||{skin.name}{'StatTrak™' if skin.is_stattrak else ''} | {skin.skin_name} ({skin.abrasion}) 磨损:{rand} 价格:{skin.skin_price},"
)
wImg.text((5, 200), skin)
wImg.text((5, 220), f"磨损:{str(mosun)[:9]}")
wImg.text((5, 240), f"价格:{price_result}")
img_list.append(wImg)
logger.info(
f"USER {user_qq} GROUP {group} 开启{case_name}武器箱 获得 {skin} 磨损:{mosun} 价格:{uplist[10]}"
)
if await update_user_total(user, uplist, 0):
logger.info(
f"USER {user_qq} GROUP {group} 开启{case_name}武器箱 {num} 次, 数据更新成功"
)
else:
logger.warning(
f"USER {user_qq} GROUP {group} 开启{case_name}武器箱 {num} 次, 价格:{uplist[10]} 数据更新失败"
)
# markImg = BuildImage(1000, h, 200, 270)
# for img in img_list:
# markImg.paste(img)
markImg = await asyncio.get_event_loop().run_in_executor(
None, paste_markImg, h, img_list
)
over_count = max_count - user.today_open_total
result = ""
for i in range(len(name_list)):
if uplist[i]:
result += f"[{name_list[i]}{uplist[i]}] "
return (
f"开启{case_name}武器箱\n剩余开箱次数:{over_count}\n"
+ image(b64=markImg.pic2bs4())
+ "\n"
+ result[:-1]
+ f"\n总获取金额:{uplist[-1]:.2f}\n总花费:{17 * num}"
)
def paste_markImg(h: int, img_list: list):
wImg = BuildImage(200, 270, 200, 200)
await wImg.apaste(
alpha2white_pil(
Image.open(
IMAGE_PATH
/ "cases"
/ case
/ f"{cn2py(skin.name)} - {cn2py(skin.skin_name)}.png"
).resize((200, 200), Image.ANTIALIAS)
),
(0, 0),
)
await wImg.atext(
(5, 200),
f"{skin.name}{'StatTrak™' if skin.is_stattrak else ''} | {skin.skin_name} ({skin.abrasion})",
)
await wImg.atext((5, 220), f"磨损:{rand}")
await wImg.atext((5, 240), f"价格:{skin.skin_price}")
img_list.append(wImg)
logger.info(
f"开启{case_name}武器箱获得 {skin.name}{'StatTrak™' if skin.is_stattrak else ''} | {skin.skin_name} ({skin.abrasion}) 磨损: [{rand}] 价格: {skin.skin_price}",
"开箱",
user_qq,
group_id,
)
await user.save()
markImg = BuildImage(1000, h, 200, 270)
for img in img_list:
markImg.paste(img)
return markImg
over_count = max_count - user.today_open_total
result = ""
for color_name in skin_count:
result += f"[{color_name}:{skin_count[color_name]}] "
return (
f"开启{case_name}武器箱\n剩余开箱次数:{over_count}\n"
+ image(markImg.pic2bs4())
+ "\n"
+ result[:-1]
+ f"\n总获取金额:{total_price:.2f}\n总花费:{17 * num}"
)
def _handle_is_MAX_COUNT() -> str:
return f"今天已达开箱上限了喔,明天再来吧\n(提升好感度可以增加每日开箱数 #疯狂暗示)"
async def update_user_total(user: OpenCasesUser, up_list: list, num: int = 1) -> bool:
try:
await user.update_or_create(
total_count=user.total_count + num,
blue_count=user.blue_count + up_list[0],
blue_st_count=user.blue_st_count + up_list[1],
purple_count=user.purple_count + up_list[2],
purple_st_count=user.purple_st_count + up_list[3],
pink_count=user.pink_count + up_list[4],
pink_st_count=user.pink_st_count + up_list[5],
red_count=user.red_count + up_list[6],
red_st_count=user.red_st_count + up_list[7],
knife_count=user.knife_count + up_list[8],
knife_st_count=user.knife_st_count + up_list[9],
spend_money=user.spend_money + 17 * num,
make_money=user.make_money + up_list[10],
today_open_total=user.today_open_total + num,
open_cases_time_last=datetime.now(),
)
return True
except:
return False
async def total_open_statistics(user_qq: int, group: int) -> str:
user, _ = await OpenCasesUser.get_or_create(user_qq=user_qq, group_id=group)
return (

View File

@ -1,23 +1,25 @@
import os
from asyncio.exceptions import TimeoutError
from datetime import datetime, timedelta
from datetime import datetime
from typing import Optional
from nonebot.adapters.onebot.v11 import ActionFailed
import nonebot
from configs.config import Config
from configs.path_config import IMAGE_PATH
from services.log import logger
from utils.http_utils import AsyncHttpx
from utils.manager import group_manager
from utils.utils import cn2py, get_bot
from utils.utils import broadcast_group, cn2py
from .config import *
from .models.buff_prices import BuffPrice
from .models.buff_skin import BuffSkin
from .models.open_cases_user import OpenCasesUser
url = "https://buff.163.com/api/market/goods"
# proxies = 'http://49.75.59.242:3128'
driver = nonebot.get_driver()
async def util_get_buff_price(case_name: str = "狂牙大行动") -> str:
cookie = {"session": Config.get_config("open_cases", "COOKIE")}
@ -255,22 +257,86 @@ async def get_price(d_name):
return result[:-1], 999
async def update_count_daily():
async def reset_count_daily():
"""
重置每日开箱
"""
try:
await OpenCasesUser.all().update(today_open_total=0)
bot = get_bot()
gl = await bot.get_group_list()
gl = [g["group_id"] for g in gl]
for g in gl:
try:
await bot.send_group_msg(
group_id=g, message="[[_task|open_case_reset_remind]]今日开箱次数重置成功"
)
except ActionFailed:
logger.warning(f"{g} 群被禁言,无法发送 开箱重置提醒")
logger.info("今日开箱次数重置成功")
await broadcast_group(
"[[_task|open_case_reset_remind]]今日开箱次数重置成功", log_cmd="开箱重置提醒"
)
except Exception as e:
logger.error(f"开箱重置错误 e:{e}")
logger.error(f"开箱重置错误", e=e)
def get_color(case_name: str, name: str, skin_name: str) -> Optional[str]:
case_py = cn2py(case_name).upper()
color_map = {}
color_map["KNIFE"] = eval(case_py + "_CASE_KNIFE")
color_map["RED"] = eval(case_py + "_CASE_RED")
color_map["PINK"] = eval(case_py + "_CASE_PINK")
color_map["PURPLE"] = eval(case_py + "_CASE_PURPLE")
color_map["BLUE"] = eval(case_py + "_CASE_BLUE")
for key in color_map:
for skin in color_map[key]:
if name in skin and skin_name in skin:
return key
return None
@driver.on_startup
async def _():
"""
将旧表数据移动到新表
"""
if not await BuffSkin.first() and await BuffPrice.first():
logger.debug("开始移动旧表数据 BuffPrice -> BuffSkin")
id2name = {1: "狂牙大行动", 2: "突围大行动", 3: "命悬一线", 4: "裂空", 5: "光谱"}
data_list: List[BuffSkin] = []
for data in await BuffPrice.all():
logger.debug(f"移动旧表数据: {data.skin_name}")
case_name = id2name[data.case_id]
name = data.skin_name
is_stattrak = "StatTrak" in name
name = name.replace("(★ StatTrak™", "").replace("StatTrak™", "").strip()
name, skin_name = name.split("|")
abrasion = "无涂装"
if "(" in skin_name:
skin_name, abrasion = skin_name.split("(")
if abrasion.endswith(")"):
abrasion = abrasion[:-1]
color = get_color(case_name, name.strip(), skin_name.strip())
if not color:
search_list = [
x
for x in data_list
if x.skin_name == skin_name.strip() and x.name == name.strip()
]
if search_list:
color = get_color(
case_name, search_list[0].name, search_list[0].skin_name
)
if not color:
logger.debug(
f"箱子: [{case_name}] 皮肤: [{name}|{skin_name}] 未获取到皮肤品质,跳过..."
)
continue
data_list.append(
BuffSkin(
case_name=case_name,
name=name.strip(),
skin_name=skin_name.strip(),
is_stattrak=is_stattrak,
abrasion=abrasion.strip(),
skin_price=data.skin_price,
color=color,
create_time=datetime.now(),
update_time=datetime.now(),
)
)
await BuffSkin.bulk_create(data_list, batch_size=10)
logger.debug("完成移动旧表数据 BuffPrice -> BuffSkin")
# 蝴蝶刀(★) | 噩梦之夜 (久经沙场)

View File

@ -35,6 +35,7 @@ Config.add_plugin_config(
True,
help_="被动 B站转发解析 进群默认开关状态",
default_value=True,
type=bool
)

View File

@ -1,7 +1,9 @@
from pathlib import Path
from typing import Tuple
import nonebot
from configs.config import Config
from utils.utils import GDict
Config.add_plugin_config(
"hibiapi",
@ -25,6 +27,7 @@ Config.add_plugin_config(
5000,
help_="最低收藏PIX使用HIBIAPI搜索图片时达到最低收藏才会添加至图库",
default_value=5000,
type=int,
)
Config.add_plugin_config(
"pix",
@ -32,6 +35,7 @@ Config.add_plugin_config(
(0, 1),
help_="自动撤回参1延迟撤回色图时间(秒)0 为关闭 | 参2监控聊天类型0(私聊) 1(群聊) 2(群聊+私聊)",
default_value=(0, 1),
type=Tuple[int, int],
)
Config.add_plugin_config(
"pix",
@ -39,13 +43,15 @@ Config.add_plugin_config(
(10, 0),
help_="PIX图库 与 额外图库OmegaPixivIllusts 混合搜索的比例 参1PIX图库 参2OmegaPixivIllusts扩展图库没有此图库请设置为0",
default_value=(10, 0),
type=Tuple[int, int],
)
Config.add_plugin_config(
"pix", "TIMEOUT", 10, help_="下载图片超时限制(秒)", default_value=10, type=int
)
Config.add_plugin_config("pix", "TIMEOUT", 10, help_="下载图片超时限制(秒)", default_value=10)
Config.add_plugin_config(
"pix", "SHOW_INFO", True, help_="是否显示图片的基本信息如PID等", default_value=True
"pix", "SHOW_INFO", True, help_="是否显示图片的基本信息如PID等", default_value=True, type=bool
)
GDict["run_sql"].append("ALTER TABLE omega_pixiv_illusts ADD classified Integer;")
nonebot.load_plugins("plugins/pix_gallery")
# GDict["run_sql"].append("ALTER TABLE omega_pixiv_illusts ADD classified Integer;")
nonebot.load_plugins(str(Path(__file__).parent.resolve()))

View File

@ -1,16 +1,18 @@
from utils.utils import is_number
from configs.config import Config
from ._model.omega_pixiv_illusts import OmegaPixivIllusts
from utils.message_builder import image, custom_forward_msg
from utils.manager import withdraw_message_manager
from services.log import logger
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent, Message
from nonebot.params import CommandArg
from ._data_source import get_image
from ._model.pixiv import Pixiv
from nonebot import on_command
import random
from nonebot import on_command
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
from nonebot.params import CommandArg
from configs.config import Config
from services.log import logger
from utils.manager import withdraw_message_manager
from utils.message_builder import custom_forward_msg, image
from utils.utils import is_number
from ._data_source import get_image
from ._model.omega_pixiv_illusts import OmegaPixivIllusts
from ._model.pixiv import Pixiv
__zx_plugin_name__ = "PIX"
__plugin_usage__ = """
@ -55,9 +57,20 @@ __plugin_configs__ = {
"value": None,
"help": "单次发送的图片数量达到指定值时转发为合并消息",
"default_value": None,
"type": int,
},
"ALLOW_GROUP_SETU": {
"value": False,
"help": "允许非超级用户使用-s参数",
"default_value": False,
"type": bool,
},
"ALLOW_GROUP_R18": {
"value": False,
"help": "允许非超级用户使用-r参数",
"default_value": False,
"type": bool,
},
"ALLOW_GROUP_SETU": {"value": False, "help": "允许非超级用户使用-s参数", "default_value": False},
"ALLOW_GROUP_R18": {"value": False, "help": "允许非超级用户使用-r参数", "default_value": False},
}

View File

@ -1,16 +1,25 @@
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent, Message, NetworkError
import time
from asyncio.exceptions import TimeoutError
from typing import Type
from nonebot import on_command
from nonebot.adapters.onebot.v11 import (
Bot,
GroupMessageEvent,
Message,
MessageEvent,
NetworkError,
)
from nonebot.matcher import Matcher
from nonebot.params import CommandArg
from nonebot import on_command
from utils.utils import is_number
from .data_source import get_pixiv_urls, download_pixiv_imgs, search_pixiv_urls
from services.log import logger
from asyncio.exceptions import TimeoutError
from utils.message_builder import custom_forward_msg
from configs.config import Config
from typing import Type
from nonebot.rule import to_me
import time
from configs.config import Config
from services.log import logger
from utils.message_builder import custom_forward_msg
from utils.utils import is_number
from .data_source import download_pixiv_imgs, get_pixiv_urls, search_pixiv_urls
__zx_plugin_name__ = "P站排行/搜图"
@ -61,21 +70,19 @@ __plugin_settings__ = {
}
__plugin_block_limit__ = {"rst": "P站排行榜或搜图正在搜索请不要重复触发命令..."}
__plugin_configs__ = {
"TIMEOUT": {
"value": 10,
"help": "图片下载超时限制",
"default_value": 10
},
"TIMEOUT": {"value": 10, "help": "图片下载超时限制", "default_value": 10, "type": int},
"MAX_PAGE_LIMIT": {
"value": 20,
"help": "作品最大页数限制,超过的作品会被略过",
"default_value": 20
"default_value": 20,
"type": int,
},
"ALLOW_GROUP_R18": {
"value": False,
"help": "允许群聊中使用 r18 参数",
"default_value": False
}
"default_value": False,
"type": bool,
},
}
Config.add_plugin_config(
"hibiapi",
@ -84,12 +91,7 @@ Config.add_plugin_config(
help_="如果没有自建或其他hibiapi请不要修改",
default_value="https://api.obfs.dev",
)
Config.add_plugin_config(
"pixiv",
"PIXIV_NGINX_URL",
"i.pixiv.re",
help_="Pixiv反向代理"
)
Config.add_plugin_config("pixiv", "PIXIV_NGINX_URL", "i.pixiv.re", help_="Pixiv反向代理")
rank_dict = {
@ -158,7 +160,9 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip()
if isinstance(event, GroupMessageEvent):
if "r18" in msg.lower() and not Config.get_config("pixiv_rank_search", "ALLOW_GROUP_R18"):
if "r18" in msg.lower() and not Config.get_config(
"pixiv_rank_search", "ALLOW_GROUP_R18"
):
await pixiv_keyword.finish("(脸红#) 你不会害羞的 八嘎!", at_sender=True)
r18 = 0 if "r18" in msg else 1
msg = msg.replace("r18", "").strip().split()
@ -168,7 +172,7 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
num = 10
page = 1
if (n := len(msg)) > 0:
keyword = msg[0].replace("#"," ")
keyword = msg[0].replace("#", " ")
if n > 1:
if not is_number(msg[1]):
await pixiv_keyword.finish("图片数量必须是数字!", at_sender=True)
@ -206,7 +210,10 @@ async def send_image(
idx = 0
mes_list = []
for title, author, urls in info_list:
_message = f"title: {title}\nauthor: {author}\n" + await download_pixiv_imgs(urls, event.user_id, idx)
_message = (
f"title: {title}\nauthor: {author}\n"
+ await download_pixiv_imgs(urls, event.user_id, idx)
)
mes_list.append(_message)
idx += 1
mes_list = custom_forward_msg(mes_list, bot.self_id)

View File

@ -57,6 +57,7 @@ __plugin_configs__ = {
"value": 1000,
"help": "俄罗斯轮盘最大赌注金额",
"default_value": 1000,
"type": int,
}
}

View File

@ -1,12 +1,13 @@
from nonebot import on_command
from .data_source import from_anime_get_info
from services.log import logger
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent, Message
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
from nonebot.params import ArgStr, CommandArg
from nonebot.typing import T_State
from configs.config import Config
from utils.message_builder import custom_forward_msg
from nonebot.params import CommandArg, ArgStr
from configs.config import Config
from services.log import logger
from utils.message_builder import custom_forward_msg
from .data_source import from_anime_get_info
__zx_plugin_name__ = "搜番"
__plugin_usage__ = f"""
@ -29,7 +30,12 @@ __plugin_settings__ = {
}
__plugin_block_limit__ = {"rst": "搜索还未完成,不要重复触发!"}
__plugin_configs__ = {
"SEARCH_ANIME_MAX_INFO": {"value": 20, "help": "搜索动漫返回的最大数量", "default_value": 20}
"SEARCH_ANIME_MAX_INFO": {
"value": 20,
"help": "搜索动漫返回的最大数量",
"default_value": 20,
"type": int,
}
}
search_anime = on_command("搜番", aliases={"搜动漫"}, priority=5, block=True)
@ -42,7 +48,9 @@ async def _(state: T_State, arg: Message = CommandArg()):
@search_anime.got("anime", prompt="是不是少了番名?")
async def _(bot: Bot, event: MessageEvent, state: T_State, key_word: str = ArgStr("anime")):
async def _(
bot: Bot, event: MessageEvent, state: T_State, key_word: str = ArgStr("anime")
):
await search_anime.send(f"开始搜番 {key_word}", at_sender=True)
anime_report = await from_anime_get_info(
key_word,

View File

@ -1,12 +1,13 @@
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
from nonebot.params import Arg, ArgStr, CommandArg, Depends
from nonebot.plugin import on_command
from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent, Message
from nonebot.typing import T_State
from services.log import logger
from utils.utils import get_message_img
from utils.message_builder import custom_forward_msg
from nonebot.params import CommandArg, Arg, ArgStr, Depends
from .saucenao import get_saucenao_image
from services.log import logger
from utils.message_builder import custom_forward_msg
from utils.utils import get_message_img
from .saucenao import get_saucenao_image
__zx_plugin_name__ = "识图"
__plugin_usage__ = """
@ -27,7 +28,12 @@ __plugin_settings__ = {
"cmd": ["识图"],
}
__plugin_configs__ = {
"MAX_FIND_IMAGE_COUNT": {"value": 3, "help": "识图返回的最大结果数", "default_value": 3},
"MAX_FIND_IMAGE_COUNT": {
"value": 3,
"help": "识图返回的最大结果数",
"default_value": 3,
"type": int,
},
"API_KEY": {
"value": None,
"help": "Saucenao的API_KEY通过 https://saucenao.com/user.php?page=search-api 注册获取",
@ -44,12 +50,11 @@ async def get_image_info(mod: str, url: str):
def parse_image(key: str):
async def _key_parser(
state: T_State, img: Message = Arg(key)
):
async def _key_parser(state: T_State, img: Message = Arg(key)):
if not get_message_img(img):
await search_image.reject_arg(key, "请发送要识别的图片!")
state[key] = img
return _key_parser

View File

@ -1,13 +1,17 @@
from datetime import datetime
from configs.config import Config
from nonebot import on
from nonebot.adapters.onebot.v11 import (Bot, Event, GroupMessageEvent,
PrivateMessageEvent)
from nonebot.adapters.onebot.v11 import (
Bot,
Event,
GroupMessageEvent,
PrivateMessageEvent,
)
from nonebot.message import handle_event
from ._rule import rule
from configs.config import Config
from ._rule import rule
__zx_plugin_name__ = "自身消息触发 [Hidden]"
__plugin_version__ = 0.1
@ -18,6 +22,7 @@ Config.add_plugin_config(
False,
help_="允许真寻自身触发命令需要在go-cqhttp配置文件中report-self-message修改为true触发命令时需前缀cmd且受权限影响例如cmd签到",
default_value=False,
type=bool,
)
message_sent = on(

View File

@ -78,29 +78,44 @@ __plugin_configs__ = {
"value": (0, 1),
"help": "自动撤回参1延迟撤回色图时间(秒)0 为关闭 | 参2监控聊天类型0(私聊) 1(群聊) 2(群聊+私聊)",
"default_value": (0, 1),
"type": Tuple[int, int],
},
"ONLY_USE_LOCAL_SETU": {
"value": False,
"help": "仅仅使用本地色图,不在线搜索",
"default_value": False,
"type": bool,
},
"INITIAL_SETU_PROBABILITY": {
"value": 0.7,
"help": "初始色图概率,总概率 = 初始色图概率 + 好感度",
"default_value": 0.7,
"type": float,
},
"DOWNLOAD_SETU": {
"value": True,
"help": "是否存储下载的色图,使用本地色图可以加快图片发送速度",
"default_value": True,
"type": bool,
},
"TIMEOUT": {"value": 10, "help": "色图下载超时限制(秒)", "default_value": 10, "type": int},
"SHOW_INFO": {
"value": True,
"help": "是否显示色图的基本信息如PID等",
"default_value": True,
"type": bool,
},
"ALLOW_GROUP_R18": {
"value": False,
"help": "在群聊中启用R18权限",
"default_value": False,
"type": bool,
},
"TIMEOUT": {"value": 10, "help": "色图下载超时限制(秒)", "default_value": 10},
"SHOW_INFO": {"value": True, "help": "是否显示色图的基本信息如PID等", "default_value": True},
"ALLOW_GROUP_R18": {"value": False, "help": "在群聊中启用R18权限", "default_value": False},
"MAX_ONCE_NUM2FORWARD": {
"value": None,
"help": "单次发送的图片数量达到指定值时转发为合并消息",
"default_value": None,
"type": int,
},
}
Config.add_plugin_config("pixiv", "PIXIV_NGINX_URL", "i.pixiv.re", help_="Pixiv反向代理")

View File

@ -1,24 +1,25 @@
from typing import Tuple, Any
from pathlib import Path
from typing import Any, Tuple
from .group_user_checkin import (
group_user_check_in,
group_user_check,
group_impression_rank,
impression_rank,
check_in_all
)
from nonebot import on_command, on_regex
from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message
from nonebot.adapters.onebot.v11.permission import GROUP
from utils.message_builder import image
from nonebot import on_command, on_regex
from utils.utils import scheduler
from nonebot.params import CommandArg, RegexGroup
from pathlib import Path
from configs.path_config import DATA_PATH
from services.log import logger
from .utils import clear_sign_data_pic
from utils.utils import is_number
from utils.message_builder import image
from utils.utils import is_number, scheduler
from .goods_register import driver
from .group_user_checkin import (
check_in_all,
group_impression_rank,
group_user_check,
group_user_check_in,
impression_rank,
)
from .utils import clear_sign_data_pic
try:
import ujson as json
@ -49,22 +50,34 @@ __plugin_settings__ = {
}
__plugin_cd_limit__ = {}
__plugin_configs__ = {
"MAX_SIGN_GOLD": {"value": 200, "help": "签到好感度加成额外获得的最大金币数", "default_value": 200},
"SIGN_CARD1_PROB": {"value": 0.2, "help": "签到好感度双倍加持卡Ⅰ掉落概率", "default_value": 0.2},
"MAX_SIGN_GOLD": {
"value": 200,
"help": "签到好感度加成额外获得的最大金币数",
"default_value": 200,
"type": int,
},
"SIGN_CARD1_PROB": {
"value": 0.2,
"help": "签到好感度双倍加持卡Ⅰ掉落概率",
"default_value": 0.2,
"type": float,
},
"SIGN_CARD2_PROB": {
"value": 0.09,
"help": "签到好感度双倍加持卡Ⅱ掉落概率",
"default_value": 0.09,
"type": float,
},
"SIGN_CARD3_PROB": {
"value": 0.05,
"help": "签到好感度双倍加持卡Ⅲ掉落概率",
"default_value": 0.05,
"type": float,
},
}
_file = Path(f"{DATA_PATH}/not_show_sign_rank_user.json")
_file = DATA_PATH / "not_show_sign_rank_user.json"
try:
data = json.load(open(_file, "r", encoding="utf8"))
except (FileNotFoundError, ValueError, TypeError):

View File

@ -1,14 +1,17 @@
from nonebot import on_command
from nonebot.typing import T_State
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent
from .data_source import download_gocq_lasted, upload_gocq_lasted
from services.log import logger
from utils.utils import scheduler, get_bot
from nonebot.permission import SUPERUSER
from configs.config import Config
from pathlib import Path
import os
from pathlib import Path
from typing import List
from nonebot import on_command
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent
from nonebot.permission import SUPERUSER
from nonebot.typing import T_State
from configs.config import Config
from services.log import logger
from utils.utils import get_bot, scheduler
from .data_source import download_gocq_lasted, upload_gocq_lasted
__zx_plugin_name__ = "更新gocq [Superuser]"
__plugin_usage__ = """
@ -25,6 +28,7 @@ __plugin_configs__ = {
"value": [],
"help": "需要为哪些群更新最新版gocq吗上传最新版gocq示例[434995955, 239483248]",
"default_value": [],
"type": List[int],
}
}

View File

@ -1,12 +1,13 @@
from nonebot.adapters.onebot.v11 import Bot, MessageEvent
from nonebot.matcher import Matcher
from nonebot.message import IgnoredException, run_preprocessor
from nonebot.typing import T_State
from configs.config import Config as gConfig
from utils.manager import plugins2settings_manager
from .api import *
from .auth import *
from nonebot.matcher import Matcher
from nonebot.message import run_preprocessor, IgnoredException
from utils.manager import plugins2settings_manager
from nonebot.typing import T_State
from nonebot.adapters.onebot.v11 import Bot, MessageEvent
gConfig.add_plugin_config("web-ui", "username", "admin", name="web-ui", help_="前端管理用户名")

View File

@ -1,6 +1,9 @@
from pathlib import Path
import nonebot
from configs.config import Config
from utils.utils import GDict
import nonebot
Config.add_plugin_config(
"word_bank",
@ -8,9 +11,10 @@ Config.add_plugin_config(
5,
name="词库问答",
help_="设置增删词库的权限等级",
default_value=5
default_value=5,
type=int,
)
GDict['run_sql'].append("ALTER TABLE word_bank2 ADD to_me VARCHAR(255);")
GDict["run_sql"].append("ALTER TABLE word_bank2 ADD to_me VARCHAR(255);")
nonebot.load_plugins("plugins/word_bank")
nonebot.load_plugins(str(Path(__file__).parent.resolve()))

View File

@ -1,16 +1,19 @@
import re
from datetime import datetime, timedelta
from typing import Tuple, Union
import pytz
from nonebot import on_command, get_driver
from nonebot import get_driver, on_command
from nonebot.adapters.onebot.v11 import Message, MessageSegment
from nonebot.adapters.onebot.v11.event import GroupMessageEvent
from nonebot.matcher import Matcher
from nonebot.params import Arg, Command, CommandArg, Depends
from nonebot.typing import T_State
from .data_source import draw_word_cloud, get_list_msg
from configs.config import Config
from .data_source import draw_word_cloud, get_list_msg
__zx_plugin_name__ = "词云"
__plugin_usage__ = """
@ -60,13 +63,16 @@ wordcloud_cmd = on_command(
"我的本月词云",
"我的年度词云",
"我的历史词云",
}, block=True, priority=5
},
block=True,
priority=5,
)
Config.add_plugin_config(
"word_clouds",
"WORD_CLOUDS_TEMPLATE",
1,
help_="词云模板 参1图片生成默认使用真寻图片可在项目路径resources/image/wordcloud下配置图片多张则随机 | 参2/其他:黑底图片"
help_="词云模板 参1图片生成默认使用真寻图片可在项目路径resources/image/wordcloud下配置图片多张则随机 | 参2/其他:黑底图片",
type=int,
)
@ -74,9 +80,9 @@ def parse_datetime(key: str):
"""解析数字,并将结果存入 state 中"""
async def _key_parser(
matcher: Matcher,
state: T_State,
input_: Union[datetime, Message] = Arg(key),
matcher: Matcher,
state: T_State,
input_: Union[datetime, Message] = Arg(key),
):
if isinstance(input_, datetime):
return
@ -102,10 +108,10 @@ def get_datetime_fromisoformat_with_timezone(date_string: str) -> datetime:
@wordcloud_cmd.handle()
async def handle_first_receive(
event: GroupMessageEvent,
state: T_State,
commands: Tuple[str, ...] = Command(),
args: Message = CommandArg(),
event: GroupMessageEvent,
state: T_State,
commands: Tuple[str, ...] = Command(),
args: Message = CommandArg(),
):
command = commands[0]
@ -172,10 +178,10 @@ async def handle_first_receive(
parameterless=[Depends(parse_datetime("stop"))],
)
async def handle_message(
event: GroupMessageEvent,
start: datetime = Arg(),
stop: datetime = Arg(),
my: bool = Arg(),
event: GroupMessageEvent,
start: datetime = Arg(),
stop: datetime = Arg(),
my: bool = Arg(),
):
# 是否只查询自己的记录
if my:
@ -183,9 +189,14 @@ async def handle_message(
else:
user_id = None
# 将时间转换到 东八 时区
messages = await get_list_msg(user_id, int(event.group_id),
days=(start.astimezone(pytz.timezone("Asia/Shanghai")),
stop.astimezone(pytz.timezone("Asia/Shanghai"))))
messages = await get_list_msg(
user_id,
int(event.group_id),
days=(
start.astimezone(pytz.timezone("Asia/Shanghai")),
stop.astimezone(pytz.timezone("Asia/Shanghai")),
),
)
if messages:
image_bytes = await draw_word_cloud(messages, get_driver().config)
if image_bytes:

43
poetry.lock generated
View File

@ -254,6 +254,23 @@ type = "legacy"
url = "https://mirrors.aliyun.com/pypi/simple"
reference = "ali"
[[package]]
name = "cattrs"
version = "22.2.0"
description = "Composable complex class support for attrs and dataclasses."
category = "main"
optional = false
python-versions = ">=3.7"
[package.dependencies]
attrs = ">=20"
exceptiongroup = {version = "*", markers = "python_version < \"3.11\""}
[package.source]
type = "legacy"
url = "https://mirrors.aliyun.com/pypi/simple"
reference = "ali"
[[package]]
name = "certifi"
version = "2022.12.7"
@ -437,6 +454,22 @@ type = "legacy"
url = "https://mirrors.aliyun.com/pypi/simple"
reference = "ali"
[[package]]
name = "exceptiongroup"
version = "1.1.0"
description = "Backport of PEP 654 (exception groups)"
category = "main"
optional = false
python-versions = ">=3.7"
[package.extras]
test = ["pytest (>=6)"]
[package.source]
type = "legacy"
url = "https://mirrors.aliyun.com/pypi/simple"
reference = "ali"
[[package]]
name = "fastapi"
version = "0.88.0"
@ -1876,7 +1909,7 @@ reference = "ali"
[metadata]
lock-version = "1.1"
python-versions = "^3.8"
content-hash = "98eb1c3b662c674caee17f448657522b88489ea5b7ad13c5ccc02dde313ce7ab"
content-hash = "30f718b1d834abeaf0be2239ac66ebf40d71ca72b28ecea5b13d64aedeaaa6a9"
[metadata.files]
aiofiles = [
@ -2025,6 +2058,10 @@ cachetools = [
{file = "cachetools-5.2.0-py3-none-any.whl", hash = "sha256:f9f17d2aec496a9aa6b76f53e3b614c965223c061982d434d160f930c698a9db"},
{file = "cachetools-5.2.0.tar.gz", hash = "sha256:6a94c6402995a99c3970cc7e4884bb60b4a8639938157eeed436098bf9831757"},
]
cattrs = [
{file = "cattrs-22.2.0-py3-none-any.whl", hash = "sha256:bc12b1f0d000b9f9bee83335887d532a1d3e99a833d1bf0882151c97d3e68c21"},
{file = "cattrs-22.2.0.tar.gz", hash = "sha256:f0eed5642399423cf656e7b66ce92cdc5b963ecafd041d1b24d136fdde7acf6d"},
]
certifi = [
{file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"},
{file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"},
@ -2135,6 +2172,10 @@ ecdsa = [
emoji = [
{file = "emoji-1.7.0.tar.gz", hash = "sha256:65c54533ea3c78f30d0729288998715f418d7467de89ec258a31c0ce8660a1d1"},
]
exceptiongroup = [
{file = "exceptiongroup-1.1.0-py3-none-any.whl", hash = "sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e"},
{file = "exceptiongroup-1.1.0.tar.gz", hash = "sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23"},
]
fastapi = [
{file = "fastapi-0.88.0-py3-none-any.whl", hash = "sha256:263b718bb384422fe3d042ffc9a0c8dece5e034ab6586ff034f6b4b1667c3eee"},
{file = "fastapi-0.88.0.tar.gz", hash = "sha256:915bf304180a0e7c5605ec81097b7d4cd8826ff87a02bb198e336fb9f3b5ff02"},

View File

@ -45,6 +45,7 @@ nonebot-plugin-apscheduler = "^0.2.0"
nonebot-plugin-htmlrender = "^0.2.0"
cachetools = "^5.2.0"
tortoise-orm = {extras = ["asyncpg"], version = "^0.19.3"}
cattrs = "^22.2.0"
[tool.poetry.dev-dependencies]