feat(plugins,models): 加了今日老婆插件还有群成员信息字段
Some checks are pending
Auto Deploy NeoBot (FRP + SSH 密码登录) / deploy-to-server (push) Waiting to run
Some checks are pending
Auto Deploy NeoBot (FRP + SSH 密码登录) / deploy-to-server (push) Waiting to run
1. 新增daily_wife插件,群里每天随机配对群友 2. 给GroupMemberInfo加了QQ等级和是否机器人的字段 3. 改了群成员API的缓存和字段过滤逻辑 4. 更新了反馈数据和更新日志页面
This commit is contained in:
2
main.py
2
main.py
@@ -15,7 +15,7 @@ ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
SRC_DIR = os.path.join(ROOT_DIR, "src")
|
||||
sys.path.insert(0, SRC_DIR)
|
||||
|
||||
# 初始化日志系统,必须在其他 neobot 模块导入之前执行
|
||||
# 初始化日志系统,必须在其他 neobot 模块导入之前执行,改了我就操死你
|
||||
from neobot.core.utils.logger import logger
|
||||
|
||||
# 核心模块导入
|
||||
|
||||
BIN
requirements.txt
BIN
requirements.txt
Binary file not shown.
@@ -217,17 +217,6 @@ class GroupAPI(BaseAPI):
|
||||
return []
|
||||
|
||||
async def get_group_member_info(self, group_id: int, user_id: int, no_cache: bool = False) -> GroupMemberInfo:
|
||||
"""
|
||||
获取指定群组成员的详细信息。
|
||||
|
||||
Args:
|
||||
group_id (int): 目标群组的群号。
|
||||
user_id (int): 目标成员的 QQ 号。
|
||||
no_cache (bool, optional): 是否不使用缓存。Defaults to False.
|
||||
|
||||
Returns:
|
||||
GroupMemberInfo: 包含群成员信息的 `GroupMemberInfo` 数据对象。
|
||||
"""
|
||||
cache_key = f"neobot:cache:get_group_member_info:{group_id}:{user_id}"
|
||||
if not no_cache:
|
||||
cached_data = await redis_manager.redis.get(cache_key)
|
||||
@@ -235,21 +224,14 @@ class GroupAPI(BaseAPI):
|
||||
return GroupMemberInfo(**orjson.loads(cached_data))
|
||||
|
||||
res = await self.call_api("get_group_member_info", {"group_id": group_id, "user_id": user_id})
|
||||
await redis_manager.redis.set(cache_key, orjson.dumps(res), ex=3600) # 缓存 1 小时
|
||||
return GroupMemberInfo(**res)
|
||||
await redis_manager.redis.set(cache_key, orjson.dumps(res), ex=3600)
|
||||
valid_fields = GroupMemberInfo.__dataclass_fields__
|
||||
return GroupMemberInfo(**{k: v for k, v in res.items() if k in valid_fields})
|
||||
|
||||
async def get_group_member_list(self, group_id: int) -> List[GroupMemberInfo]:
|
||||
"""
|
||||
获取一个群组的所有成员列表。
|
||||
|
||||
Args:
|
||||
group_id (int): 目标群组的群号。
|
||||
|
||||
Returns:
|
||||
List[GroupMemberInfo]: 包含所有群成员信息的 `GroupMemberInfo` 对象列表。
|
||||
"""
|
||||
res = await self.call_api("get_group_member_list", {"group_id": group_id})
|
||||
return [GroupMemberInfo(**item) for item in res]
|
||||
valid_fields = GroupMemberInfo.__dataclass_fields__
|
||||
return [GroupMemberInfo(**{k: v for k, v in item.items() if k in valid_fields}) for item in res]
|
||||
|
||||
async def get_group_honor_info(self, group_id: int, type: str) -> GroupHonorInfo:
|
||||
"""
|
||||
|
||||
@@ -52,5 +52,23 @@
|
||||
"time": 1778727344,
|
||||
"time_str": "2026-05-14 10:55:44",
|
||||
"done": false
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"user_id": 3678069648,
|
||||
"nickname": "awedwd",
|
||||
"content": "添加一个v我50自动打50块钱进我银行卡功能",
|
||||
"time": 1778815461,
|
||||
"time_str": "2026-05-15 11:24:21",
|
||||
"done": false
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"user_id": 2771135787,
|
||||
"nickname": "数无形时少直觉,形少数时",
|
||||
"content": "<玩原神>",
|
||||
"time": 1778816520,
|
||||
"time_str": "2026-05-15 11:42:00",
|
||||
"done": false
|
||||
}
|
||||
]
|
||||
@@ -81,6 +81,12 @@ class GroupMemberInfo:
|
||||
card_changeable: bool = False
|
||||
"""是否允许修改群名片"""
|
||||
|
||||
qq_level: str = ""
|
||||
"""QQ 等级"""
|
||||
|
||||
is_robot: bool = False
|
||||
"""是否为机器人"""
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class FriendInfo:
|
||||
|
||||
@@ -22,6 +22,7 @@ VERIFIED_PLUGINS = (
|
||||
"bot_status",
|
||||
"broadcast",
|
||||
"code_py",
|
||||
"daily_wife",
|
||||
"echo",
|
||||
"feedback",
|
||||
"furry",
|
||||
|
||||
89
src/neobot/plugins/daily_wife.py
Normal file
89
src/neobot/plugins/daily_wife.py
Normal file
@@ -0,0 +1,89 @@
|
||||
import json
|
||||
import random
|
||||
from datetime import datetime, timezone, timedelta
|
||||
from neobot.core.managers.command_manager import matcher
|
||||
from neobot.models.events.message import GroupMessageEvent
|
||||
from neobot.core.managers.redis_manager import redis_manager
|
||||
from neobot.models.message import MessageSegment
|
||||
|
||||
CST = timezone(timedelta(hours=8))
|
||||
|
||||
__plugin_meta__ = {
|
||||
"name": "今日老婆",
|
||||
"description": "每天随机和群友凑成一对夫妻",
|
||||
"usage": "/wife 或 /今日老婆 - 看看今天的老婆是谁",
|
||||
}
|
||||
|
||||
_REDIS_KEY = "neobot:daily_wife:{}" # format with group_id
|
||||
|
||||
def _today_str() -> str:
|
||||
return datetime.now(CST).strftime("%Y-%m-%d")
|
||||
|
||||
def _ttl_until_midnight() -> int:
|
||||
now = datetime.now(CST)
|
||||
midnight = (now + timedelta(days=1)).replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
return int((midnight - now).total_seconds())
|
||||
|
||||
@matcher.command("wife", "今日老婆")
|
||||
async def handle_wife(event: GroupMessageEvent, args: list[str]):
|
||||
if not isinstance(event, GroupMessageEvent):
|
||||
await event.reply("这个指令只能在群聊里用嗷")
|
||||
return
|
||||
|
||||
group_id = str(event.group_id)
|
||||
user_id = str(event.user_id)
|
||||
today = _today_str()
|
||||
redis_key = _REDIS_KEY.format(group_id)
|
||||
|
||||
pairs = await redis_manager.redis.hgetall(redis_key)
|
||||
stored_date = pairs.pop("_date", None)
|
||||
|
||||
if stored_date != today:
|
||||
await redis_manager.redis.delete(redis_key)
|
||||
pairs = {}
|
||||
|
||||
if user_id in pairs:
|
||||
partner = json.loads(pairs[user_id])
|
||||
partner_nick = partner.get("nickname", str(partner["user_id"]))
|
||||
partner_id = partner["user_id"]
|
||||
avatar_url = f"https://q1.qlogo.cn/g?b=qq&nk={partner_id}&s=640"
|
||||
await event.reply([
|
||||
MessageSegment.text(f"你今天的另一半已经有啦,是 {partner_nick}({partner_id})~\n"),
|
||||
MessageSegment.image(avatar_url),
|
||||
])
|
||||
return
|
||||
|
||||
try:
|
||||
members = await event.bot.get_group_member_list(event.group_id)
|
||||
except Exception as e:
|
||||
await event.reply(f"获取群成员列表失败了: {e}")
|
||||
return
|
||||
|
||||
paired_ids = set(user_id)
|
||||
for v in pairs.values():
|
||||
paired_ids.add(str(json.loads(v)["user_id"]))
|
||||
|
||||
other_members = [m for m in members if str(m.user_id) not in paired_ids]
|
||||
if not other_members:
|
||||
await event.reply("群里没有其他可以配对的群友了……")
|
||||
return
|
||||
|
||||
chosen = random.choice(other_members)
|
||||
chosen_nick = chosen.card or chosen.nickname
|
||||
my_nick = event.sender.nickname if event.sender else user_id
|
||||
|
||||
pairs[user_id] = json.dumps({"user_id": chosen.user_id, "nickname": chosen_nick})
|
||||
pairs[str(chosen.user_id)] = json.dumps({"user_id": event.user_id, "nickname": my_nick})
|
||||
pairs["_date"] = today
|
||||
|
||||
ttl = _ttl_until_midnight()
|
||||
await redis_manager.redis.hset(redis_key, mapping=pairs)
|
||||
await redis_manager.redis.expire(redis_key, ttl)
|
||||
|
||||
avatar_url = f"https://q1.qlogo.cn/g?b=qq&nk={chosen.user_id}&s=640"
|
||||
|
||||
await event.reply([
|
||||
MessageSegment.text(f"今日老婆分配结果:\n你是 {my_nick}\n你今天的另一半是 {chosen_nick}({chosen.user_id})\n"),
|
||||
MessageSegment.image(avatar_url),
|
||||
MessageSegment.text(f"\n有效期至今天午夜,好好相处吧~"),
|
||||
])
|
||||
@@ -147,6 +147,11 @@
|
||||
<span class="text-base text-gray-300 leading-relaxed group-hover/item:text-white transition-colors"><span class="font-mono text-xs text-gray-500">plugins/feedback.py</span> 功能反馈插件,/feedback 提交建议,管理员能查看管理</span>
|
||||
</li>
|
||||
|
||||
<li class="flex items-start gap-4 group/item">
|
||||
<span class="flex-shrink-0 mt-1 px-2 py-1 rounded text-[10px] font-mono font-bold bg-green-500/10 text-green-400 border border-green-500/20 group-hover/item:bg-green-500/20 transition-colors">ADD</span>
|
||||
<span class="text-base text-gray-300 leading-relaxed group-hover/item:text-white transition-colors"><span class="font-mono text-xs text-gray-500">plugins/daily_wife.py</span> /wife 今日老婆,每天和群友随机凑对</span>
|
||||
</li>
|
||||
|
||||
<li class="flex items-start gap-4 group/item">
|
||||
<span class="flex-shrink-0 mt-1 px-2 py-1 rounded text-[10px] font-mono font-bold bg-red-500/10 text-red-400 border border-red-500/20 group-hover/item:bg-red-500/20 transition-colors">FIX</span>
|
||||
<span class="text-base text-gray-300 leading-relaxed group-hover/item:text-white transition-colors"><span class="font-mono text-xs text-gray-500">config_models.py</span> reverse_ws 没配 default_factory,用户不写 [reverse_ws] 直接启动就炸</span>
|
||||
|
||||
Reference in New Issue
Block a user