feat(plugins,models): 加了今日老婆插件还有群成员信息字段
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:
2026-05-15 13:52:11 +08:00
parent 67d01392e4
commit 3a52652b4a
8 changed files with 125 additions and 24 deletions

View File

@@ -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:
"""

View File

@@ -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
}
]

View File

@@ -81,6 +81,12 @@ class GroupMemberInfo:
card_changeable: bool = False
"""是否允许修改群名片"""
qq_level: str = ""
"""QQ 等级"""
is_robot: bool = False
"""是否为机器人"""
@dataclass(slots=True)
class FriendInfo:

View File

@@ -22,6 +22,7 @@ VERIFIED_PLUGINS = (
"bot_status",
"broadcast",
"code_py",
"daily_wife",
"echo",
"feedback",
"furry",

View 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有效期至今天午夜,好好相处吧~"),
])

View File

@@ -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>