feat✨: 更新内置插件

This commit is contained in:
HibiKier
2024-02-25 03:18:34 +08:00
parent 131200a28e
commit eb0572ea77
83 changed files with 7588 additions and 450 deletions
+160
View File
@@ -0,0 +1,160 @@
# from typing import Dict
# from services.db_context import Model
# from tortoise import fields
# from .goods_info import GoodsInfo
# class BagUser(Model):
# id = fields.IntField(pk=True, generated=True, auto_increment=True)
# """自增id"""
# user_id = fields.CharField(255)
# """用户id"""
# group_id = fields.CharField(255)
# """群聊id"""
# gold = fields.IntField(default=100)
# """金币数量"""
# spend_total_gold = fields.IntField(default=0)
# """花费金币总数"""
# get_total_gold = fields.IntField(default=0)
# """获取金币总数"""
# get_today_gold = fields.IntField(default=0)
# """今日获取金币"""
# spend_today_gold = fields.IntField(default=0)
# """今日获取金币"""
# property: Dict[str, int] = fields.JSONField(default={}) # type: ignore
# """道具"""
# class Meta:
# table = "bag_users"
# table_description = "用户道具数据表"
# unique_together = ("user_id", "group_id")
# @classmethod
# async def get_gold(cls, user_id: str, group_id: str) -> int:
# """获取当前金币
# 参数:
# user_id: 用户id
# group_id: 所在群组id
# 返回:
# int: 金币数量
# """
# user, _ = await cls.get_or_create(user_id=user_id, group_id=group_id)
# return user.gold
# @classmethod
# async def get_property(
# cls, user_id: str, group_id: str, only_active: bool = False
# ) -> Dict[str, int]:
# """获取当前道具
# 参数:
# user_id: 用户id
# group_id: 所在群组id
# only_active: 仅仅获取主动使用的道具
# 返回:
# Dict[str, int]: 道具名称与数量
# """
# user, _ = await cls.get_or_create(user_id=user_id, group_id=group_id)
# if only_active and user.property:
# data = {}
# name_list = [
# x.goods_name
# for x in await GoodsInfo.get_all_goods()
# if not x.is_passive
# ]
# for key in [x for x in user.property if x in name_list]:
# data[key] = user.property[key]
# return data
# return user.property
# @classmethod
# async def add_gold(cls, user_id: str, group_id: str, num: int):
# """增加金币
# 参数:
# user_id: 用户id
# group_id: 所在群组id
# num: 金币数量
# """
# user, _ = await cls.get_or_create(user_id=user_id, group_id=group_id)
# user.gold = user.gold + num
# user.get_total_gold = user.get_total_gold + num
# user.get_today_gold = user.get_today_gold + num
# await user.save(update_fields=["gold", "get_today_gold", "get_total_gold"])
# @classmethod
# async def spend_gold(cls, user_id: str, group_id: str, num: int):
# """花费金币
# 参数:
# user_id: 用户id
# group_id: 所在群组id
# num: 金币数量
# """
# user, _ = await cls.get_or_create(user_id=str(user_id), group_id=str(group_id))
# user.gold = user.gold - num
# user.spend_total_gold = user.spend_total_gold + num
# user.spend_today_gold = user.spend_today_gold + num
# await user.save(update_fields=["gold", "spend_total_gold", "spend_today_gold"])
# @classmethod
# async def add_property(cls, user_id: str, group_id: str, name: str, num: int = 1):
# """增加道具
# 参数:
# user_id: 用户id
# group_id: 所在群组id
# name: 道具名称
# num: 道具数量
# """
# user, _ = await cls.get_or_create(user_id=str(user_id), group_id=str(group_id))
# property_ = user.property
# if property_.get(name) is None:
# property_[name] = 0
# property_[name] += num
# user.property = property_
# await user.save(update_fields=["property"])
# @classmethod
# async def delete_property(
# cls, user_id: str, group_id: str, name: str, num: int = 1
# ) -> bool:
# """使用/删除 道具
# 参数:
# user_id: 用户id
# group_id: 所在群组id
# name: 道具名称
# num: 使用个数
# 返回:
# bool: 是否使用/删除成功
# """
# user, _ = await cls.get_or_create(user_id=str(user_id), group_id=str(group_id))
# property_ = user.property
# if name in property_:
# if (n := property_.get(name, 0)) < num:
# return False
# if n == num:
# del property_[name]
# else:
# property_[name] -= num
# await user.save(update_fields=["property"])
# return True
# return False
# @classmethod
# async def _run_script(cls):
# return [
# "ALTER TABLE bag_users DROP props;", # 删除 props 字段
# "ALTER TABLE bag_users RENAME COLUMN user_qq TO user_id;", # 将user_qq改为user_id
# "ALTER TABLE bag_users ALTER COLUMN user_id TYPE character varying(255);",
# # 将user_id字段类型改为character varying(255)
# "ALTER TABLE bag_users ALTER COLUMN group_id TYPE character varying(255);",
# ]
+172
View File
@@ -0,0 +1,172 @@
import time
from tortoise import fields
from typing_extensions import Self
from zhenxun.services.db_context import Model
from zhenxun.services.log import logger
from zhenxun.utils.exception import UserAndGroupIsNone
class BanConsole(Model):
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
user_id = fields.CharField(255, null=True)
"""用户id"""
group_id = fields.CharField(255, null=True)
"""群组id"""
ban_level = fields.IntField()
"""使用ban命令的用户等级"""
ban_time = fields.BigIntField()
"""ban开始的时间"""
duration = fields.BigIntField()
"""ban时长"""
operator = fields.CharField(255)
"""使用Ban命令的用户"""
class Meta:
table = "ban_console"
table_description = ".ban/b了 封禁人员/群组数据表"
@classmethod
async def _get_data(cls, user_id: str | None, group_id: str | None) -> Self | None:
"""获取数据
参数:
user_id: 用户id
group_id: 群组id
异常:
UserAndGroupIsNone: 用户id和群组id都为空
返回:
Self | None: Self
"""
if not user_id and not group_id:
raise UserAndGroupIsNone()
user = None
if user_id:
if group_id:
user = await cls.get_or_none(user_id=user_id, group_id=group_id)
else:
user = await cls.get_or_none(user_id=user_id, group_id__isnull=True)
else:
if group_id:
user = await cls.get_or_none(user_id__isnull=True, group_id=group_id)
return user
@classmethod
async def check_ban_level(
cls, user_id: str | None, group_id: str | None, level: int
) -> bool:
"""检测ban掉目标的用户与unban用户的权限等级大小
参数:
user_id: 用户id
group_id: 群组id
level: 权限等级
返回:
bool: 权限判断
"""
user = await cls._get_data(user_id, group_id)
if user:
logger.debug(
f"检测用户被ban等级,user_level: {user.ban_level},level: {level}",
target=f"{group_id}:{user_id}",
)
return bool(user and user.ban_level >= level)
return False
@classmethod
async def check_ban_time(
cls, user_id: str | None, group_id: str | None = None
) -> int:
"""检测用户被ban时长
参数:
user_id: 用户id
返回:
int: ban剩余时长,-1时为永久ban,0表示未被ban
"""
logger.debug(f"获取用户ban时长", target=f"{group_id}:{user_id}")
user = await cls._get_data(user_id, group_id)
if user:
if user.duration == -1:
return -1
_time = time.time() - (user.ban_time + user.duration)
if _time > 0:
return 0
return int(time.time() - user.ban_time - user.duration)
return 0
@classmethod
async def is_ban(cls, user_id: str | None, group_id: str | None = None) -> bool:
"""判断用户是否被ban
参数:
user_id: 用户id
返回:
bool: 是否被ban
"""
logger.debug(f"检测是否被ban", target=f"{group_id}:{user_id}")
if await cls.check_ban_time(user_id, group_id):
return True
else:
await cls.unban(user_id, group_id)
return False
@classmethod
async def ban(
cls,
user_id: str | None,
group_id: str | None,
ban_level: int,
duration: int,
operator: str | None,
):
"""ban掉目标用户
参数:
user_id: 用户id
group_id: 群组id
ban_level: 使用命令者的权限等级
duration: 时长,秒
operator: 操作者id
"""
logger.debug(
f"封禁用户,等级:{ban_level},时长: {duration}",
target=f"{group_id}:{user_id}",
)
user = await cls._get_data(user_id, group_id)
if user:
await cls.unban(user_id, group_id)
await cls.create(
user_id=user_id,
group_id=group_id,
ban_level=ban_level,
ban_time=int(time.time()),
duration=duration,
operator=operator or 0,
)
@classmethod
async def unban(cls, user_id: str | None, group_id: str | None = None) -> bool:
"""unban用户
参数:
user_id: 用户id
group_id: 群组id
返回:
bool: 是否被ban
"""
user = await cls._get_data(user_id, group_id)
if user:
logger.debug("解除封禁", target=f"{group_id}:{user_id}")
await user.delete()
return True
return False
+125
View File
@@ -0,0 +1,125 @@
from datetime import datetime, timedelta
from typing import Literal, Tuple
from tortoise import fields
from tortoise.functions import Count
from typing_extensions import Self
from zhenxun.services.db_context import Model
class ChatHistory(Model):
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
user_id = fields.CharField(255)
"""用户id"""
group_id = fields.CharField(255, null=True)
"""群聊id"""
text = fields.TextField(null=True)
"""文本内容"""
plain_text = fields.TextField(null=True)
"""纯文本"""
create_time = fields.DatetimeField(auto_now_add=True)
"""创建时间"""
bot_id = fields.CharField(255, null=True)
"""bot记录id"""
platform = fields.CharField(255, null=True)
"""平台"""
class Meta:
table = "chat_history"
table_description = "聊天记录数据表"
@classmethod
async def get_group_msg_rank(
cls,
gid: str,
limit: int = 10,
order: str = "DESC",
date_scope: tuple[datetime, datetime] | None = None,
) -> list[Self]:
"""获取排行数据
参数:
gid: 群号
limit: 获取数量
order: 排序类型,desc,des
date_scope: 日期范围
"""
o = "-" if order == "DESC" else ""
query = cls.filter(group_id=gid)
if date_scope:
query = query.filter(create_time__range=date_scope)
return list(
await query.annotate(count=Count("user_id"))
.order_by(o + "count")
.group_by("user_id")
.limit(limit)
.values_list("user_id", "count")
) # type: ignore
@classmethod
async def get_group_first_msg_datetime(cls, group_id: str) -> datetime | None:
"""获取群第一条记录消息时间
参数:
group_id: 群组id
"""
if (
message := await cls.filter(group_id=group_id)
.order_by("create_time")
.first()
):
return message.create_time
@classmethod
async def get_message(
cls,
uid: str,
gid: str,
type_: Literal["user", "group"],
msg_type: Literal["private", "group"] | None = None,
days: int | Tuple[datetime, datetime] | None = None,
) -> list[Self]:
"""获取消息查询query
参数:
uid: 用户id
gid: 群聊id
type_: 类型,私聊或群聊
msg_type: 消息类型,用户或群聊
days: 限制日期
"""
if type_ == "user":
query = cls.filter(user_id=uid)
if msg_type == "private":
query = query.filter(group_id__isnull=True)
elif msg_type == "group":
query = query.filter(group_id__not_isnull=True)
else:
query = cls.filter(group_id=gid)
if uid:
query = query.filter(user_id=uid)
if days:
if isinstance(days, int):
query = query.filter(
create_time__gte=datetime.now() - timedelta(days=days)
)
elif isinstance(days, tuple):
query = query.filter(create_time__range=days)
return await query.all() # type: ignore
@classmethod
async def _run_script(cls):
return [
"alter table chat_history alter group_id drop not null;", # 允许 group_id 为空
"alter table chat_history alter text drop not null;", # 允许 text 为空
"alter table chat_history alter plain_text drop not null;", # 允许 plain_text 为空
"ALTER TABLE chat_history RENAME COLUMN user_qq TO user_id;", # 将user_id改为user_id
"ALTER TABLE chat_history ALTER COLUMN user_id TYPE character varying(255);",
"ALTER TABLE chat_history ALTER COLUMN group_id TYPE character varying(255);",
"ALTER TABLE chat_history ADD bot_id VARCHAR(255);", # 添加bot_id字段
"ALTER TABLE chat_history ALTER COLUMN bot_id TYPE character varying(255);",
"ALTER TABLE chat_history ADD COLUMN platform character varying(255);",
]
+37 -24
View File
@@ -15,32 +15,32 @@ class FriendUser(Model):
"""用户名称"""
nickname = fields.CharField(max_length=255, null=True, description="用户自定义昵称")
"""私聊下自定义昵称"""
platform = fields.CharField(255, null=True, description="平台")
"""平台"""
class Meta:
table = "friend_users"
table_description = "好友信息数据表"
@classmethod
async def get_user_name(cls, user_id: Union[int, str]) -> str:
"""
说明:
获取好友用户名称
async def get_user_name(cls, user_id: str) -> str:
"""获取好友用户名称
参数:
:param user_id: 用户id
user_id: 用户id
"""
if user := await cls.get_or_none(user_id=str(user_id)):
if user := await cls.get_or_none(user_id=user_id):
return user.user_name
return ""
@classmethod
async def get_user_nickname(cls, user_id: Union[int, str]) -> str:
"""
说明:
获取用户昵称
async def get_user_nickname(cls, user_id: str) -> str:
"""获取用户昵称
参数:
:param user_id: 用户id
user_id: 用户id
"""
if user := await cls.get_or_none(user_id=str(user_id)):
if user := await cls.get_or_none(user_id=user_id):
if user.nickname:
_tmp = ""
if black_word := Config.get_config("nickname", "BLACK_WORD"):
@@ -50,21 +50,34 @@ class FriendUser(Model):
return ""
@classmethod
async def set_user_nickname(cls, user_id: Union[int, str], nickname: str):
"""
说明:
设置用户昵称
async def set_user_nickname(
cls,
user_id: str,
nickname: str,
uname: str | None = None,
platform: str | None = None,
):
"""设置用户昵称
参数:
:param user_id: 用户id
:param nickname: 昵称
user_id: 用户id
nickname: 昵称
uname: 用户昵称
platform: 平台
"""
defaults = {"nickname": nickname}
if uname is not None:
defaults["user_name"] = uname
if platform is not None:
defaults["platform"] = platform
await cls.update_or_create(
user_id=str(user_id), defaults={"nickname": nickname}
user_id=user_id,
defaults=defaults,
)
@classmethod
async def _run_script(cls):
await cls.raw(
"ALTER TABLE friend_users ALTER COLUMN user_id TYPE character varying(255);"
)
# 将user_id字段类型改为character varying(255))
def _run_script(cls):
return [
"ALTER TABLE friend_users ALTER COLUMN user_id TYPE character varying(255);",
"ALTER TABLE friend_users ADD COLUMN platform character varying(255) default 'qq';",
]
+162
View File
@@ -0,0 +1,162 @@
import uuid
from typing import Dict
from tortoise import fields
from typing_extensions import Self
from zhenxun.services.db_context import Model
class GoodsInfo(Model):
__tablename__ = "goods_info"
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
uuid = fields.CharField(255, null=True)
"""uuid"""
goods_name = fields.CharField(255, unique=True)
"""商品名称"""
goods_price = fields.IntField()
"""价格"""
goods_description = fields.TextField()
"""描述"""
goods_discount = fields.FloatField(default=1)
"""折扣"""
goods_limit_time = fields.BigIntField(default=0)
"""限时"""
daily_limit = fields.IntField(default=0)
"""每日限购"""
is_passive = fields.BooleanField(default=False)
"""是否为被动道具"""
icon = fields.TextField(null=True)
"""图标路径"""
class Meta:
table = "goods_info"
table_description = "商品数据表"
@classmethod
async def add_goods(
cls,
goods_name: str,
goods_price: int,
goods_description: str,
goods_discount: float = 1,
goods_limit_time: int = 0,
daily_limit: int = 0,
is_passive: bool = False,
icon: str | None = None,
):
"""添加商品
参数:
goods_name: 商品名称
goods_price: 商品价格
goods_description: 商品简介
goods_discount: 商品折扣
goods_limit_time: 商品限时
daily_limit: 每日购买限制
is_passive: 是否为被动道具
icon: 图标
"""
if not await cls.exists(goods_name=goods_name):
await cls.create(
uuid=uuid.uuid1(),
goods_name=goods_name,
goods_price=goods_price,
goods_description=goods_description,
goods_discount=goods_discount,
goods_limit_time=goods_limit_time,
daily_limit=daily_limit,
is_passive=is_passive,
icon=icon,
)
@classmethod
async def delete_goods(cls, goods_name: str) -> bool:
"""删除商品
参数:
goods_name: 商品名称
返回:
bool: 是否删除成功
"""
if goods := await cls.get_or_none(goods_name=goods_name):
await goods.delete()
return True
return False
@classmethod
async def update_goods(
cls,
goods_name: str,
goods_price: int | None = None,
goods_description: str | None = None,
goods_discount: float | None = None,
goods_limit_time: int | None = None,
daily_limit: int | None = None,
is_passive: bool | None = None,
icon: str | None = None,
):
"""更新商品信息
参数:
goods_name: 商品名称
goods_price: 商品价格
goods_description: 商品简介
goods_discount: 商品折扣
goods_limit_time: 商品限时时间
daily_limit: 每日次数限制
is_passive: 是否为被动
icon: 图标
"""
if goods := await cls.get_or_none(goods_name=goods_name):
await cls.update_or_create(
goods_name=goods_name,
defaults={
"goods_price": goods_price or goods.goods_price,
"goods_description": goods_description or goods.goods_description,
"goods_discount": goods_discount or goods.goods_discount,
"goods_limit_time": (
goods_limit_time
if goods_limit_time is not None
else goods.goods_limit_time
),
"daily_limit": (
daily_limit if daily_limit is not None else goods.daily_limit
),
"is_passive": (
is_passive if is_passive is not None else goods.is_passive
),
"icon": icon or goods.icon,
},
)
@classmethod
async def get_all_goods(cls) -> list[Self]:
"""
获得全部有序商品对象
"""
query = await cls.all()
id_lst = [x.id for x in query]
goods_lst = []
for _ in range(len(query)):
min_id = min(id_lst)
goods_lst.append([x for x in query if x.id == min_id][0])
id_lst.remove(min_id)
return goods_lst
@classmethod
async def _run_script(cls):
if goods_list := await cls.filter(uuid__isnull=True).all():
for goods in goods_list:
goods.uuid = uuid.uuid1()
await cls.bulk_update(goods_list, ["uuid"], 10)
return [
"ALTER TABLE goods_info ADD uuid VARCHAR(255);",
"ALTER TABLE goods_info ADD daily_limit Integer DEFAULT 0;",
"ALTER TABLE goods_info ADD is_passive boolean DEFAULT False;",
"ALTER TABLE goods_info ADD icon VARCHAR(255);",
"ALTER TABLE goods_info DROP daily_purchase_limit;", # 删除 daily_purchase_limit 字段
]
+54
View File
@@ -0,0 +1,54 @@
from tortoise import fields
from zhenxun.services.db_context import Model
class GroupConsole(Model):
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
group_id = fields.CharField(255, description="群组id")
"""群聊id"""
channel_id = fields.CharField(255, null=True, description="频道id")
"""频道id"""
group_name = fields.TextField(default="", description="群组名称")
"""群聊名称"""
max_member_count = fields.IntField(default=0, description="最大人数")
"""最大人数"""
member_count = fields.IntField(default=0, description="当前人数")
"""当前人数"""
group_flag = fields.IntField(default=0, description="群认证标记")
"""群认证标记"""
block_plugin = fields.TextField(default="", description="禁用插件")
"""禁用插件"""
block_task = fields.TextField(default="", description="禁用插件")
"""禁用插件"""
platform = fields.CharField(255, default="qq", description="所属平台")
"""所属平台"""
class Meta:
table = "group_console"
table_description = "群组信息表"
unique_together = ("group_id", "channel_id")
@classmethod
async def is_block_task(
cls, group_id: str, task: str, channel_id: str | None = None
) -> bool:
"""查看群组是否禁用被动
参数:
group_id: 群组id
task: 任务模块
channel_id: 频道id
返回:
bool: 是否禁用被动
"""
return await cls.exists(
group_id=group_id, channel_id=channel_id, block_task__contains=f"{task},"
)
@classmethod
def _run_script(cls):
return []
-31
View File
@@ -1,31 +0,0 @@
from typing import List, Optional
from tortoise import fields
from zhenxun.services.db_context import Model
from zhenxun.services.log import logger
class GroupInfo(Model):
group_id = fields.CharField(255, pk=True)
"""群聊id"""
group_name = fields.TextField(default="")
"""群聊名称"""
max_member_count = fields.IntField(default=0)
"""最大人数"""
member_count = fields.IntField(default=0)
"""当前人数"""
group_flag = fields.IntField(default=0)
"""群认证标记"""
class Meta:
table = "group_info"
table_description = "群聊信息表"
@classmethod
def _run_script(cls):
return [
"ALTER TABLE group_info ADD group_flag Integer NOT NULL DEFAULT 0;", # group_info表添加一个group_flag
"ALTER TABLE group_info ALTER COLUMN group_id TYPE character varying(255);"
# 将group_id字段类型改为character varying(255)
]
+25 -4
View File
@@ -1,5 +1,3 @@
from typing import List, Optional
from tortoise import fields
from zhenxun.services.db_context import Model
@@ -8,6 +6,8 @@ from zhenxun.services.db_context import Model
class GroupInfo(Model):
group_id = fields.CharField(255, pk=True, description="群组id")
"""群聊id"""
# channel_id = fields.CharField(255, description="群组id")
# """频道id"""
group_name = fields.TextField(default="", description="群组名称")
"""群聊名称"""
max_member_count = fields.IntField(default=0, description="最大人数")
@@ -16,15 +16,36 @@ class GroupInfo(Model):
"""当前人数"""
group_flag = fields.IntField(default=0, description="群认证标记")
"""群认证标记"""
block_plugin = fields.TextField(default="", description="禁用插件")
"""禁用插件"""
block_task = fields.TextField(default="", description="禁用插件")
"""禁用插件"""
platform = fields.CharField(255, default="qq", description="所属平台")
"""所属平台"""
class Meta:
table = "group_info"
table_description = "群聊信息表"
@classmethod
async def is_block_task(cls, group_id: str, task: str) -> bool:
"""查看群组是否禁用被动
参数:
group_id: 群组id
task: 任务模块
返回:
bool: 是否禁用被动
"""
return await cls.exists(group_id=group_id, block_task__contains=f"{task},")
@classmethod
def _run_script(cls):
return [
"ALTER TABLE group_info ADD group_flag Integer NOT NULL DEFAULT 0;", # group_info表添加一个group_flag
"ALTER TABLE group_info ALTER COLUMN group_id TYPE character varying(255);"
# 将group_id字段类型改为character varying(255)
"ALTER TABLE group_info ALTER COLUMN group_id TYPE character varying(255);",
"ALTER TABLE group_info ADD block_plugin Text NOT NULL DEFAULT '';",
"ALTER TABLE group_info ADD block_task Text NOT NULL DEFAULT '';",
"ALTER TABLE group_info ADD platform character varying(255) NOT NULL DEFAULT 'qq';",
]
+41 -55
View File
@@ -1,9 +1,8 @@
from datetime import datetime
from typing import List, Optional, Set, Union
from typing import Set
from tortoise import fields
from zhenxun.configs.config import Config
from zhenxun.services.db_context import Model
from zhenxun.services.log import logger
@@ -23,6 +22,8 @@ class GroupInfoUser(Model):
"""群聊昵称"""
uid = fields.BigIntField(null=True)
"""用户uid"""
platform = fields.CharField(255, null=True, description="平台")
"""平台"""
class Meta:
table = "group_info_users"
@@ -30,59 +31,65 @@ class GroupInfoUser(Model):
unique_together = ("user_id", "group_id")
@classmethod
async def get_group_member_id_list(cls, group_id: Union[int, str]) -> Set[int]:
"""
说明:
获取该群所有用户id
async def get_group_member_id_list(cls, group_id: str) -> Set[int]:
"""获取该群所有用户id
参数:
:param group_id: 群号
group_id: 群号
"""
return set(
await cls.filter(group_id=str(group_id)).values_list("user_id", flat=True)
await cls.filter(group_id=group_id).values_list("user_id", flat=True)
) # type: ignore
@classmethod
async def set_user_nickname(
cls, user_id: Union[int, str], group_id: Union[int, str], nickname: str
cls,
user_id: str,
group_id: str,
nickname: str,
uname: str | None = None,
platform: str | None = None,
):
"""
说明:
设置群员在该群内的昵称
"""设置群员在该群内的昵称
参数:
:param user_id: 用户id
:param group_id: 群号
:param nickname: 昵称
user_id: 用户id
group_id: 群号
nickname: 昵称
uname: 用户昵称
platform: 平台
"""
defaults = {"nickname": nickname}
if uname is not None:
defaults["user_name"] = uname
if platform is not None:
defaults["platform"] = platform
await cls.update_or_create(
user_id=str(user_id),
group_id=str(group_id),
defaults={"nickname": nickname},
user_id=user_id,
group_id=group_id,
defaults=defaults,
)
@classmethod
async def get_user_all_group(cls, user_id: Union[int, str]) -> List[int]:
"""
说明:
获取该用户所在的所有群聊
async def get_user_all_group(cls, user_id: str) -> list[int]:
"""获取该用户所在的所有群聊
参数:
:param user_id: 用户id
user_id: 用户id
"""
return list(
await cls.filter(user_id=str(user_id)).values_list("group_id", flat=True)
) # type: ignore
@classmethod
async def get_user_nickname(
cls, user_id: Union[int, str], group_id: Union[int, str]
) -> str:
"""
说明:
获取用户在该群的昵称
async def get_user_nickname(cls, user_id: str, group_id: str) -> str:
"""获取用户在该群的昵称
参数:
:param user_id: 用户id
:param group_id: 群号
user_id: 用户id
group_id: 群号
"""
if user := await cls.get_or_none(user_id=str(user_id), group_id=str(group_id)):
if user := await cls.get_or_none(user_id=user_id, group_id=group_id):
if user.nickname:
nickname = ""
if black_word := Config.get_config("nickname", "BLACK_WORD"):
@@ -92,28 +99,6 @@ class GroupInfoUser(Model):
return user.nickname
return ""
@classmethod
async def get_group_member_uid(
cls, user_id: Union[int, str], group_id: Union[int, str]
) -> Optional[int]:
logger.debug(
f"GroupInfoUser 尝试获取 用户[<u><e>{user_id}</e></u>] 群聊[<u><e>{group_id}</e></u>] UID"
)
user, _ = await cls.get_or_create(user_id=str(user_id), group_id=str(group_id))
_max_uid_user, _ = await cls.get_or_create(user_id="114514", group_id="114514")
_max_uid = _max_uid_user.uid
if not user.uid:
all_user = await cls.filter(user_id=str(user_id)).all()
for x in all_user:
if x.uid:
return x.uid
user.uid = _max_uid + 1
_max_uid_user.uid = _max_uid + 1
await cls.bulk_update([user, _max_uid_user], ["uid"])
logger.debug(
f"GroupInfoUser 获取 用户[<u><e>{user_id}</e></u>] 群聊[<u><e>{group_id}</e></u>] UID: {user.uid}"
)
return user.uid
@classmethod
async def _run_script(cls):
@@ -124,4 +109,5 @@ class GroupInfoUser(Model):
"ALTER TABLE group_info_users ALTER COLUMN user_id TYPE character varying(255);",
# 将user_id字段类型改为character varying(255)
"ALTER TABLE group_info_users ALTER COLUMN group_id TYPE character varying(255);",
"ALTER TABLE group_info_users ADD COLUMN platform character varying(255) default 'qq';",
]
+20 -27
View File
@@ -24,9 +24,8 @@ class LevelUser(Model):
unique_together = ("user_id", "group_id")
@classmethod
async def get_user_level(cls, user_id: int | str, group_id: int | str) -> int:
"""
获取用户在群内的等级
async def get_user_level(cls, user_id: str, group_id: str | None) -> int:
"""获取用户在群内的等级
参数:
user_id: 用户id
@@ -35,20 +34,21 @@ class LevelUser(Model):
返回:
int: 权限等级
"""
if user := await cls.get_or_none(user_id=str(user_id), group_id=str(group_id)):
if not group_id:
return 0
if user := await cls.get_or_none(user_id=user_id, group_id=group_id):
return user.user_level
return 0
@classmethod
async def set_level(
cls,
user_id: int | str,
group_id: int | str,
user_id: str,
group_id: str,
level: int,
group_flag: int = 0,
):
"""
设置用户在群内的权限
"""设置用户在群内的权限
参数:
user_id: 用户id
@@ -57,8 +57,8 @@ class LevelUser(Model):
group_flag: 是否被自动更新刷新权限 0:是, 1:否.
"""
await cls.update_or_create(
user_id=str(user_id),
group_id=str(group_id),
user_id=user_id,
group_id=group_id,
defaults={
"user_level": level,
"group_flag": group_flag,
@@ -66,9 +66,8 @@ class LevelUser(Model):
)
@classmethod
async def delete_level(cls, user_id: int | str, group_id: int | str) -> bool:
"""
删除用户权限
async def delete_level(cls, user_id: str, group_id: str) -> bool:
"""删除用户权限
参数:
user_id: 用户id
@@ -77,17 +76,14 @@ class LevelUser(Model):
返回:
bool: 是否含有用户权限
"""
if user := await cls.get_or_none(user_id=str(user_id), group_id=str(group_id)):
if user := await cls.get_or_none(user_id=user_id, group_id=group_id):
await user.delete()
return True
return False
@classmethod
async def check_level(
cls, user_id: int | str, group_id: int | str, level: int
) -> bool:
"""
检查用户权限等级是否大于 level
async def check_level(cls, user_id: str, group_id: str, level: int) -> bool:
"""检查用户权限等级是否大于 level
参数:
user_id: 用户id
@@ -98,20 +94,17 @@ class LevelUser(Model):
bool: 是否大于level
"""
if group_id:
if user := await cls.get_or_none(
user_id=str(user_id), group_id=str(group_id)
):
if user := await cls.get_or_none(user_id=user_id, group_id=group_id):
return user.user_level >= level
else:
user_list = await cls.filter(user_id=str(user_id)).all()
user_list = await cls.filter(user_id=user_id).all()
user = max(user_list, key=lambda x: x.user_level)
return user.user_level >= level
return False
@classmethod
async def is_group_flag(cls, user_id: int | str, group_id: int | str) -> bool:
"""
检测是否会被自动更新刷新权限
async def is_group_flag(cls, user_id: str, group_id: str) -> bool:
"""检测是否会被自动更新刷新权限
参数:
user_id: 用户id
@@ -120,7 +113,7 @@ class LevelUser(Model):
返回:
bool: 是否会被自动更新权限刷新
"""
if user := await cls.get_or_none(user_id=str(user_id), group_id=str(group_id)):
if user := await cls.get_or_none(user_id=user_id, group_id=group_id):
return user.group_flag == 1
return False
+1 -1
View File
@@ -17,7 +17,7 @@ class PluginInfo(Model):
"""插件名称"""
status = fields.BooleanField(default=True, description="全局开关状态")
"""全局开关状态"""
block_type = fields.CharEnumField(
block_type: BlockType | None = fields.CharEnumField(
BlockType, default=None, null=True, description="禁用类型"
)
"""禁用类型"""
+1
View File
@@ -22,6 +22,7 @@ class PluginLimit(Model):
on_delete=fields.CASCADE,
description="所属插件",
)
"""所属插件"""
limit_type = fields.CharEnumField(PluginLimitType, description="限制类型")
"""限制类型"""
watch_type = fields.CharEnumField(LimitWatchType, description="监听类型")
+26
View File
@@ -0,0 +1,26 @@
from datetime import datetime
from typing import List, Literal, Optional, Tuple, Union
from tortoise import fields
from zhenxun.services.db_context import Model
class SignLog(Model):
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
user_id = fields.CharField(255, unique=True, description="用户id")
"""用户id"""
impression = fields.DecimalField(10, 3, default=0, description="好感度")
"""好感度"""
create_time = fields.DatetimeField(auto_now_add=True, description="创建时间")
"""创建时间"""
bot_id = fields.CharField(255, null=True, description="botId")
"""bot记录id"""
platform = fields.CharField(255, null=True, description="平台")
"""平台"""
class Meta:
table = "sign_log"
table_description = "用户签到记录表"
+72
View File
@@ -0,0 +1,72 @@
from tortoise import fields
from typing_extensions import Self
from zhenxun.services.db_context import Model
from .sign_log import SignLog
from .user_console import UserConsole
class SignUser(Model):
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
user_id = fields.CharField(255, unique=True, description="用户id")
"""用户id"""
sign_count = fields.IntField(default=0, description="签到次数")
"""签到次数"""
impression = fields.DecimalField(10, 3, default=0, description="好感度")
"""好感度"""
user_console: fields.OneToOneRelation[UserConsole] = fields.OneToOneField(
"models.UserConsole", related_name="user_console", description="用户数据"
)
"""用户数据"""
add_probability = fields.DecimalField(
10, 3, default=0, description="双倍签到增加概率"
)
"""双倍签到增加概率"""
specify_probability = fields.DecimalField(
10, 3, default=0, description="指定双倍概率"
)
"""使用指定双倍概率"""
platform = fields.CharField(255, null=True, description="平台")
"""平台"""
class Meta:
table = "sign_users"
table_description = "用户签到数据表"
@classmethod
async def sign(
cls,
user_id: str | Self,
impression: float,
bot_id: str | None = None,
platform: str | None = None,
) -> Self:
"""签到
参数:
user_id: 用户id
impression: 好感度
bot_id: bot Id
platform: 平台
"""
if isinstance(user_id, SignUser):
user = user_id
else:
user, _ = await cls.get_or_create(
user_id=user_id, defaults={"platform": platform}
)
user.impression = float(user.impression) + impression
user.add_probability = 0
user.specify_probability = 0
user.sign_count += 1
await user.save()
await SignLog.create(
user_id=user.user_id,
impression=impression,
bot_id=bot_id,
platform=platform,
)
return user
+22
View File
@@ -0,0 +1,22 @@
from tortoise import fields
from zhenxun.services.db_context import Model
class TaskInfo(Model):
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
module = fields.CharField(255, description="被动技能模块名")
"""被动技能模块名"""
name = fields.CharField(255, description="被动技能名称")
"""被动技能名称"""
status = fields.BooleanField(default=True, description="全局开关状态")
"""全局开关状态"""
run_time = fields.CharField(255, null=True, description="运行时间")
"""运行时间"""
run_count = fields.IntField(default=0, description="运行次数")
"""运行次数"""
class Meta:
table = "task_info"
table_description = "被动技能基本信息"
+79
View File
@@ -0,0 +1,79 @@
from typing import Dict
from tortoise import fields
from zhenxun.services.db_context import Model
from zhenxun.utils.enum import GoldHandle
from .user_gold_log import UserGoldLog
class UserConsole(Model):
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
user_id = fields.CharField(255, unique=True, description="用户id")
"""用户id"""
uid = fields.IntField(description="UID")
"""UID"""
gold = fields.IntField(default=100, description="金币数量")
"""金币数量"""
sign = fields.ReverseRelation["SignUser"] # type: ignore
"""好感度"""
props: Dict[str, int] = fields.JSONField(default={}) # type: ignore
"""道具"""
platform = fields.CharField(255, null=True, description="平台")
"""平台"""
create_time = fields.DatetimeField(auto_now_add=True, description="创建时间")
"""创建时间"""
class Meta:
table = "user_console"
table_description = "用户数据表"
@classmethod
async def get_new_uid(cls):
if user := await cls.annotate().order_by("uid").first():
return user.uid + 1
return 1
@classmethod
async def add_gold(
cls, user_id: str, gold: int, source: str, platform: str | None = None
):
"""添加金币
参数:
user_id: 用户id
gold: 金币
source: 来源
platform: 平台.
"""
user, _ = await cls.get_or_create(
user_id=user_id, defaults={"platform": platform, "uid": cls.get_new_uid()}
)
user.gold += gold
await user.save(update_fields=["gold"])
await UserGoldLog.create(
user_id=user_id, gold=gold, handle=GoldHandle.GET, source=source
)
@classmethod
async def add_props(
cls, user_id: str, goods_uuid: str, num: int = 1, platform: str | None = None
):
"""添加道具
参数:
user_id: 用户id
goods_uuid: 道具uuid
num: 道具数量.
platform: 平台.
"""
user, _ = await cls.get_or_create(
user_id=user_id, defaults={"platform": platform, "uid": cls.get_new_uid()}
)
if goods_uuid not in user.props:
user.props[goods_uuid] = 0
user.props[goods_uuid] += num
await user.save(update_fields=["props"])
+24
View File
@@ -0,0 +1,24 @@
from tortoise import fields
from zhenxun.services.db_context import Model
from zhenxun.utils.enum import GoldHandle
class UserGoldLog(Model):
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
user_id = fields.CharField(255, description="用户id")
"""用户id"""
gold = fields.IntField(description="金币")
"""金币"""
handle = fields.CharEnumField(GoldHandle, default=None, description="道具处理类型")
"""金币处理类型"""
source = fields.CharField(255, null=True, description="来源插件")
"""来源插件"""
create_time = fields.DatetimeField(auto_now_add=True, description="创建时间")
"""创建时间"""
class Meta:
table = "user_gold_log"
table_description = "用户金币记录表"
+25
View File
@@ -0,0 +1,25 @@
from typing import Dict
from tortoise import fields
from zhenxun.services.db_context import Model
from .sign_user import SignUser
class UserProps(Model):
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
user_id = fields.CharField(255, unique=True, description="用户id")
"""用户id"""
name = fields.CharField(255, description="道具名称")
"""道具名称"""
property: Dict[str, int] = fields.JSONField(default={}) # type: ignore
"""道具"""
platform = fields.CharField(255, null=True)
"""平台"""
class Meta:
table = "user_props"
table_description = "用户道具表"
+30
View File
@@ -0,0 +1,30 @@
from typing import Dict
from tortoise import fields
from zhenxun.services.db_context import Model
from zhenxun.utils.enum import PropHandle
from .sign_user import SignUser
class UserPropsLog(Model):
id = fields.IntField(pk=True, generated=True, auto_increment=True)
"""自增id"""
user_id = fields.CharField(255, description="用户id")
"""用户id"""
uuid = fields.CharField(255, description="道具uuid")
"""道具uuid"""
num = fields.IntField(null=True, description="道具金币")
"""数量"""
gold = fields.IntField(null=True, description="道具金币")
"""道具金币"""
handle = fields.CharEnumField(PropHandle, default=None, description="道具处理类型")
"""道具处理类型"""
create_time = fields.DatetimeField(auto_now_add=True, description="创建时间")
"""创建时间"""
class Meta:
table = "user_props_log"
table_description = "用户道具记录表"