Skip to content

feat(structures): add Presences structures #11411

Open
AsadHumayun wants to merge 39 commits intodiscordjs:mainfrom
AsadHumayun:feat/add-presence-structures
Open

feat(structures): add Presences structures #11411
AsadHumayun wants to merge 39 commits intodiscordjs:mainfrom
AsadHumayun:feat/add-presence-structures

Conversation

@AsadHumayun
Copy link
Contributor

@AsadHumayun AsadHumayun commented Jan 31, 2026

This PR will aim to implement the GatewayPresence structures.

Mentioning #10981 for visibility.

Feel free to leave any comments or feedback and I will address as-is but PR is in a very early draft state at the moment with only really the empty structures files laid out.

I will also be adding tests on this PR once I'm done with the structures.

Notes for when PR gets ready:
Prefer "activity secrets" or "activity's secrets"?
https://github.com/AsadHumayun/discord.js/blob/2ed8c63b71af9c388ac054eb111d41fd26c2b4e1/packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivitySecrets.ts#L10-L29

I've gone ahead and added the tests for these structures. While adding the tests, they uncovered a mistake that I had previously made with one of the structures (and corrected it) [acad472].

For GatewayActivity, some properties were not exposed as getters as they were either not documented on the Discord API docs, or were marked @unstable in discord-api-tyes, e.g:

https://github.com/discordjs/discord-api-types/blob/592503aa18a7b970bd6275ca59369b3b4c86b7be/payloads/v10/gateway.ts#L141-L146

I did consider adding this as a remark on the class, but these are undocumented fields so I decided not to in the end.

As we are already deciding not to expose deprecated API fields, I figured it made sense to also not expose these (IIRC discord.js as a library do not encourage use of undocumented API fields).

One additional note I'd like to highlight:

https://github.com/AsadHumayun/discord.js/blob/a22076a0d644443a0328212fc0f54c42f2a372ff/packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivityAssets.ts#L70-L82

In case it doesn't embed, the GatewayPresenceActivityAssets structure's documentation shows a field invite_cover_image, which is not exposed by its corresponding discord-api-types structure; see

https://github.com/discordjs/discord-api-types/blob/592503aa18a7b970bd6275ca59369b3b4c86b7be/payloads/v10/gateway.ts#L353-L355

I will also append this comment to the topmost comment on this PR so that it does not get missed. Apologies for this taking a while to get through, not been feeling great as of late.

@vercel
Copy link

vercel bot commented Jan 31, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated (UTC)
discord-js Skipped Skipped Feb 11, 2026 11:14pm
discord-js-guide Skipped Skipped Feb 11, 2026 11:14pm

Request Review

@vercel vercel bot temporarily deployed to Preview – discord-js January 31, 2026 22:37 Inactive
@vercel vercel bot temporarily deployed to Preview – discord-js-guide January 31, 2026 22:37 Inactive
@codecov
Copy link

codecov bot commented Jan 31, 2026

Codecov Report

❌ Patch coverage is 76.51515% with 31 lines in your changes missing coverage. Please review.
✅ Project coverage is 32.39%. Comparing base (c460a92) to head (5d529bf).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...ackages/structures/src/entitlements/Entitlement.ts 0.00% 9 Missing ⚠️
...kages/structures/src/subscriptions/Subscription.ts 0.00% 4 Missing ⚠️
.../structures/src/bitfields/ActivityFlagsBitField.ts 33.33% 2 Missing ⚠️
...ages/structures/src/presences/Activity/Activity.ts 93.10% 0 Missing and 2 partials ⚠️
packages/structures/src/channels/Channel.ts 0.00% 1 Missing ⚠️
packages/structures/src/emojis/Emoji.ts 0.00% 1 Missing ⚠️
packages/structures/src/messages/Message.ts 75.00% 0 Missing and 1 partial ⚠️
packages/structures/src/messages/MessageCall.ts 0.00% 1 Missing ⚠️
packages/structures/src/polls/Poll.ts 0.00% 1 Missing ⚠️
...structures/src/presences/Activity/ActivityParty.ts 90.90% 0 Missing and 1 partial ⚠️
... and 8 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #11411      +/-   ##
==========================================
+ Coverage   31.56%   32.39%   +0.83%     
==========================================
  Files         386      395       +9     
  Lines       13944    14042      +98     
  Branches     1098     1104       +6     
