聊天插件
如果您想构建一个可以在聊天中对话、对观众做出反应或管理消息的插件,那么这就是开始的页面。 代码示例同时在两种受支持的语言中显示。 首先在 JavaScript 或 Python SDK 页面上设置您的工具链。
Owncast 在三层中暴露聊天功能:
- 聊天事件处理程序,使您的插件能够在有人说话、加入、离开或更改名称时作出反应。
- 聊天和用户 API,使您的插件能够发布消息、检查聊天状态和管理用户。
- 聊天过滤器,使您的插件可以在观众看到之前重写或丢弃消息。
您可以构建的内容
- 能够对命令或关键字作出回应的聊天机器人。
- 能够在用户加入时问候他们的欢迎机器人。
- 在直播开始时发布消息的提醒机器人。
- 由
owncast.timer或 tick 处理程序驱动的倒计时和定时器机器人。 - 能够隐藏消息、断开客户端或禁用滥用用户的管理助手。
- 在播出之前重写、翻译或丢弃消息的过滤器。
一个回复机器人仅是一个处理程序:
- JavaScript
- Python
const { definePlugin, owncast } = require("@owncast/plugin-sdk");
module.exports = definePlugin({
onChatMessage(msg) {
const name = msg.user?.displayName ?? "someone";
owncast.chat.send(`${name} said: ${msg.body}`);
},
});
from owncast_plugin import plugin, owncast
@plugin.on_chat_message
def echo(msg):
name = msg.user.display_name if msg.user else "someone"
owncast.chat.send(f"{name} said: {msg.body}")
对聊天的反应
定义 onChatMessage (@plugin.on_chat_message 在 Python 中) 以便在消息经过过滤后看到每条消息,就在它广播给观众之前:
- JavaScript
- Python
module.exports = definePlugin({
onChatMessage(msg) {
owncast.chat.send(`echo: ${msg.body}`);
},
});
@plugin.on_chat_message
def echo(msg):
owncast.chat.send(f"echo: {msg.body}")
您最常涉及的字段是 msg.body(原始文本),msg.user(发送者身份,user.id 用于每个用户的状态,user.scopes 用于管理检查)和 msg.timestamp(确定性,因此在比较经过时间或测试断言时优先使用)。 不要依据显示名称设置状态或权限。
有关聊天插件可以订阅的完整消息有效载荷及每个其他事件(用户加入和离开、重命名、管理等),请参见 事件参考。
发送聊天消息
owncast.chat.send
发布聊天消息。 以您插件的机器人身份发送。 接受纯文本,而不是标记:聊天 UI 在显示时将其 HTML 转义,因此字符如 \<, &, 和 " 将作为文本而不是 HTML 渲染。
- JavaScript
- Python
owncast.chat.send("hello chat");
owncast.chat.sendAction("waves"); // /me-style action message
owncast.chat.system("Stream starting in 5 minutes");
owncast.chat.send("hello chat")
owncast.chat.send_action("waves") # /me-style action message
owncast.chat.system("Stream starting in 5 minutes")
需要 chat.send。
owncast.chat.sendAction
发布动作样式(/me)消息:在 JavaScript 中为 sendAction,在 Python 中为 send_action。 像 send 一样,接受纯文本,并且在显示时由聊天 UI 进行 HTML 转义。
需要 chat.send。
owncast.chat.system
发布服务器公告消息。 没有机器人身份被附加。 主体以 HTML 行内呈现。 将其用于简短的服务器归属通知,例如 "直播将在 5 分钟内开始"。 将主体视为不受信任的 HTML 输出:在没有转义的情况下,不要插入观众控制的输入。
需要 chat.send。
聊天身份
每个插件只有一个聊天身份:当安装插件时,Owncast 提供的机器人身份。 如果已设置,其显示名称为您清单的 bot.displayName,否则为 name。
send 和 sendAction 都通过 Owncast 的正常聊天管道发布作为此身份,包括过滤器、速率限制和管理。 插件不能以任意名称发布或冒充真实用户。
机器人用户基于插件的 slug 进行区分,因此身份在 name 或 bot.displayName 的清单编辑中得以保留。 如果您需要多个聊天身份,请构建多个插件。
读取聊天状态
owncast.chat.history
返回最近的聊天消息(可选的限制默认为 50)。 每条记录的形状为 { id, user?, clientId?, body, timestamp }。
需要 chat.history。
owncast.chat.clients
Return the list of currently connected chat clients: { id, userId?, displayName?, connectedAt?, userAgent?, ipAddress?, messageCount? }. id 是每个连接客户端使用的 ID,用于 owncast.chat.kick。
需要 chat.history。
owncast.server.emotes
当您的机器人想要引用或镜像表情符号目录时,读取服务器的自定义聊天表情({ name, url })。
需要 server.read。
owncast.users.list 和 owncast.users.get
通过 id 读取聊天用户列表或单个用户记录。
需要 users.read。
管理 API
这些是在 JavaScript 中的 deleteMessage / kick / sendTo / replyTo 和 Python 中的 delete_message / kick / send_to / reply_to。
owncast.chat.deleteMessage
根据消息 ID 隐藏观众的聊天消息。
需要 chat.moderate。
owncast.chat.kick
根据客户端 ID 断开聊天客户端。
需要 chat.moderate。
owncast.chat.sendTo
向单个已连接客户端发送私人消息,按客户端 ID。
需要 chat.send。
owncast.chat.replyTo
向发送聊天消息的人悄悄回复。 您可以传递完整的消息对象或裸客户端 ID(如果仅此而已)。 当发送者连接不再已知时,它返回一个虚值,这会让您清晰地回退到公共消息。
- JavaScript
- Python
module.exports = definePlugin({
onChatMessage(msg) {
if (!owncast.chat.replyTo(msg, "psst: got your message")) {
owncast.chat.send("got your message"); // sender already disconnected
}
},
});
@plugin.on_chat_message
def whisper(msg):
if not owncast.chat.reply_to(msg, "psst: got your message"):
owncast.chat.send("got your message") # sender already disconnected
需要 chat.send。
命令
对于聊天命令,声明一个包含别名、冷却时间、管理门控和自动 !help 列表的命令表。 参见 聊天命令。
管理用户
owncast.users.setEnabled
通过 ID 启用或禁用聊天用户,带可选原因:在 JavaScript 中使用 setEnabled,在 Python 中使用 set_enabled。
需要 users.moderate。
owncast.users.banIP
禁止一个 IP 加入聊天:在 JavaScript 中为 banIP,在 Python 中为 ban_ip。
需要 users.moderate。
聊天过滤器
过滤器在消息播出之前查看聊天信息,能够重写或丢弃它们。 过滤器以最低优先级先运行。 一个 drop 结束链条,消息不会到达后面的过滤器或通知。 一个 modify 将新有效载荷传递给下一个过滤器。
filterChatMessage
接收与聊天消息处理程序相同的 ChatMessage 结构,并返回三个结果之一,由 filter 辅助构建:
- 通过:让消息保持不变。
- 修改:用新的有效载荷替换它。
- 丢弃:丢弃它(带理由)。 链条在这里停止。
- JavaScript
- Python
const { definePlugin, filter } = require("@owncast/plugin-sdk");
module.exports = definePlugin({
filterChatMessage(msg) {
if (msg.body.includes("spam")) return filter.drop("spam keyword");
if (msg.body.includes("damn")) {
return filter.modify({ ...msg, body: msg.body.replace("damn", "****") });
}
return filter.pass();
},
});
from owncast_plugin import plugin, filter
@plugin.filter_chat_message
def clean(msg):
if "spam" in msg.body:
return filter.drop("spam keyword")
if "damn" in msg.body:
return filter.modify({**msg.raw, "body": msg.body.replace("damn", "****")})
return filter.pass_() # trailing underscore: pass is a keyword
需要 chat.filter 权限。 如果插件定义过滤处理程序而没有声明该权限,主机会拒绝加载。
过滤器优先级(可选)
较低的数字较早运行。 默认值为 100。 Set it with filterPriority (JavaScript) on the plugin definition, or by calling plugin.set_filter_priority(priority) (Python).
当您插件的行为取决于其他过滤器是否已运行时使用。 例如,脏话过滤器通常应在翻译器之前运行。
过滤器安全性
- 错误被视为通过。 抛出过滤器永远不会阻止聊天。
- 过滤器的时间限制为 50 毫秒。 缓慢的过滤器被取消并视为通过。
- 在连续 5 次失败(错误或超时)后,插件将在余下的会话中自动禁用。 成功的过滤器调用会重置计数器。
主机强制执行对聊天插件有意义的限制
一些主机限制值得设计:
- 过滤器运行时间:每条消息 50 毫秒
- 事件处理程序运行时间(聊天消息、用户加入等):每次调用 500 毫秒
- 每次调用硬性上限:10 秒
- 过滤器输出大小:1 MiB
- 待处理的计时器:同时 64 个
- 定时器延迟范围:100 毫秒到 24 小时
这意味着聊天机器人和过滤器应该保持轻量,避免在热路径中的缓慢网络往返,并保持重写有效载荷的小。
您常需要的权限
chat.send:发布聊天消息和私人回复。chat.history:读取最近的聊天消息和连接的客户端。chat.moderate:隐藏消息并断开客户端。chat.filter:在广播之前重写或丢弃消息。users.read:检查用户记录。users.moderate:禁用聊天用户或禁止 IP。
有关完整的安全模型,请参见 权限。
示例聊天插件
插件SDK提供了小型聊天为中心的示例,这些示例与本页的模式紧密匹配(每个都有JavaScript和Python版本):
echo-bot:使用聊天消息处理程序 +owncast.chat.send的最小回复机器人。chat-logger:记录每条聊天消息而不进行回复。stream-tracker:组合聊天命令、聊天用户生命周期处理程序和操作公告。profanity-filter:重写消息而不丢失它们。slow-mode:使用msg.timestamp进行速率限制而丢弃消息。engagement-bot:通过删除一条消息来进行管理。timer-bot:从聊天中驱动的提醒/倒计时机器人,使用计时器和滴答处理程序。
在 examples/js · examples/python 查阅它们。
它与其他插件文档的关系
- 选择 SDK 和 JavaScript / Python 页面涵盖了特定语言的设置、CLI 和语法。
- 聊天命令 涵盖了命令表、自动生成的
!help和将命令与自己的聊天处理程序混合。 - 事件处理程序 是 所有 插件事件的完整处理程序参考。
- Owncast APIs 是 所有
owncast.*方法的完整 API 参考。 - 清单参考 涵盖了权限、机器人身份字段和每个清单属性。
- 贡献 UI 涵盖观众侧的 UI、覆盖层、按钮、脚本和样式,如果您的聊天插件还提供前端组件。
如果您从头开始,请先阅读 快速入门,然后再回来这里。
Improve this page
See something missing or incorrect? Edit this page and improve the documentation for everyone.
