Skip to main content

nonebot_plugin_receipts

一个面向 NoneBot2 的独立插件,用来把发送给 Bot 的文本和图片消息转成 ESC/POS 原始打印数据,再投递给 receipts-spooler。

当前实现面向 OneBot v11 适配器,适合 QQ 机器人消息场景。

功能

  • 提供 ticket、receipt 指令,二者互为别名
  • 支持命令后直接附带文本和图片
  • 如果命令后没有内容,会继续追问下一条消息
  • 将文本和图片合成为一张热敏小票图,再编码为 ESC/POS 栅格打印命令
  • 通过 receipts-spooler 的 /api/v1/task/push_raw 接口提交打印任务

安装

cd nonebot_plugin_receipts
pip install -e .

然后在你的 NoneBot2 项目中加载插件:

nonebot.load_plugin("nonebot_plugin_receipts")

配置

插件通过 NoneBot 全局配置读取以下环境变量:

变量 默认值 说明
RECEIPTS_SPOOLER_URL http://127.0.0.1:8000 receipts-spooler 服务地址
RECEIPTS_SPOOLER_TOKEN 空 对应 X-Spooler-Token
RECEIPTS_SPOOLER_TIMEOUT 5.0 调用 spooler 的 HTTP 超时
RECEIPT_IMAGE_FETCH_TIMEOUT 5.0 下载图片消息内容时的 HTTP 超时
RECEIPT_RENDER_MODE raster 渲染模式,可选 raster/hybrid
RECEIPT_PRINTER_WIDTH 576 小票像素宽度,最大 576
RECEIPT_TEMPLATE_PATH 空 可选,指向渲染模板 JSON 文件
RECEIPT_FONT_PATH 空 可选,建议配置支持中文的 TTF/OTF 字体
RECEIPT_FONT_SIZE 24 文本字号
RECEIPT_LINE_SPACING 6 文本行距
RECEIPT_SECTION_GAP 6 文本和图片之间的垂直间距
RECEIPT_SESSION_TIMEOUT_SECONDS 120 等待用户补发打印内容的超时时间(秒)
RECEIPT_FEED_LINES 4 打印后走纸行数
RECEIPT_ENABLE_CUT true 是否附加切纸命令
RECEIPT_ALLOWED_USER_IDS 空 允许提交打印任务的 QQ 号白名单
RECEIPT_ALLOWED_GROUP_IDS 空 允许提交打印任务的 QQ 群号白名单

渲染模式

  • raster:把文本和图片一起渲染成整张位图,再输出 ESC/POS 栅格数据,兼容性最好。
  • hybrid:文本走打印机原生字符输出,图片仍走位图,能减少大量文字被渲染成图片。

hybrid 模式下,中文是否正常输出取决于打印机对中英文字符集的支持情况。

白名单

可以通过以下配置限制谁能提交打印任务:

  • RECEIPT_ALLOWED_USER_IDS:允许提交的 QQ 号白名单
  • RECEIPT_ALLOWED_GROUP_IDS:允许提交的 QQ 群号白名单

两个配置都为空时,默认允许所有会话使用。
只要命中任意一个条件就会放行:

  • 发送者 QQ 号在 RECEIPT_ALLOWED_USER_IDS 中
  • 当前群号在 RECEIPT_ALLOWED_GROUP_IDS 中

未命中白名单的消息会被直接忽略,不会回复任何提示。

环境变量可以写成逗号分隔,例如:

RECEIPT_ALLOWED_USER_IDS=123456,234567
RECEIPT_ALLOWED_GROUP_IDS=345678,456789

渲染模板

如果你想单独调整小票布局,可以配置 RECEIPT_TEMPLATE_PATH 指向一个 JSON 文件。项目根目录里附带了一个示例文件 receipt_template.example.json。

支持的模板字段:

字段 默认值 说明
margin 16 左右和顶部内边距
header_enabled false 是否渲染页眉
header_text {sender_name}({sender_id}) 页眉文字模板
footer_enabled true 是否渲染页脚
footer_text {sender_name}({sender_id}) @ {timestamp} 页脚文字模板
footer_timestamp_format %Y-%m-%d %H:%M:%S 时间格式
footer_timezone_offset_hours 8 页脚时间使用的时区偏移

header_text 和 footer_text 都支持这些占位符:

  • {timestamp}
  • {sender_name}
  • {sender_id}

当 header 存在时,会在页眉和正文之间绘制一条全宽横线;当 footer 存在时,会在正文和页脚之间再绘制一条全宽横线。

示例:

{
  "margin": 24,
  "header_enabled": true,
  "header_text": "来自 {sender_name}({sender_id})",
  "footer_enabled": true,
  "footer_text": "{sender_name}({sender_id}) 打印于 {timestamp}",
  "footer_timestamp_format": "%Y/%m/%d %H:%M",
  "footer_timezone_offset_hours": 8
}

使用

直接在命令后附带内容:

/ticket 今晚睡大觉

或者:

  1. 发送 /ticket 或 /receipt
  2. 按提示继续发送一条包含文本、图片或两者混合的消息

插件会把纯文本和图片消息段一起打印,并在提交成功后回复当前队列长度。

