杂项
一些杂项功能的说明和配置,用户通常不需要涉及这些,以下内容主要供搭建者和开发者查阅。
货币系统
IdhagnBot 有一个简单的货币系统,目前只有 purchase
和 sign 插件使用这个系统,不同群聊之间的货币是独立的。具体请参考 API 文档。状态文件在 states/currency/群号.yaml
,参考如下:
你通常不应该修改状态文件,除非别无选择。
users:
987654321: 100 # 用户: 金币数
用户别名
在使用 /rua
等命令时,需要指定一个用户,除了可以直接输入 QQ 号或者 @ 对方,IdhagnBot 还会将群员昵称和群名片中的空格和特殊符号去掉,用于查找群员。
但当群员的昵称和群名片只包含特殊符号而不包含任何中文、英文、数字时,IdhagnBot 将不能通过名字找到他,此时你可以为他手动指定别名。
假如一个名字可以查找到两个或更多群员,为了防止不必要的误会,IdhagnBot 默认也会拒绝匹配到任何一个,除非手动指定别名。
别名还可以用于给群员“起外号”,如果给某人起了不太好听的外号而被他打了我不为此负责。
使用 /match 名字
可以查看名字能搜索到哪些群员(如果只有一个群员,也会显示他的别名),使用 /match QQ号
可以查看群员的所有别名,包括自动生成的。
config/user_aliases.yaml
aliases:
- contexts: # 这些别名在哪些上下文生效,不指定时在所有上下文生效
- 123456789 # -1 指私聊,-2 指任意群聊
aliases:
- names:
- 名字1
- 名字2
users: # 部分命令可以接受指代多个群员的别名,但大部分命令只接受指代一个群员的别名
- 123456789
- 987654321
开发示例
通常你需要使用 util.user_aliases.match_uid
,这个函数会在内部处理大部分细节,在出错时抛出 util.util.AggregateError
,包含相对友好的错误信息,当一个名称既能精确匹配也能模糊匹配时,精确匹配优先。
如果需要更底层的方法,你可以使用 util.user_aliases.get_aliases
和 util.user_aliases.match
,参见 API 文档
日志
IdhagnBot 和 Nonebot2 一样,也使用 Loguru 作为日志库,但 IdhagnBot 覆盖了 Nonebot2 的默认格式。
config/log.yaml
sinks: # 如果不指定,默认值如下,可以指定多个 sink
- level: INFO # 日志等级,可以是字符串或数字,不区分大小写,参见 Loguru 的日志等级
fold_nonebot: true # 是否将 nonebot. 开头的模块都显示为 nonebot,就像 Nonebot2 默认的日志一样
format: "<g>{time:HH:mm:ss}</g>|<lvl>{level:8}</lvl>| <c>{name}</c> - {message}" # 日志格式,此处为默认格式
colorize: null # 是否使用彩色日志,false 强制关闭,true 强制开启,null 自动检测
backtrace: true # 异常的 traceback 是否显示完整栈(而非只显示到 try-except)
diagnose: false # 异常是否显示变量的值等(可能包含敏感内容,并且很长)
# type: stderr # stdout、stderr 或 syslog
# syslog 使用 Python 的 syslog 标准库,只在 POSIX 系统上可用(如 Linux、Mac 等)
# 如果你将机器人作为 Systemd 服务运行,推荐使用 syslog
file: 日志文件名 # 和 type 二选一,只有 file 能用下面的选项
rotation: 日志滚动
retention: 清理旧日志
compression: 压缩日志
encoding: utf8 # 编码,默认为 utf8
newline: null # 为 null 时使用系统换行,也可指定为 "\r"、"\n" 或者 "\r\n"
warnings_as_log: true # 将 Python 标准库 warnings 输出的警告作为 WARN 等级的日志输出,默认为 true
stdio_as_log: false # 将 stdout 和 stderr 分别作为 INFO 和 ERROR 等级的日志输出,默认为 false,不建议开启,可能导致奇怪的问题
关于 rotation、retention 和 compression 的写法,请参见 Loguru 的文档
开发示例也请参见 Loguru。
杂项方法
包含一些解析颜色字符串和处理颜色的方法,解析颜色字符串时支持 3 位或 6 位十六进制、CSS 颜色名、rgb(r, g, b)
、hsl(h, s, l)
、Material Design 颜色名,不支持 Alpha 通道。 包含 NoneBot 没有的额外钩子,目前只有 on_message_sent 一个。 用于加载插件和子模块。 包含一些处理 Pillow 图片的实用方法。 包含一些实用但琐碎的方法。util.misc
的,我有点脑抽……config/misc.yaml
special_font:
pixel: Unifont # 用在 meme_word.nokia 中,未指定时 fallback 为 sans
osu: "" # 用在 meme_word.osu 中,未指定时 fallback 为 sans bold
font_substitute:
# PangoCairo 使用 FontConfig,因此 IdhagnBot 会跟随系统设置,但你也可以手动覆盖
# 目前 IdhagnBot 使用了这些通用名
serif: Noto Serif CJK SC
serif bold: Noto Serif CJK SC Bold
sans: Noto Sans CJK SC
sans medium: Noto Sans CJK SC Medium
sans bold: Noto Sans CJK SC Bold
sans heavy: Noto Sans CJK SC Heavy
monospace: Iosevka
# 其实上面这些字体并没有什么特殊含义,只是我喜欢而已(逃)
chromium: "" # Pyppeteer 使用的 Chromium 路径,默认为空,即让 Pyppeteer 自行下载
# 以下两项默认都是 bicubic
resample: bicubic # Pillow 除缩放外的图片插值方式,可用:nearest、bilinear、bicubic
scale_resample: bicubic # Pillow 缩放图片插值方式,除上面三个还可用:box、hamming、lanczos
# 以下四项请参考 PyCairo 的文档:https://pycairo.readthedocs.io/en/latest/reference/enums.html
# default 为使用系统默认值
text_antialias: gray # 字体抗锯齿方式,默认:gray,可用:default、none、fast、good、best、gray、subpixel
# best 抗拒齿在部分平台上可能无法正常渲染
# 不建议使用次像素抗拒齿,会导致字体边缘发绿等问题
text_subpixel: default # 次像素排列方式,默认:default,可用:default、rgb、bgr、vrgb、vbgr
# 这个选项只在使用次像素抗锯齿时有效
text_hint_metrics: true # 是否微调字体度量,默认:true,可用:default、true、false
text_hint_style: slight # 是否微调字体轮廓,默认:slight,可用:default、none、slight、medium、full
libimagequant: false
# 默认为 false,要启用 libimagequant,将此处改为 true 并参考下文自行编译安装 Pillow
# 因为 libimagequant 为 GPL 协议,PyPI 上的 Pillow 二进制包没有编译 libimagequant 支持
# 如果为 true 但 libimagequant 不可用,会显示一个警告并使用 quantize 指定的量化方法
# 另外,libimagequant 包含抖动仿色,因此启用之后下面的 dither 将不生效
quantize: fastoctree
# 默认为 fastoctree,也可为 mediancut 或者 maxcoverage
# 注意对于 RGBA 图片无论设置为什么都会使用 fastoctree,因为其余两个不支持 RGBA
dither: true
# 是否启用抖动仿色,默认为 true
字体渲染
IdhagnBot 使用 PangoCairo 来渲染文字,以提供 Emoji 等特殊符号的 fallback,也支持其他一些高级排版特性。
开发示例
util.textutil 主要提供 layout、render 和 paste 三个函数,paste 会将文字粘贴到目标图像上(并返回渲染的图片),是最便捷的函数。如果需要更多的控制,render 返回 PIL.Image.Image,layout 返回 Pango.Layout。具体请参考 API 文档
。浏览器渲染
IdhagnBot 由于作者的精神洁癖,偏向尽可能使用 Pillow、PyCairo、NumPy、OpenCV 等库生成图片而非调用浏览器,但以下功能由于极其复杂只能使用浏览器渲染:
开发示例
util.misc.browser
会使用配置文件中的 Chromium 路径创建 Pyppeteer 的浏览器实例,并且自动关闭浏览器,防止后台残留。
from util import misc
async with misc.browser() as browser:
pass # 使用获取的 browser
图片采样
IdhagnBot 默认使用双立方插值来缩放图片或进行其他变换,通常不应该造成性能影响。但如果确实有,请参考 Pillow 的文档 适当降低采样质量。
开发示例
在使用 Image.resize 等方法时,请使用 util.imutil.resample
和 util.imutil.scale_resample
,而非硬编码采样。
from PIL import Image
from util import imutil
im = Image.new("RGBA", (100, 100))
# scale_resample 可能被指定为 Box、Hamming 或 Lanczos,不要用在 resize 以外的方法中
im.resize((50, 50), imutil.scale_resample())
# resample 一定只会被指定为 Nearest、Bilinear 或 Bicubic
im.rotate(45, imutil.resample())
抖动仿色
IdhagnBot 在保存 GIF 时会自动转换为色板图片并应用抖动仿色,默认使用 Quantize.MEDIANCUT
(对于 RGBA 的图片强制使用 Quantize.FASTOCTREE
,因为只有它支持 RGBA,除非启用 libimagequant)。
因为 libimagequant 为 GPL 协议,PyPI 上的 Pillow 二进制包没有编译 libimagequant 支持,要启用 libimagequant,需要自行安装 libimagequant,再从源码编译安装 Pillow,并更改配置文件。
sudo pacman -S libimagequant
# 方式1: 适用于 venv 和 PEP582
# (PDM 目前不支持单独重装某一个包,这行命令会重装所有包)
PDM_NO_BINARY='Pillow' pdm sync -r
# 方式2: 仅适用于 venv,如果找不到 pip 可以运行 pdm run python -m ensurepip
pdm run python -m pip install Pillow --no-cache-dir --force-reinstall --no-binary Pillow
# 检查: 下面这行应该输出 True
pdm run python -c 'from PIL import features; print(features.check("libimagequant"))'
开发示例
util.imutil.to_segment
在保存 GIF 时会自动转换为色板图片并应用抖动仿色,如果需要手动转换,使用 util.imutil.quantize
from util import imutil
# fmt 为保存静态图的格式,默认为 png。
# afmt 为保存动图时的格式,默认为 gif,也可以是 png(APNG)和 webp。
# 在使用 gif 时会自动应用抖动仿色
# frames 为包含动图帧的数组,如果只有一帧将不会保存为动图
# frametime 为每一帧的时间,可以是单个毫秒数,即所有帧时间相同
# 也可以是与 frames 等长的毫秒数数组或者与 frames 等长的动图
segment = imutil.to_segment(frames, frametime, fmt="png", afmt="gif")
# 返回的是 nonebot 的 MessageSegment
await matcher.send(segment)
im = imutil.quantize(im) # 如果需要手动转换