使用uninfo进行群组成员更新 (#1690)

This commit is contained in:
HibiKier 2024-10-10 23:25:46 +08:00 committed by GitHub
parent 2f459719e8
commit 9e5266a491
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 144 additions and 210 deletions

22
poetry.lock generated
View File

@ -2511,6 +2511,26 @@ type = "legacy"
url = "https://mirrors.aliyun.com/pypi/simple"
reference = "ali"
[[package]]
name = "nonebot-plugin-uninfo"
version = "0.4.0"
description = "Universal Information Model for Nonebot2"
optional = false
python-versions = ">=3.9"
files = [
{file = "nonebot_plugin_uninfo-0.4.0-py3-none-any.whl", hash = "sha256:d60a8491af52b1b2c0cdb3f2e4a4a8d02e66216a33e8d162f1da8bec73b3b701"},
{file = "nonebot_plugin_uninfo-0.4.0.tar.gz", hash = "sha256:3e1a494d05639a0227a8565d5cde90ec9724934a7ec32bf1e0bd40404faf9713"},
]
[package.dependencies]
importlib-metadata = ">=4.13.0"
nonebot2 = ">=2.3.0"
[package.source]
type = "legacy"
url = "https://mirrors.aliyun.com/pypi/simple"
reference = "ali"
[[package]]
name = "nonebot-plugin-userinfo"
version = "0.1.3"
@ -4925,4 +4945,4 @@ reference = "ali"
[metadata]
lock-version = "2.0"
python-versions = "^3.10"
content-hash = "e66133515a2b17715ddf5f887ec31f128751acda1ea67736e9d27b29a9b16b65"
content-hash = "527819a6117da3c41931d968f9238468aee98f2ca97f06e1ba1e7948b6cbe65c"

View File

@ -51,6 +51,7 @@ nonebot-plugin-alconna = "0.51.1"
arclet-alconna = "1.8.23"
aiocache = "^0.12.2"
py-cpuinfo = "^9.0.0"
nonebot-plugin-uninfo = "^0.4.1"
[tool.poetry.dev-dependencies]
nonebug = "^0.3.2"

View File

@ -49,18 +49,15 @@ _notice = on_notice(priority=1, block=False, rule=notice_rule(GroupIncreaseNotic
async def _(bot: Bot, session: EventSession, arparma: Arparma):
if gid := session.id3 or session.id2:
logger.info("更新群组成员信息", arparma.header_result, session=session)
await MemberUpdateManage.update(bot, gid)
await MessageUtils.build_message("已经成功更新了群组成员信息!").finish(
reply_to=True
)
result = await MemberUpdateManage.update_group_member(bot, gid)
await MessageUtils.build_message(result).finish(reply_to=True)
await MessageUtils.build_message("群组id为空...").send()
@_notice.handle()
async def _(bot: Bot, event: GroupIncreaseNoticeEvent):
# TODO: 其他适配器的加群自动更新群组成员信息
if str(event.user_id) == bot.self_id:
await MemberUpdateManage.update(bot, str(event.group_id))
await MemberUpdateManage.update_group_member(bot, str(event.group_id))
logger.info(
f"{BotConfig.self_nickname}加入群聊更新群组信息",
"更新群组成员列表",
@ -81,7 +78,9 @@ async def _():
if group_list:
for group in group_list:
try:
await MemberUpdateManage.update(bot, group.group_id)
await MemberUpdateManage.update_group_member(
bot, group.group_id
)
logger.debug("自动更新群组成员信息成功...")
except Exception as e:
logger.error(

View File

@ -1,213 +1,129 @@
from datetime import datetime, timezone, timedelta
import nonebot
from nonebot.adapters import Bot
# from nonebot.adapters.kaiheila import Bot as KaiheilaBot
from nonebot.adapters.onebot.v11 import Bot as v11Bot
from nonebot.adapters.onebot.v12 import Bot as v12Bot
from nonebot_plugin_uninfo import Member, SceneType, get_interface
from zhenxun.services.log import logger
from zhenxun.configs.config import Config
from zhenxun.models.level_user import LevelUser
from zhenxun.utils.platform import PlatformUtils
from zhenxun.models.group_member_info import GroupInfoUser
# from nonebot.adapters.discord import Bot as DiscordBot
# from nonebot.adapters.dodo import Bot as DodoBot
class MemberUpdateManage:
@classmethod
async def update(cls, bot: Bot, group_id: str):
if not group_id:
return logger.warning(
f"bot: {bot.self_id}group_id为空无法更新群成员信息..."
)
if isinstance(bot, v11Bot):
await cls.v11(bot, group_id)
elif isinstance(bot, v12Bot):
await cls.v12(bot, group_id)
# elif isinstance(bot, KaiheilaBot):
# await cls.kaiheila(bot, group_id)
# elif isinstance(bot, DodoBot):
# await cls.dodo(bot, group_id)
# elif isinstance(bot, DiscordBot):
# await cls.discord(bot, group_id)
async def __handle_user(
cls,
member: Member,
db_user: list[GroupInfoUser],
group_id: str,
data_list: tuple[list, list, list],
platform: str | None,
):
"""单个成员操作
# @classmethod
# async def discord(cls, bot: DiscordBot, group_id: str):
# # TODO: discord更新群组成员信息
# pass
# @classmethod
# async def dodo(cls, bot: DodoBot, group_id: str):
# page_size = 100
# result_size = 100
# max_id = 0
# exist_member_list = []
# group_member_list: list[MemberInfo] = []
# while result_size == page_size:
# group_member_data = await bot.get_member_list(
# island_source_id=group_id, page_size=page_size
# )
# result_size = len(group_member_data.list)
# group_member_list += group_member_data.list
# max_id = group_member_data.max_id
# if group_member_list:
# for user in group_member_list:
# exist_member_list.append(user.dodo_source_id)
# await GroupInfoUser.update_or_create(
# user_id=user.dodo_source_id,
# group_id=group_id,
# defaults={
# "user_name": user.nick_name or user.personal_nick_name,
# "user_join_time": user.join_time,
# "platform": "dodo",
# },
# )
# if delete_member_list := list(
# set(exist_member_list).difference(
# set(await GroupInfoUser.get_group_member_id_list(group_id))
# )
# ):
# await GroupInfoUser.filter(
# user_id__in=delete_member_list, group_id=group_id
# ).delete()
# logger.info(
# f"删除已退群用户",
# "更新群组成员信息",
# group_id=group_id,
# platform="dodo",
# )
# @classmethod
# async def kaiheila(cls, bot: KaiheilaBot, group_id: str):
# # TODO: kaiheila 更新群组成员信息
# pass
@classmethod
async def v11(cls, bot: v11Bot, group_id: str):
exist_member_list = []
参数:
member: Member
db_user: db成员数据
group_id: 群组id
data_list: 数据列表
platform: 平台
"""
driver = nonebot.get_driver()
default_auth = Config.get_config("admin_bot_manage", "ADMIN_DEFAULT_AUTH")
group_member_list = await bot.get_group_member_list(group_id=int(group_id))
db_user = await GroupInfoUser.filter(group_id=group_id).all()
nickname = member.nick or member.user.name or ""
role = member.role
db_user_uid = [u.user_id for u in db_user]
uid2name = {u.user_id: u.user_name for u in db_user}
create_list = []
update_list = []
delete_list = []
for user_info in group_member_list:
user_id = str(user_info["user_id"])
nickname = user_info["card"] or user_info["nickname"]
role = user_info["role"]
if (
default_auth
and role in ["owner", "admin"]
and not await LevelUser.is_group_flag(user_id, group_id)
if member.id in driver.config.superusers:
await LevelUser.set_level(member.id, group_id, 9)
elif default_auth:
if role != "MEMBER" and not await LevelUser.is_group_flag(
member.id, group_id
):
if role == "owner":
await LevelUser.set_level(user_id, group_id, default_auth + 1)
else:
await LevelUser.set_level(user_id, group_id, default_auth)
if user_id in bot.config.superusers:
await LevelUser.set_level(user_id, group_id, 9)
join_time = datetime.fromtimestamp(
user_info["join_time"], timezone(timedelta(hours=8))
)
if cnt := db_user_uid.count(user_id):
users = [u for u in db_user if u.user_id == user_id]
if cnt > 1:
for u in users[1:]:
delete_list.append(u.id)
if nickname != uid2name.get(user_id):
user = users[0]
user.user_name = nickname
update_list.append(user)
else:
create_list.append(
GroupInfoUser(
user_id=user_id,
group_id=group_id,
user_name=nickname,
user_join_time=join_time,
platform="qq",
)
if role == "OWNER":
await LevelUser.set_level(member.id, group_id, default_auth + 1)
elif role == "ADMINISTRATOR":
await LevelUser.set_level(member.id, group_id, default_auth)
if cnt := db_user_uid.count(member.id):
users = [u for u in db_user if u.user_id == member.id]
if cnt > 1:
for u in users[1:]:
data_list[2].append(u.id)
if nickname != uid2name.get(member.id):
user = users[0]
user.user_name = nickname
data_list[1].append(user)
else:
data_list[0].append(
GroupInfoUser(
user_id=member.id,
group_id=group_id,
user_name=nickname,
user_join_time=member.joined_at,
platform=platform,
)
exist_member_list.append(user_id)
if create_list:
await GroupInfoUser.bulk_create(create_list, 30)
logger.debug(
f"创建用户数据 {len(create_list)}",
"更新群组成员信息",
target=group_id,
)
if update_list:
await GroupInfoUser.bulk_update(update_list, ["user_name"], 30)
logger.debug(
f"更新户数据 {len(update_list)}", "更新群组成员信息", target=group_id
)
if delete_list:
await GroupInfoUser.filter(id__in=delete_list).delete()
logger.debug(f"删除重复数据 Ids: {delete_list}", "更新群组成员信息")
if delete_member_list := [
uid for uid in db_user_uid if uid not in exist_member_list
]:
await GroupInfoUser.filter(
user_id__in=delete_member_list, group_id=group_id
).delete()
logger.info(
f"删除已退群用户 {len(delete_member_list)}",
"更新群组成员信息",
group_id=group_id,
platform="qq",
)
@classmethod
async def v12(cls, bot: v12Bot, group_id: str):
# TODO: v12更新群组成员信息
pass
# exist_member_list = []
# default_auth = Config.get_config("admin_bot_manage", "ADMIN_DEFAULT_AUTH")
# group_member_list: list[GetGroupMemberInfoResp] =
# await bot.get_group_member_list(
# group_id=group_id
# )
# for user_info in group_member_list:
# user_id = user_info.user_id
# nickname = user_info.user_displayname or user_info.user_name
# role = user_info["role"]
# if default_auth:
# if role in ["owner", "admin"] and not LevelUser.is_group_flag(
# str(user_id), group_id
# ):
# await LevelUser.set_level(user_id, group_id, default_auth)
# if str(user_id) in bot.config.superusers:
# await LevelUser.set_level(str(user_id), group_id, 9)
# join_time = datetime.strptime(
# time.strftime("%Y-%m-%d %H:%M:%S",
# time.localtime(user_info["join_time"])),
# "%Y-%m-%d %H:%M:%S",
# )
# await GroupInfoUser.update_or_create(
# user_id=str(user_id),
# group_id=group_id,
# defaults={
# "user_name": nickname,
# "user_join_time": join_time.replace(
# tzinfo=timezone(timedelta(hours=8))
# ),
# },
# )
# exist_member_list.append(str(user_id))
# logger.debug("更新成功", "更新群组成员信息",
# session=user_id, group_id=group_id)
# if delete_member_list := list(
# set(exist_member_list).difference(
# set(await GroupInfoUser.get_group_member_id_list(group_id))
# )
# ):
# await GroupInfoUser.filter(
# user_id__in=delete_member_list, group_id=group_id
# ).delete()
# logger.info(f"删除已退群用户", "更新群组成员信息", group_id=group_id)
async def update_group_member(cls, bot: Bot, group_id: str) -> str:
"""更新群组成员信息
参数:
bot: Bot
group_id: 群组id
返回:
str: 返回消息
"""
if not group_id:
logger.warning(f"bot: {bot.self_id}group_id为空无法更新群成员信息...")
return "群组id为空..."
if interface := get_interface(bot):
scenes = await interface.get_scenes()
platform = PlatformUtils.get_platform(bot)
group_list = [s for s in scenes if s.is_group and s.id == group_id]
if not group_list:
logger.warning(
f"bot: {bot.self_id}group_id: {group_id},群组不存在,"
"无法更新群成员信息..."
)
return "更新群组失败,群组不存在..."
members = await interface.get_members(SceneType.GROUP, group_list[0].id)
db_user = await GroupInfoUser.filter(group_id=group_id).all()
db_user_uid = [u.user_id for u in db_user]
data_list = ([], [], [])
exist_member_list = []
for member in members:
await cls.__handle_user(member, db_user, group_id, data_list, platform)
exist_member_list.append(member.id)
if data_list[0]:
await GroupInfoUser.bulk_create(data_list[0], 30)
logger.debug(
f"创建用户数据 {len(data_list[0])}",
"更新群组成员信息",
target=group_id,
)
if data_list[1]:
await GroupInfoUser.bulk_update(data_list[1], ["user_name"], 30)
logger.debug(
f"更新户数据 {len(data_list[1])}",
"更新群组成员信息",
target=group_id,
)
if data_list[2]:
await GroupInfoUser.filter(id__in=data_list[2]).delete()
logger.debug(f"删除重复数据 Ids: {data_list[2]}", "更新群组成员信息")
if delete_member_list := [
uid for uid in db_user_uid if uid not in exist_member_list
]:
await GroupInfoUser.filter(
user_id__in=delete_member_list, group_id=group_id
).delete()
logger.info(
f"删除已退群用户 {len(delete_member_list)}",
"更新群组成员信息",
group_id=group_id,
platform="qq",
)
return "群组成员信息更新完成!"

View File

@ -7,10 +7,10 @@ import nonebot
from pydantic import BaseModel
from nonebot.adapters import Bot
from nonebot.utils import is_coroutine_callable
from nonebot_plugin_uninfo import get_interface
from nonebot.adapters.dodo import Bot as DodoBot
from nonebot.adapters.onebot.v11 import Bot as v11Bot
from nonebot.adapters.onebot.v12 import Bot as v12Bot
from nonebot.adapters.discord import Bot as DiscordBot
from nonebot.adapters.kaiheila import Bot as KaiheilaBot
from nonebot_plugin_alconna.uniseg import Target, Receipt, UniMessage
@ -380,13 +380,11 @@ class PlatformUtils:
返回:
str | None: 平台
"""
if isinstance(bot, v11Bot | v12Bot):
return "qq"
if isinstance(bot, DodoBot):
return "dodo"
if isinstance(bot, KaiheilaBot):
return "kaiheila"
return "discord" if isinstance(bot, DiscordBot) else None
if interface := get_interface(bot):
info = interface.basic_info()
platform = info["scope"].lower()
return "qq" if platform.startswith("qq") else platform
return "unknown"
@classmethod
async def get_group_list(cls, bot: Bot) -> tuple[list[GroupConsole], str]: