Skip to content

feat(plugin-gateway): add Message#threadable - #248

Merged
kodiakhq[bot] merged 1 commit into
mainfrom
feat/plugin-gateway-message-threadable
Oct 17, 2026
Merged

kodiakhq[bot] merged 1 commit into
mainfrom
feat/plugin-gateway-message-threadable

Conversation

@RedStar071

Copy link
Copy Markdown
Member

🔗 Linked issue

Closes #184

🧭 Context

Message in @wolfstar/plugin-gateway ports discord.js's permission getters (editable, deletable, bulkDeletable, pinnable, crosspostable) but has no threadable, the one that tells whether the bot can start a thread from a message. Upstream is discord.js#11500, which is still a draft with changes requested.

📚 Description

Adds Message#threadable, built like crosspostable: it reads the cache only, so it is a plain boolean with a synchronous cache and a promise with an asynchronous one. It is false for a message that already has a thread (HasThread flag) or that is outside a guild. Otherwise it needs the channel in the cache (ChannelUncached on a miss), of type text or announcement, and the bot must have ViewChannel and CreatePublicThreads there (GuildUncachedMe / GuildUncached on a miss, as for the sibling getters).

Decisions, following the maintainer's go-ahead on Pullfrog's plan:

  • Differs from discord.js: discord.js passes checkAdmin = false, so an administrator without an explicit CreatePublicThreads is not threadable. Here the default permissions.has("CreatePublicThreads") is used, because the API lets administrators create threads and the getter answers "can the client start a thread here". The TSDoc, the changeset and a test say so.
  • No viewable getter: ViewChannel is checked inline through hasCachedPermission.
  • No channel-level variant and no fetchThreadable() twin (the existing fetch* twins are @deprecated, so a new one would add deprecated API). The async-cache test asserts the values directly.
  • The TSDoc states that it is a permission and channel-type check only: locked or archived parents, the active thread limit and announcement messages that must be published first are not checked.
  • Plan deviation: hasCachedPermission now takes several permissions (true when the bot has all of them), so ViewChannel and CreatePublicThreads cost one member and permission read instead of two.

Before merging: discord.js#11500 is a draft. Re-check it for shape or semantics changes, and hold this PR if they change.

Key changes

  • packages/plugin-gateway/src/structures/messages/Message.ts: new threadable getter; hasCachedPermission accepts several permissions.
  • packages/plugin-gateway/tests/sync-getters.test.ts: DM, HasThread, thread channel, voice channel, text and announcement with and without CreatePublicThreads, administrator bot, ChannelUncached, GuildUncachedMe, and the asynchronous-cache promise form.
  • packages/plugin-gateway/tests/types/sync-getters.ts: message.threadable in messageChecks.
  • packages/plugin-gateway/README.md: threadable added to the list of discord.js getters.
  • .changeset/gateway-message-threadable.md: minor bump for @wolfstar/plugin-gateway.

Verification (run locally): pnpm build, pnpm typecheck and pnpm test (121 files, 1721 tests) pass. pnpm lint passes oxlint (pre-existing warnings only); oxfmt --check reports every file on my Windows checkout because the working tree has CRLF line endings, unrelated to this change. The files I touched were formatted by the oxfmt pre-commit hook.

Type of Change

  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation change
  • Workflow / CI change

Pre-flight Checklist

  • I have read the Contributing Guidelines (if applicable)
  • My code follows the code style of this project
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • I have updated the documentation accordingly
  • I added a changeset with pnpm changeset (or pnpm changeset add --empty if no release is needed). See .changeset/README.md.

🤖 AI disclosure: Claude Code was used on this PR. Code written with claude-sonnet-5-5; PR description written with claude-sonnet-5-5. AI policy.

@coldtea-pr-lens

coldtea-pr-lens Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Architecture

Architecture diagram for wolfstar-project/plugins at 21172b0

Play the walkthrough


Data flow

Data flow diagram for wolfstar-project/plugins at 21172b0

Follow each request


Review

Nothing flagged · reviewed 21172b0


Tip

Click the link under each diagram to open it on a canvas you can zoom, pan and step through

🪧 More tips
  • Run npx skills add coldteadotai/pr-lens, then tell your coding agent: "Diagram the change you just made with PR Lens and attach it to the pull request."
  • Run npx @coldtea/pr-lens-cli analyze --base origin/main on a branch, then npx @coldtea/pr-lens-cli render .pr-lens/graph.json. Same lenses, your own model key, before the pull request exists
  • The diagrams are links. Click one to open it on the canvas, then press W or click play to walk through the change
  • Open a diagram on the canvas, then press W or click play to walk through the change one step at a time
  • The CLI's render reads .github/pr-lens.yml and applies your renames, exclusions and lane pins at draw time
  • Set github.comment.collapsed: true in .github/pr-lens.yml to fold the comment behind one View architecture and data flow row. Drawing still runs as before
  • Set github.draw: on-demand in .github/pr-lens.yml and PR Lens stops drawing pull requests on its own. Comment @pr-lens draw on a pull request when you want that one drawn
  • Add .github/workflows/pr-lens.yml with coldteadotai/pr-lens/packages/action@v0 and your model provider's key as its api-key to run PR Lens from your own CI. Any /chat/completions endpoint works
  • After a push, tick Redraw to draw the latest commit
  • Switch GitHub to dark mode and the diagrams follow. The moving dots are this pull request's data in motion

Thanks for using PR Lens! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

@wolfstarbot wolfstarbot added the packages:plugin-gateway Changes in plugin-gateway label Oct 17, 2026

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes: the full diff of the single commit adding Message#threadable.

  • Message#threadable: built like crosspostable (cache-only, CacheRead<boolean>, same ChannelUncached / GuildUncachedMe / GuildUncached behaviour), false for HasThread or non-guild messages, and limited to text and announcement channels with ViewChannel and CreatePublicThreads.
  • Variadic hasCachedPermission: now true only when the bot has every listed permission. The existing single-permission callers behave as before.
  • Tests, type check, README, changeset: sync and async-cache cases, the administrator divergence from discord.js, and a minor changeset.

The one pending item is already in the PR description: discord.js#11500 is still a draft, so re-check it before merging.

Pullfrog  | View workflow run | Using claude-sonnet-5-5 | 𝕏

@kodiakhq
kodiakhq Bot merged commit 12a880f into main Oct 17, 2026
18 checks passed
@kodiakhq
kodiakhq Bot deleted the feat/plugin-gateway-message-threadable branch October 17, 2026 09:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

packages:plugin-gateway Changes in plugin-gateway

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(plugin-gateway): Message#threadable (discord.js parity)

2 participants