==========================================
+ Hits         4401     4549     +148     
+ Misses       9409     9355      -54     
- Partials      134      138       +4     
Flag Coverage Δ
structures 42.35% <76.51%> (+7.32%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@vercel vercel bot temporarily deployed to Preview – discord-js-guide February 1, 2026 01:53 Inactive
@vercel vercel bot temporarily deployed to Preview – discord-js February 1, 2026 01:53 Inactive
@vercel vercel bot temporarily deployed to Preview – discord-js-guide February 1, 2026 13:54 Inactive
@vercel vercel bot temporarily deployed to Preview – discord-js February 1, 2026 13:54 Inactive
@AsadHumayun
Copy link
Contributor Author

Note to self: PR CI failed due to missing dependent files. This should be fixed when the PR is in a finished/ready to review state.

@vercel vercel bot temporarily deployed to Preview – discord-js February 1, 2026 16:10 Inactive
@vercel vercel bot temporarily deployed to Preview – discord-js-guide February 1, 2026 16:10 Inactive
@vercel vercel bot temporarily deployed to Preview – discord-js February 2, 2026 21:24 Inactive
@vercel vercel bot temporarily deployed to Preview – discord-js-guide February 2, 2026 21:24 Inactive
@AsadHumayun
Copy link
Contributor Author

Note / CI for latest commit here was cancelled due to GitHub Actions not being picked up by a runner.

The job was not acquired by Runner of type hosted even after multiple attempts

@Jiralite
Copy link
Member

Jiralite commented Feb 2, 2026

Don't worry about that.

https://www.githubstatus.com/incidents/xwn6hjps36ty

@vercel vercel bot temporarily deployed to Preview – discord-js-guide February 4, 2026 23:03 Inactive
@vercel vercel bot temporarily deployed to Preview – discord-js February 4, 2026 23:03 Inactive
@AsadHumayun AsadHumayun marked this pull request as ready for review February 4, 2026 23:20
@AsadHumayun AsadHumayun requested a review from a team as a code owner February 4, 2026 23:20
@AsadHumayun
Copy link
Contributor Author

I've gone ahead and added the tests for these structures. While adding the tests, they uncovered a mistake that I had previously made with one of the structures (and corrected it) [acad472].

For GatewayActivity, some properties were not exposed as getters as they were either not documented on the Discord API docs, or were marked @unstable in discord-api-tyes, e.g:

https://github.com/discordjs/discord-api-types/blob/592503aa18a7b970bd6275ca59369b3b4c86b7be/payloads/v10/gateway.ts#L141-L146

I did consider adding this as a remark on the class, but these are undocumented fields so I decided not to in the end.

As we are already deciding not to expose deprecated API fields, I figured it made sense to also not expose these (IIRC discord.js as a library do not encourage use of undocumented API fields).

One additional note I'd like to highlight:

https://github.com/AsadHumayun/discord.js/blob/a22076a0d644443a0328212fc0f54c42f2a372ff/packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivityAssets.ts#L70-L82

In case it doesn't embed, the GatewayPresenceActivityAssets structure's documentation shows a field invite_cover_image, which is not exposed by its corresponding discord-api-types structure; see

https://github.com/discordjs/discord-api-types/blob/592503aa18a7b970bd6275ca59369b3b4c86b7be/payloads/v10/gateway.ts#L353-L355

I will also append this comment to the topmost comment on this PR so that it does not get missed. Apologies for this taking a while to get through, not been feeling great as of late.

@coderabbitai
Copy link

coderabbitai bot commented Feb 4, 2026

📝 Walkthrough

Walkthrough

This PR introduces a comprehensive gateway presence structures implementation, adding multiple TypeScript classes for handling Discord gateway presence data. Classes include Activity-related substructures (Assets, Button, Emoji, Party, Secrets, Timestamps), GatewayPresenceUpdate, GatewayPresenceClientStatus, and a new ActivityFlagsBitField. All follow a consistent pattern extending the Structure base class with generic Omitted parameters and providing type-safe property accessors.

Changes

Cohort / File(s) Summary
Activity Substructures
packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivityAssets.ts, GatewayPresenceActivityButton.ts, GatewayPresenceActivityEmoji.ts, GatewayPresenceActivityParty.ts, GatewayPresenceActivitySecrets.ts, GatewayPresenceActivityTimestamps.ts
Six new Structure-extending classes providing typed access to Discord activity data. Each implements DataTemplate, constructor, and getters. Notable: Emoji includes URL generation via CDN routes; Party and Emoji include computed timestamps from Snowflake IDs; Timestamps provides Date conversions.
Main Activity Class
packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivity.ts
Core activity wrapper class with 14 getters exposing activity properties (name, type, URL, timestamps, flags, details, state). Includes flags getter returning GatewayPresenceActivityFlagsBitField when applicable and multiple computed properties (createdAt/createdTimestamp).
Gateway Presence Core
packages/structures/src/gatewayPresences/GatewayPresenceClientStatus.ts, GatewayPresenceUpdate.ts
Two Structure-extending classes. ClientStatus provides desktop/mobile/web status getters. GatewayPresenceUpdate exposes since timestamp conversion to Date and status/afk accessors.
Bitfields
packages/structures/src/bitfields/GatewayPresenceActivityFlagsBitField.ts
New BitField subclass for ActivityFlags with overridden toJSON method for specific JSON representation.
Module Exports
packages/structures/src/gatewayPresences/Activity/index.ts, packages/structures/src/gatewayPresences/index.ts, packages/structures/src/index.ts
Barrel files consolidating exports for Activity substructures and gateway presences; main structures index updated to expose gatewayPresences module.
Tests
packages/structures/__tests__/gatewayPresences.test.ts
Comprehensive test suite (364 lines) validating instantiation, getters, toJSON output, in-place patching via kPatch symbol, timestamp computations, URL generation, and cross-structure consistency for all gateway presence classes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The PR description comprehensively explains the implementation of GatewayPresence structures, including decisions about undocumented fields, test additions, bug fixes, and known API documentation discrepancies.
Title check ✅ Passed The title 'feat(structures): add Presences structures' accurately summarizes the main change, which is adding multiple new gateway presence-related structure classes and their tests to the structures package.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


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

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Fix all issues with AI agents
In `@packages/structures/__tests__/gatewayPresences.test.ts`:
- Around line 228-231: The test 'correct value for all getters' contains a
tautological assertion using expect(instance.url).toBe(instance.url); replace it
so the getter is compared against the source fixture: change to
expect(instance.url).toBe(data.url) (and similarly ensure other getters in the
same test compare to the corresponding properties on data, e.g., instance.label
-> data.label).

In
`@packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivityParty.ts`:
- Around line 45-58: Remove the two invalid getters from
GatewayPresenceActivityParty: delete the createdTimestamp and createdAt
accessors (and any direct reliance on isIdSet or DiscordSnowflake.timestampFrom
in that class) because party.id is an arbitrary string, not a Snowflake; if
other code expects these properties, replace those usages with a proper source
of creation time or return undefined/null explicitly where creation time is not
available. Ensure GatewayPresenceActivityParty no longer exposes
createdTimestamp/createdAt and run/adjust any callers that referenced
GatewayPresenceActivityParty.createdTimestamp or .createdAt to avoid relying on
a fabricated timestamp.

In
`@packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivityTimestamps.ts`:
- Around line 52-56: The endAt getter incorrectly casts the stored timestamp to
a string; change the cast in GatewayPresenceActivityTimestamps.endAt to use "as
number" (matching startAt) and ensure the returned Date is constructed from that
numeric timestamp or null if absent; update the endAt getter to mirror the
startAt getter's casting and null handling.

In `@packages/structures/src/gatewayPresences/GatewayPresenceUpdate.ts`:
- Around line 34-44: The TODO about the getter name can be removed and the
docblock clarified: update the JSDoc for the GatewayPresenceUpdate.get since
getter to state it returns a Date|null (e.g., "Time when the client went idle as
a Date object, or null if not idle"), remove the bracketed TODO note, and keep
the existing getter logic that reads this.sinceTimestamp and returns new
Date(timestamp) or null; reference the getter since and the raw numeric property
sinceTimestamp in your changes.

In `@packages/structures/src/gatewayPresences/index.ts`:
- Around line 6-12: Remove the inline TODO in the public barrel
(gatewayPresences index) and either open a tracked issue in the repo describing
the missing requestToSpeak[At] timestamp getter (reference the
VoiceState.requestToSpeakTimestamp pattern) or implement the getter now; ensure
the index export no longer contains the TODO comment and include the new issue
number or PR reference in the codebase or changelog so this work is actionable
outside the barrel.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c71228a and a22076a.

📒 Files selected for processing (14)
  • packages/structures/__tests__/gatewayPresences.test.ts
  • packages/structures/src/bitfields/GatewayPresenceActivityFlagsBitField.ts
  • packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivity.ts
  • packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivityAssets.ts
  • packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivityButton.ts
  • packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivityEmoji.ts
  • packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivityParty.ts
  • packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivitySecrets.ts
  • packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivityTimestamps.ts
  • packages/structures/src/gatewayPresences/Activity/index.ts
  • packages/structures/src/gatewayPresences/GatewayPresenceClientStatus.ts
  • packages/structures/src/gatewayPresences/GatewayPresenceUpdate.ts
  • packages/structures/src/gatewayPresences/index.ts
  • packages/structures/src/index.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2026-01-24T21:41:15.330Z
Learnt from: Qjuh
Repo: discordjs/discord.js PR: 11393
File: packages/structures/src/bitfields/ApplicationFlagsBitField.ts:13-15
Timestamp: 2026-01-24T21:41:15.330Z
Learning: For BitField classes, preserve numeric flags by using super.toJSON(true) when you need a numeric value. The toJSON(asNumber?: boolean) method returns a number when asNumber is true and a string otherwise, so always pass true to obtain a numeric representation for storage/comparison. This guidance applies to similar bitfield classes across the codebase (not just ApplicationFlagsBitField).

Applied to files:

  • packages/structures/src/bitfields/GatewayPresenceActivityFlagsBitField.ts
🧬 Code graph analysis (8)
packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivitySecrets.ts (1)
packages/structures/src/utils/symbols.ts (1)
  • kData (1-1)
packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivityButton.ts (1)
packages/structures/src/utils/symbols.ts (1)
  • kData (1-1)
packages/structures/src/gatewayPresences/GatewayPresenceClientStatus.ts (1)
packages/structures/src/utils/symbols.ts (1)
  • kData (1-1)
packages/structures/src/bitfields/GatewayPresenceActivityFlagsBitField.ts (1)
packages/discord.js/typings/index.d.ts (1)
  • BitField (663-680)
packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivityTimestamps.ts (1)
packages/structures/src/utils/symbols.ts (1)
  • kData (1-1)
packages/structures/src/gatewayPresences/GatewayPresenceUpdate.ts (1)
packages/structures/src/utils/symbols.ts (1)
  • kData (1-1)
packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivityAssets.ts (1)
packages/structures/src/utils/symbols.ts (1)
  • kData (1-1)
packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivity.ts (3)
packages/structures/src/utils/symbols.ts (1)
  • kData (1-1)
packages/structures/src/utils/type-guards.ts (1)
  • isFieldSet (25-32)
packages/structures/src/bitfields/GatewayPresenceActivityFlagsBitField.ts (1)
  • GatewayPresenceActivityFlagsBitField (7-16)
🔇 Additional comments (12)
packages/structures/src/bitfields/GatewayPresenceActivityFlagsBitField.ts (1)

1-16: LGTM!

The implementation correctly follows the BitField pattern. The toJSON(true) override ensures numeric flags are preserved, which aligns with the established pattern for bitfield classes. Based on learnings: "For BitField classes, preserve numeric flags by using super.toJSON(true) when you need a numeric value."

packages/structures/src/gatewayPresences/GatewayPresenceClientStatus.ts (1)

1-46: LGTM!

The class follows the established Structure pattern consistently, with appropriate DataTemplate, constructor, and property getters for desktop, mobile, and web status fields.

packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivityTimestamps.ts (1)

1-40: LGTM!

The imports, class structure, DataTemplate, constructor, and the start/startAt getters follow the established pattern correctly.

packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivityButton.ts (1)

1-42: LGTM!

The implementation follows the established Structure pattern. The @remarks documentation helpfully clarifies the API behavior difference between receiving and sending button data.

packages/structures/src/gatewayPresences/GatewayPresenceUpdate.ts (1)

1-33: LGTM!

The structure, DataTemplate, constructor, and remaining getters (sinceTimestamp, status, afk) follow the established pattern correctly.

Also applies to: 45-61

packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivityEmoji.ts (1)

1-74: LGTM!

The implementation correctly handles snowflake-based timestamp derivation and CDN URL construction with appropriate null safety via isIdSet. The url() method follows Discord CDN patterns properly.

packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivityParty.ts (1)

1-44: LGTM!

The imports, class structure, DataTemplate, constructor, and id/size getters follow the established pattern correctly. The size getter documentation clearly explains the array structure.

packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivityAssets.ts (1)

27-67: LGTM — getters map cleanly to raw data.

packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivity.ts (1)

33-132: LGTM — consistent accessors and safe flag handling.

packages/structures/src/gatewayPresences/Activity/GatewayPresenceActivitySecrets.ts (1)

27-46: LGTM — simple, consistent getters.

packages/structures/src/gatewayPresences/Activity/index.ts (1)

1-7: LGTM — barrel exports look complete.

packages/structures/src/index.ts (1)

6-6: LGTM — gatewayPresences export added.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@AsadHumayun AsadHumayun force-pushed the feat/add-presence-structures branch from 5d529bf to eb1787a Compare February 11, 2026 23:14
@vercel vercel bot temporarily deployed to Preview – discord-js February 11, 2026 23:14 Inactive
@vercel vercel bot temporarily deployed to Preview – discord-js-guide February 11, 2026 23:14 Inactive
@AsadHumayun AsadHumayun changed the title feat(structures): add GatewayPresence structures feat(structures): add Presences structures Feb 11, 2026
@AsadHumayun
Copy link
Contributor Author

AsadHumayun commented Feb 15, 2026

Dropping a quick update on here before I forget

discordjs/discord-api-types#1519 was merged to dapi-types today and the subsequent missing types have been added.

However I imagine that it will still take some time for the new version of dapi-types to get released, and then additional time as the monorepo gets updated to use the new version of dapi-types once that does get released.

We also need a definitive decision regarding moving away from the xAt convention in favour of xDate.

The changes were applied in this commit:

refactor(structures)!: use xDate convention in favour of xAt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Review in Progress

Development

Successfully merging this pull request may close these issues.

4 participants