如果命令后没有直接附带内容,插件会提示用户继续发送,并明确说明多久后超时。
如果用户在该时间窗口后才继续回复,插件会提示“已超时”,并直接结束本次等待;此时需要重新发送 /ticket 或 /receipt 开始新的打印流程。

RECEIPT_SESSION_TIMEOUT_SECONDS 的实际生效时间不会超过 NoneBot 全局 SESSION_EXPIRE_TIMEOUT,建议两者保持一致或让前者更小。

文本里支持类似 Markdown 的多级标题语法:

  • # 一级标题
  • ## 二级标题
  • ### 三级标题
  • 一直到 ###### 六级标题

在 raster 模式下会使用更大的字号和额外留白;在 hybrid 模式下会尽量映射为 ESC/POS 的加粗和放大文本。
如果需要打印以 # 开头的普通文本,可以写成 \# 普通文本。

给别的插件调用(公开 API)

如果另一个插件想借这里的能力打印东西(例如门锁插件把"有人按门铃" 打成小票),请只依赖下面这个模块,不要 import renderer / spooler 等 内部模块——那些是实现细节,重构时不会保证兼容。

from nonebot_plugin_receipts.api import print_text, render_text
from nonebot_plugin_receipts.template import ReceiptTemplateContext

# 渲染并投递(最常用)
await print_text(
    "!! 门铃 !!\n\n23:12 有人按门铃\n小米全自动智能门锁(工作室)",
    context=ReceiptTemplateContext(
        sender_name="小米全自动智能门锁",   # 会填进模板的 {sender_name}
        sender_id="1021313131",
    ),
)

# 只要字节、自己投递
payload: bytes = await render_text("只渲染不发送")
函数 作用
print_text(text, *, config=None, context=None) 文本 → ESC/POS → 投给 spooler
render_text(text, *, config=None, context=None) 文本 → ESC/POS 字节(不投递)
print_message(message, *, config=None, context=None) 同上,但接受 OneBot 消息(可含图片)
render_message(message, *, config=None, context=None) 同上,只渲染
build_text_message(text) 把纯文本包成 OneBot 消息
get_runtime_config() 读当前 NoneBot 运行时配置

要点:

  • config 省略时从 NoneBot 运行时读,所以调用方不需要自己配一遍 spooler 地址与令牌,它们只在这里配;
  • context 省略时用空上下文,模板里的 {sender_name} / {sender_id} 会是空;
  • 本插件自己的 /ticket 命令走的也是这条路径,所以行为不会两套实现漂移。

手动实机测试(不启动 NoneBot)

可直接运行脚本把测试内容渲染为 ESC/POS 并提交到 receipts-spooler:

python scripts/manual_print_test.py --mode hybrid --spooler-url http://127.0.0.1:8000

常用参数:

  • --mode hybrid|raster:渲染模式,默认 hybrid
  • --text:测试文本(支持 # 标题语法)
  • --spooler-url:spooler 地址
  • --spooler-token:可选鉴权 token
  • --printer-width:打印宽度(像素)
  • --feed-lines:走纸行数
  • --cut:追加切纸命令(默认不切)
  • --divider-only:只打印一条分割线(用于实机校准)
  • --divider-chars:分割线字符数(默认按 printer_width / 12)

也支持通过环境变量传参:

  • RENDER_MODE
  • SPOOLER_URL
  • SPOOLER_TOKEN
  • PRINTER_WIDTH
  • FEED_LINES
  • SENDER_NAME
  • SENDER_ID

该脚本仅用于手动联调与实机验证,不参与自动化测试流程。

注意事项

  • 如果你需要打印中文,最好配置 RECEIPT_FONT_PATH 指向支持中文的字体文件。
  • 图片消息需要 OneBot 事件中带有可访问的 url,或消息段 file 为 base64://... / http(s)://...。
  • 本插件不会直接连接打印机,只负责把任务提交到 receipts-spooler。

Metadata

Release files for nonebot-plugin-receipts 0.2.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nonebot-plugin-receipts 0.2.5
File Size Uploaded
nonebot_plugin_receipts-0.2.5.tar.gz 29.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for nonebot-plugin-receipts 0.2.5
File Interpreter ABI Platform
nonebot_plugin_receipts-0.2.5-py3-none-any.whl Python 3 none any Details

Total release size: 53.1 kB

Release files / nonebot_plugin_receipts-0.2.5.tar.gz

Download URL nonebot_plugin_receipts-0.2.5.tar.gz
Size 29.2 kB
Tags Source
SHA-256 checksum
How to use checksums
f7646d4b92c419794ff6460565bf86d2223dc2e36f852b621f20a7e7066764e7
BLAKE2b-256 checksum
How to use checksums
d644dc466cf33d49befb253fae35a8ca146d5ad92c82be73f29fcf20adc9170e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release files / nonebot_plugin_receipts-0.2.5-py3-none-any.whl

Download URL nonebot_plugin_receipts-0.2.5-py3-none-any.whl
Size 23.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ab5f401745368626bea81bce945b7eb3ccc0e4cfe7da75608655a642c4f5883e
BLAKE2b-256 checksum
How to use checksums
546b3d1b908a5b996cfcb0b03be560e0b76857dbbd7166029978e2ab6ac6c4b0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.5 This release

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page