Files
nonebot-plugin-tetris-stats/nonebot_plugin_tetris_stats/utils/avatar.py
呵呵です fd85140c99 绑定使用图片回复 #61 (#305)
* 🚧 查数据图初版测试

Co-authored-by: C1ystal <m17687496044@163.com>
Co-authored-by: C29H25N3O5 <michaelgu495@gmail.com>

* 🙈 添加一些 ignore 文件

* 🎨 格式化代码

* 🐛 修复格式化导致的样式爆炸

* 💄 优化曲线图观感

* 💄 将雷达图的指示器名称旋转显示

* 💄 查数据图第二版

Co-authored-by: C29H25N3O5 <michaelgu495@gmail.com>

* ✏️ 修复 typo

* 💄 把用户头像文件的引用放到 html 里

* 💄 账户绑定图第一版

Co-authored-by: C1ystal <m17687496044@163.com>
Co-authored-by: C29H25N3O5 <michaelgu495@gmail.com>

* 🚧 模板化测试

*  添加依赖 fastapi

*  通过 FastAPI 提供静态文件

*  添加依赖 jinja2

* 💄 更新数据图模板 (#291)

* feat(template): show actual value

* feat(template): add user avatar

* feat(template): fix radar

* feat(style): fix name container width fixed caused display misplacement

* feat(style): fix vs value wrap display

* feat(template): make check data length in template

* feat(template): update radar data

* feat(jinja): update data

* fix(template): fix typo

* feat(style): prevent sign too long

* feat(template): turn off echarts animation

* chore(deps): add identicon.js

* fix(template): fix typo

* 🙈 更新.gitignore

* 🏗️ 大部分重构为 flex 布局

---------

Co-authored-by: shoucandanghehe <wallfjjd@gmail.com>
Co-authored-by: 呵呵です <51957264+shoucandanghehe@users.noreply.github.com>

*  添加依赖 nonebot_plugin_userinfo

*  通过 FastAPI 托管渲染后的模板

*  新增头像 api 使用 playwright 生成

*  修正模板资源文件引用路径
被托管后的正确路径

* 💄 将绑定图模板化

* 💄 重命名变量

* 🚚 重命名资源

*  使用 jinja2 渲染模板

*  使用 playwright 渲染网页

* 🩹 渲染模板时对 IO 进行一些额外处理

*  添加依赖 pillow

* 🚚 修改托管页面的路由路径

* 💬 优化绑定图文案

*  新增获取自身网络位置的方法

* 🍱 更新 unknown.svg

*  新增获取用户头像的方法

*  绑定消息使用图片回复

*  为 identicon api 添加缓存

* 🔥 删除旧文件

* 🚚 重命名模板

* 📄 添加字体 License

* 🙈 更新.gitignore

---------

Co-authored-by: C1ystal <m17687496044@163.com>
Co-authored-by: C29H25N3O5 <michaelgu495@gmail.com>
Co-authored-by: 渣渣120 <WOSHIZHAZHA120@qq.com>
2024-05-02 01:22:33 +08:00

82 lines
2.6 KiB
Python

from base64 import b64decode, b64encode
from io import BytesIO
from typing import Literal, overload
from nonebot_plugin_userinfo import UserInfo # type: ignore[import-untyped]
from PIL import Image
from ..templates import path
from .browser import BrowserManager
@overload
async def get_avatar(user: UserInfo, scheme: Literal['Data URI'], default: str | None) -> str:
"""获取用户头像的指定格式
Args:
user (UserInfo): 要获取的用户
scheme (Literal[&#39;Data URI&#39;]): 格式
default (str | None): 获取不到时的默认值
Raises:
TypeError: Can't get avatar: 当获取不到头像并且没有设置默认值时抛出
TypeError: Can't get avatar format: 当获取到的头像无法识别格式时抛出
Returns:
str: Data URI 格式的头像
"""
@overload
async def get_avatar(user: UserInfo, scheme: Literal['bytes'], default: str | None) -> bytes:
"""获取用户头像的指定格式
Args:
user (UserInfo): 要获取的用户
scheme (Literal[&#39;bytes&#39;]): 格式
default (str | None): 获取不到时的默认值
Returns:
bytes: bytes 格式的头像
"""
async def get_avatar(user: UserInfo, scheme: Literal['Data URI', 'bytes'], default: str | None) -> str | bytes:
if user.user_avatar is None:
if default is None:
raise TypeError("Can't get avatar")
return default
bot_avatar = await user.user_avatar.get_image()
if scheme == 'Data URI':
avatar_format = Image.open(BytesIO(bot_avatar)).format
if avatar_format is None:
raise TypeError("Can't get avatar format")
return f'data:{Image.MIME[avatar_format]};base64,{b64encode(bot_avatar).decode()}'
return bot_avatar
async def generate_identicon(hash: str) -> bytes: # noqa: A002
"""使用 identicon 生成头像
Args:
hash (str): 提交给 identicon 的 hash 值
Returns:
bytes: identicon 生成的 svg 的二进制数据
"""
browser = await BrowserManager.get_browser()
async with await browser.new_page() as page:
await page.add_script_tag(path=path / 'js/identicon.js')
return b64decode(
await page.evaluate(rf"""
new Identicon('{hash}', {{
background: [0x08, 0x0a, 0x06, 255],
margin: 0.15,
size: 300,
brightness: 0.48,
saturation: 0.65,
format: 'svg',
}}).toString();
""")
)