Skip to content

Dispatch chat commands in the dev server - #5

Merged
gabek merged 1 commit into
mainfrom
fix/serve-dispatch-commands
Jul 30, 2026
Merged

Dispatch chat commands in the dev server#5
gabek merged 1 commit into
mainfrom
fix/serve-dispatch-commands

Conversation

@gabek

@gabek gabek commented Jul 30, 2026

Copy link
Copy Markdown
Member

POST /_dev/chat ran the filter chain and fired chat.message.received, but never matched the message against the plugin's declared commands. A declarative commands table therefore never ran locally, and the curl both mod-commands READMEs already document produced no reply at all.

  • Call DispatchCommands after the chat notification for the same accepted message, which is the order Owncast uses. It sits behind the filter-drop early return, so a dropped message still runs no commands.
  • Preserve both the user and body returned by the filter so notifications and command gating see the same accepted message.
  • Document the object form of user in both mod-commands READMEs. A bare string is an ordinary viewer, and an object is how you grant the MODERATOR scope that ?announce needs.

One call covers prefix matching, aliases, case insensitivity, moderator gating and cooldowns, because all of that lives in the runtime already.

Driving the prebuilt mod-commands example, server log on the left of the arrow being what main produced:

?ping                    audit line only  ->  pong
?p          (alias)      audit line only  ->  pong
?PING       (case)       audit line only  ->  pong
?ping again (cooldown)   audit line only  ->  audit line only, still silent
?announce   (non-mod)    audit line only  ->  audit line only, still silent
?announce   (MODERATOR)  audit line only  ->  Announcement: hello
?bogus      (unknown)    audit line only  ->  audit line only, still silent

The audit line is the plugin's own onChatMessage handler, which still fires for every message, so ordinary chat delivery is unchanged. The Python mod-commands example produces a byte-identical log.

I also checked a throwaway plugin that declares both a filter and a command: a message the filter drops answers {"allowed":false} and runs no command, so the placement behind the early return is right.

Copilot caught one mismatch in the first version: a filter-modified user reached onChatMessage, but moderator gating still saw the original user. A focused before and after probe rewrote an ordinary viewer to MODERATOR and rewrote the body to a moderator-only command. Before the fix, onChatMessage saw MODERATOR but the command was rejected. After the fix, the command runs.

No tests added. cmd/owncast-plugin-serve has no harness for spinning up the server, so the evidence is the before and after run against the real examples and the focused filter rewrite probe. PR #4 is merged, and this branch is rebased directly onto the resulting main commit.

Copilot AI review requested due to automatic review settings July 30, 2026 22:58

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the owncast-plugin-serve dev server to more closely match production Owncast behavior by dispatching declared chat commands for accepted dev-chat messages, enabling local testing of manifest commands without running a full Owncast instance.

Changes:

  • Dispatch DispatchCommands after firing chat.message.received for accepted /\_dev/chat messages.
  • Update /_dev/chat documentation in the dev server header comment to reflect the new command-dispatch behavior.
  • Document the object form of user (including moderator scopes) in both JS and Python mod-commands example READMEs.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
host-runtime/cmd/owncast-plugin-serve/main.go Dispatch chat commands in the dev server after the accepted-message notification.
examples/python/mod-commands/README.md Document user object form to grant MODERATOR scope for local command gating tests.
examples/js/mod-commands/README.md Document user object form to grant MODERATOR scope for local command gating tests.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread host-runtime/cmd/owncast-plugin-serve/main.go Outdated
Base automatically changed from fix/serve-static-and-admin-paths to main July 30, 2026 23:03
@gabek
gabek force-pushed the fix/serve-dispatch-commands branch from b83d6d7 to beea986 Compare July 30, 2026 23:08
The dev server ran the filter chain and fired chat.message.received, but never
matched the message against the plugin's declared commands. A declarative
commands table therefore never ran locally, and the curl both mod-commands
READMEs document produced no reply.

Owncast does that matching host-side right after notifying subscribers of the
same accepted message, so the dev server has to make the call itself. It sits
behind the filter-drop early return, so a dropped message still runs no
commands.

Also document the object form of user in both mod-commands READMEs, which is how
you drive a moderator-gated command from curl.
@gabek
gabek force-pushed the fix/serve-dispatch-commands branch from beea986 to 2989a4f Compare July 30, 2026 23:12
@gabek
gabek merged commit 11b01cb into main Jul 30, 2026
70 checks passed
@gabek
gabek deleted the fix/serve-dispatch-commands branch July 30, 2026 23:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants