+ 24℃
+ 个人简介:
+
+ diff --git a/.gitignore b/.gitignore index 12907baa..db7233b2 100644 --- a/.gitignore +++ b/.gitignore @@ -179,5 +179,4 @@ plugins/activity/ !/resources/image/genshin/alc/back.png !/data/genshin_alc/ .vscode/launch.json -/resources/template/my_info plugins_/ \ No newline at end of file diff --git a/resources/template/check/res/font/fzrzExtraBold.ttf b/resources/font/fzrzExtraBold.ttf similarity index 100% rename from resources/template/check/res/font/fzrzExtraBold.ttf rename to resources/font/fzrzExtraBold.ttf diff --git a/resources/template/help/res/font/syht.otf b/resources/font/syht.otf similarity index 100% rename from resources/template/help/res/font/syht.otf rename to resources/font/syht.otf diff --git a/resources/template/help/res/font/syst.otf b/resources/font/syst.otf similarity index 100% rename from resources/template/help/res/font/syst.otf rename to resources/font/syst.otf diff --git a/resources/template/bar_chart/main.html b/resources/template/bar_chart/main.html index 8728b14b..5cc1fbdd 100644 --- a/resources/template/bar_chart/main.html +++ b/resources/template/bar_chart/main.html @@ -1,5 +1,6 @@ +
+ 24℃
+ 个人简介:
+
+
+ 好感度等级: {{data.sign_level}}级
+
+ 权限等级: {{data.level}}
+
+ 金币数量: {{data.gold}}
+
+ 道具数量: {{data.prop}}
+
+ 调用次数: {{data.call}}
+
+ 发言统计: {{data.say}}
+
+ 发言趋势图
+
+ 24℃
+ 个人简介:
+
+
+ 好感度等级: 5级
+
+ 权限等级: 9
+
+ 金币数量: 999
+
+ 道具数量: 933
+
+ 调用次数: 6443
+
+ 发言统计: 233
+
+ 发言趋势图
+ {{data.name}}
diff --git a/resources/template/ss_menu/main.css b/resources/template/ss_menu/main.css index 1cde35f4..dde33819 100644 --- a/resources/template/ss_menu/main.css +++ b/resources/template/ss_menu/main.css @@ -3,19 +3,19 @@ @font-face { font-family: fzrzFont; /* 导入的字体文件 */ - src: url("./res/font/fzrzExtraBold.ttf"); + src: url("../../font/fzrzExtraBold.ttf"); } @font-face { font-family: syhtFont; /* 导入的字体文件 */ - src: url("./res/font/syht.otf"); + src: url("../../font/syht.otf"); } @font-face { font-family: systFont; /* 导入的字体文件 */ - src: url("./res/font/syst.otf"); + src: url("../../font/syst.otf"); } diff --git a/resources/template/ss_menu/res/font/fzrzExtraBold.ttf b/resources/template/ss_menu/res/font/fzrzExtraBold.ttf deleted file mode 100644 index 8afeafca..00000000 Binary files a/resources/template/ss_menu/res/font/fzrzExtraBold.ttf and /dev/null differ diff --git a/resources/template/ss_menu/res/font/syht.otf b/resources/template/ss_menu/res/font/syht.otf deleted file mode 100644 index 630d5467..00000000 Binary files a/resources/template/ss_menu/res/font/syht.otf and /dev/null differ diff --git a/resources/template/ss_menu/res/font/syst.otf b/resources/template/ss_menu/res/font/syst.otf deleted file mode 100644 index efa94cb5..00000000 Binary files a/resources/template/ss_menu/res/font/syst.otf and /dev/null differ diff --git a/zhenxun/builtin_plugins/info/__init__.py b/zhenxun/builtin_plugins/info/__init__.py new file mode 100644 index 00000000..2d71bf8c --- /dev/null +++ b/zhenxun/builtin_plugins/info/__init__.py @@ -0,0 +1,56 @@ +from nonebot.adapters import Bot +from nonebot.plugin import PluginMetadata +from nonebot_plugin_session import EventSession +from nonebot_plugin_alconna import At, Args, Match, Alconna, Arparma, on_alconna + +from zhenxun.services.log import logger +from zhenxun.utils.enum import PluginType +from zhenxun.utils.depends import UserName +from zhenxun.utils.message import MessageUtils +from zhenxun.utils.platform import PlatformUtils +from zhenxun.configs.utils import PluginExtraData +from zhenxun.models.group_member_info import GroupInfoUser + +from .my_info import get_user_info + +__plugin_meta__ = PluginMetadata( + name="查看信息", + description="查看个人信息", + usage=""" + 查看个人/群组信息 + 指令: + 我的信息 ?[at] + """.strip(), + extra=PluginExtraData(author="HibiKier", version="0.1").dict(), +) + + +_matcher = on_alconna(Alconna("我的信息", Args["at_user?", At]), priority=5, block=True) + + +@_matcher.handle() +async def _( + bot: Bot, + session: EventSession, + arparma: Arparma, + at_user: Match[At], + nickname: str = UserName(), +): + user_id = session.id1 + if at_user.available: + user_id = at_user.result.target + if user := await GroupInfoUser.get_or_none( + user_id=user_id, group_id=session.id2 + ): + nickname = user.user_name + else: + nickname = user_id + if not user_id: + await MessageUtils.build_message("用户id为空...").finish(reply_to=True) + try: + result = await get_user_info(bot, user_id, session.id2, nickname) + await MessageUtils.build_message(result).send(at_sender=True) + logger.info("获取用户信息", arparma.header_result, session=session) + except Exception as e: + logger.error("获取用户信息失败", arparma.header_result, session=session, e=e) + await MessageUtils.build_message("获取用户信息失败...").finish(reply_to=True) diff --git a/zhenxun/builtin_plugins/info/my_info.py b/zhenxun/builtin_plugins/info/my_info.py new file mode 100644 index 00000000..43eda62c --- /dev/null +++ b/zhenxun/builtin_plugins/info/my_info.py @@ -0,0 +1,193 @@ +import random +from datetime import datetime, timedelta + +from nonebot.adapters import Bot +from tortoise.functions import Count +from tortoise.expressions import RawSQL +from nonebot_plugin_htmlrender import template_to_pic + +from zhenxun.models.sign_user import SignUser +from zhenxun.models.level_user import LevelUser +from zhenxun.models.statistics import Statistics +from zhenxun.utils.platform import PlatformUtils +from zhenxun.models.chat_history import ChatHistory +from zhenxun.models.user_console import UserConsole +from zhenxun.configs.path_config import TEMPLATE_PATH + +RACE = [ + "龙族", + "魅魔", + "森林精灵", + "血精灵", + "暗夜精灵", + "狗头人", + "狼人", + "猫人", + "猪头人", + "骷髅", + "僵尸", + "虫族", + "人类", + "天使", + "恶魔", + "甲壳虫", + "猎猫", + "人鱼", + "哥布林", + "地精", + "泰坦", + "矮人", + "山巨人", + "石巨人", +] + +SEX = ["男", "女", "雌", "雄"] + +OCC = [ + "猎人", + "战士", + "魔法师", + "狂战士", + "魔战士", + "盗贼", + "术士", + "牧师", + "骑士", + "刺客", + "游侠", + "召唤师", + "圣骑士", + "魔使", + "龙骑士", + "赏金猎手", + "吟游诗人", + "德鲁伊", + "祭司", + "符文师", + "狂暴术士", + "萨满", + "裁决者", + "角斗士", +] + +lik2level = { + 400: 8, + 270: 7, + 200: 6, + 140: 5, + 90: 4, + 50: 3, + 25: 2, + 10: 1, + 0: 0, +} + + +def get_level(impression: float) -> int: + """获取好感度等级""" + return next((level for imp, level in lik2level.items() if impression >= imp), 0) + + +async def get_chat_history( + user_id: str, group_id: str | None +) -> tuple[list[str], list[str]]: + """获取用户聊天记录 + + 参数: + user_id: 用户id + group_id: 群id + + 返回: + tuple[list[str], list[str]]: 日期列表, 次数列表 + + """ + now = datetime.now() + filter_date = now - timedelta(days=7, hours=now.hour, minutes=now.minute) + date_list = ( + await ChatHistory.filter( + user_id=user_id, group_id=group_id, create_time__gte=filter_date + ) + .annotate(date=RawSQL("DATE(create_time)"), count=Count("id")) + .group_by("date") + .values("date", "count") + ) + chart_date = [] + count_list = [] + date2cnt = {str(date["date"]): date["count"] for date in date_list} + date = now.date() + for _ in range(7): + if str(date) in date2cnt: + count_list.append(date2cnt[str(date)]) + else: + count_list.append(0) + chart_date.append(str(date)) + date -= timedelta(days=1) + for c in chart_date: + chart_date[chart_date.index(c)] = c[5:] + chart_date.reverse() + count_list.reverse() + return chart_date, count_list + + +async def get_user_info( + bot: Bot, user_id: str, group_id: str | None, nickname: str +) -> bytes: + """获取用户个人信息 + + 参数: + bot: Bot + user_id: 用户id + group_id: 群id + nickname: 用户昵称 + + 返回: + bytes: 图片数据 + """ + platform = PlatformUtils.get_platform(bot) or "" + ava_url = PlatformUtils.get_user_avatar_url(user_id, platform) + user = await UserConsole.get_user(user_id, platform) + level = await LevelUser.get_user_level(user_id, group_id) + sign_level = 0 + if sign_user := await SignUser.get_or_none(user_id=user_id): + sign_level = get_level(float(sign_user.impression)) + chat_count = await ChatHistory.filter(user_id=user_id, group_id=group_id).count() + stat_count = await Statistics.filter(user_id=user_id, group_id=group_id).count() + select_index = ["" for _ in range(9)] + select_index[sign_level] = "select" + uid = f"{user.uid}".rjust(8, "0") + uid = f"{uid[:4]} {uid[4:]}" + now = datetime.now() + weather = "moon" if now.hour < 6 or now.hour > 19 else "sun" + chart_date, count_list = await get_chat_history(user_id, group_id) + data = { + "date": now.date(), + "weather": weather, + "ava_url": ava_url, + "nickname": nickname, + "title": "勇 者", + "race": random.choice(RACE), + "sex": random.choice(SEX), + "occ": random.choice(OCC), + "uid": uid, + "description": "这是一个传奇的故事," + "人类的赞歌是勇气的赞歌,人类的伟大是勇气的伟译。", + "sign_level": sign_level, + "level": level, + "gold": user.gold, + "prop": len(user.props), + "call": stat_count, + "say": chat_count, + "select_index": select_index, + "chart_date": chart_date, + "count_list": count_list, + } + return await template_to_pic( + template_path=str((TEMPLATE_PATH / "my_info").absolute()), + template_name="main.html", + templates={"data": data}, + pages={ + "viewport": {"width": 1754, "height": 1240}, + "base_url": f"file://{TEMPLATE_PATH}", + }, + wait=2, + ) diff --git a/zhenxun/builtin_plugins/sign_in/utils.py b/zhenxun/builtin_plugins/sign_in/utils.py index def67870..c78e63ed 100644 --- a/zhenxun/builtin_plugins/sign_in/utils.py +++ b/zhenxun/builtin_plugins/sign_in/utils.py @@ -13,6 +13,7 @@ from zhenxun.models.sign_log import SignLog from zhenxun.models.sign_user import SignUser from zhenxun.utils.utils import get_user_avatar from zhenxun.utils.image_utils import BuildImage +from zhenxun.utils.platform import PlatformUtils from zhenxun.configs.config import Config, BotConfig from zhenxun.configs.path_config import IMAGE_PATH, TEMPLATE_PATH @@ -419,8 +420,9 @@ async def _generate_html_card( next_impression - previous_impression ) now = datetime.now() + ava_url = PlatformUtils.get_user_avatar_url(user.user_id, "qq") data = { - "ava": AVA_URL.format(user.user_id), + "ava_url": ava_url, "name": nickname, "uid": uid, "sign_count": f"{user.sign_count}", diff --git a/zhenxun/utils/platform.py b/zhenxun/utils/platform.py index 91ab8eb0..6ecddb54 100644 --- a/zhenxun/utils/platform.py +++ b/zhenxun/utils/platform.py @@ -267,7 +267,7 @@ class PlatformUtils: return None @classmethod - async def get_user_avatar_url(cls, user_id: str, platform: str) -> str | None: + def get_user_avatar_url(cls, user_id: str, platform: str) -> str | None: """快捷获取用户头像url 参数: