Skip to content

feat(structures): add url getters for image assets#11406

Open
Qjuh wants to merge 2 commits intodiscordjs:mainfrom
Qjuh:feat/structures-url-methods
Open

feat(structures): add url getters for image assets#11406
Qjuh wants to merge 2 commits intodiscordjs:mainfrom
Qjuh:feat/structures-url-methods

Conversation

@Qjuh
Copy link
Member

@Qjuh Qjuh commented Jan 27, 2026

Adds url getters or *URL(format) methods for getting the URLs to image assets associated with image hashs or ids of structures.

@Qjuh Qjuh requested a review from a team as a code owner January 27, 2026 18:15
@vercel
Copy link

vercel bot commented Jan 27, 2026

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

2 Skipped Deployments
Project Deployment Review Updated (UTC)
discord-js Skipped Skipped Jan 27, 2026 6:36pm
discord-js-guide Skipped Skipped Jan 27, 2026 6:36pm

Request Review

@vercel vercel bot temporarily deployed to Preview – discord-js-guide January 27, 2026 18:15 Inactive
@vercel vercel bot temporarily deployed to Preview – discord-js January 27, 2026 18:15 Inactive
@Qjuh Qjuh changed the title feat: add url getters for image assets feat(structures): add url getters for image assets Jan 27, 2026
@codecov
Copy link

codecov bot commented Jan 27, 2026

Codecov Report

❌ Patch coverage is 0% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 32.04%. Comparing base (7a7fecb) to head (4aac35e).

Files with missing lines Patch % Lines
packages/structures/src/users/User.ts 0.00% 8 Missing ⚠️
packages/structures/src/stickers/Sticker.ts 0.00% 3 Missing ⚠️
packages/structures/src/emojis/Emoji.ts 0.00% 2 Missing ⚠️
...kages/structures/src/users/AvatarDecorationData.ts 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #11406      +/-   ##
==========================================
- Coverage   32.07%   32.04%   -0.04%     
==========================================
  Files         375      375              
  Lines       13711    13726      +15     
  Branches     1077     1084       +7     
==========================================
  Hits         4398     4398              
- Misses       9179     9194      +15     
  Partials      134      134              
Flag Coverage Δ
structures 40.97% <0.00%> (-0.51%) ⬇️

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.

@coderabbitai
Copy link

coderabbitai bot commented Jan 27, 2026

📝 Walkthrough

Walkthrough

This PR adds public methods across multiple Discord structure classes to generate CDN URLs for various assets. Emoji, Sticker, AvatarDecorationData, and User classes receive new URL accessor methods that return asset CDN URLs or null when assets are unavailable.

Changes

Cohort / File(s) Summary
Asset URL accessors
packages/structures/src/emojis/Emoji.ts, packages/structures/src/stickers/Sticker.ts
Added url(format) method to both classes with format parameter (WebP default for Emoji, PNG for Sticker). Constructs CDN URL via RouteBases and CDNRoutes when asset ID is present, returns null otherwise. Added corresponding imports for CDNRoutes, ImageFormat, RouteBases, and format type definitions.
Avatar decoration asset URL
packages/structures/src/users/AvatarDecorationData.ts
Added public assetURL() method returning CDN URL for avatar decoration asset using isFieldSet guard. Returns null when asset field is absent. Introduced CDNRoutes, RouteBases imports and type APIAvatarDecorationData.
User avatar and banner URLs
packages/structures/src/users/User.ts
Added four avatar/banner URL helpers: avatarURL(format), defaultAvatarURL getter, displayAvatarURL(format), and bannerURL(format). avatarURL and bannerURL use format parameters (WebP default), defaultAvatarURL computes from discriminator or ID-derived index, displayAvatarURL prefers avatar with fallback to default. Introduced CDNRoutes, RouteBases, ImageFormat, format type definitions, and both isIdSet and isFieldSet utilities.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description is directly related to the changeset, explaining that URL getters/methods are being added for image assets associated with image hashes or IDs.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title clearly and concisely describes the main change: adding URL getters/methods for image assets across multiple structure classes.

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

✨ Finishing touches
  • 📝 Generate docstrings

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: 2

🤖 Fix all issues with AI agents
In `@packages/structures/src/stickers/Sticker.ts`:
- Around line 74-80: The Sticker.url method currently defaults the format
parameter to ImageFormat.PNG which causes Lottie/GIF stickers to generate
incorrect URLs; change url(format?: StickerFormat) so the parameter is optional
and, inside the method, if format is undefined resolve it using the sticker's
formatType via the extension map (e.g.,
StickerFormatExtensionMap[this.formatType]) before building the CDN URL (keep
the isIdSet(this[kData].id) guard and CDNRoutes.sticker call). Ensure you
reference the Sticker.url method, the format parameter, this.formatType (or the
equivalent stored on this[kData]), StickerFormatExtensionMap, and
CDNRoutes.sticker when making the change.

In `@packages/structures/src/users/User.ts`:
- Around line 91-97: The defaultAvatarURL getter currently converts a snowflake
to Number before modulo, causing precision loss; update the id-based branch to
perform the shift and modulo using BigInt and only cast the small remainder to
Number. In the defaultAvatarURL getter (referencing this[kData], isIdSet,
isFieldSet, and CDNRoutes.defaultUserAvatar), change the id path to compute
(BigInt(this[kData].id) >> 22n) % 6n and then Number(...) that result so the
remainder is accurate, leaving the discriminator branch unchanged.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7a7fecb and dda424c.

📒 Files selected for processing (4)
  • packages/structures/src/emojis/Emoji.ts
  • packages/structures/src/stickers/Sticker.ts
  • packages/structures/src/users/AvatarDecorationData.ts
  • packages/structures/src/users/User.ts
🧰 Additional context used
🧬 Code graph analysis (3)
packages/structures/src/stickers/Sticker.ts (2)
packages/structures/src/utils/type-guards.ts (1)
  • isIdSet (1-3)
packages/structures/src/utils/symbols.ts (1)
  • kData (1-1)
packages/structures/src/users/AvatarDecorationData.ts (2)
packages/structures/src/utils/type-guards.ts (1)
  • isFieldSet (25-32)
packages/structures/src/utils/symbols.ts (1)
  • kData (1-1)
packages/structures/src/users/User.ts (2)
packages/structures/src/utils/type-guards.ts (2)
  • isIdSet (1-3)
  • isFieldSet (25-32)
packages/structures/src/utils/symbols.ts (1)
  • kData (1-1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Tests
🔇 Additional comments (3)
packages/structures/src/emojis/Emoji.ts (1)

89-96: Looks good: emoji URL helper is safe and consistent.

The ID guard and CDN route composition align well with the rest of the structures helpers.

packages/structures/src/users/AvatarDecorationData.ts (1)

42-50: Asset URL helper looks good.

The field guard + CDN route composition is clean and safe.

packages/structures/src/users/User.ts (1)

82-86: Avatar/banner URL helpers look good.

The guard patterns and fallback to defaultAvatarURL are clean and consistent.

Also applies to: 104-106, 145-148

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

import { isFieldSet, isIdSet } from '../utils/type-guards.js';
import type { Partialize } from '../utils/types.js';

const StickerFormatExtensionMap = {
Copy link
Member

Choose a reason for hiding this comment

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

This should be exported to the consumer.
Maybe this should be moved to discord-api-types?

Comment on lines +44 to +45
*
* @returns the URL to the asset of this avatar decoration
Copy link
Member

Choose a reason for hiding this comment

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

redundant

Suggested change
*
* @returns the URL to the asset of this avatar decoration

}

/**
* Get the URL to the user avatar
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* Get the URL to the user avatar
* Get the URL to the user's avatar

*/
public get url() {
return isIdSet(this[kData].id) && isFieldSet(this[kData], 'format_type', 'number')
? `${RouteBases.cdn}${CDNRoutes.sticker(this[kData].id.toString(), StickerFormatExtensionMap[this[kData].format_type] as StickerFormat)}`
Copy link
Member

Choose a reason for hiding this comment

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

Not particularly fond of this cast... isEnumValue(this[kData].format_type, StickerFormatType) time? 😅

Comment on lines +93 to +97
? `${RouteBases.cdn}${CDNRoutes.defaultUserAvatar(
(isFieldSet(this[kData], 'discriminator', 'string') && this[kData].discriminator.length === 4
? Number(this[kData].discriminator) % 5
: Number(BigInt(this[kData].id) >> 22n) % 6) as DefaultUserAvatarAssets,
)}`
Copy link
Member

Choose a reason for hiding this comment

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

Too much logic here IMO. I'd rather split this up a bit

}

/**
* Get the URL to the user banner
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* Get the URL to the user banner
* Get the URL to the user's banner

@github-project-automation github-project-automation bot moved this from Todo to Review in Progress in discord.js Jan 27, 2026
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.

2 participants