Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 30 additions & 10 deletions dist/src/sources/Spotify.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/src/sources/Spotify.js.map

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions dist/src/typings/Interfaces.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ export interface IOptionsManager {
limitLoadArtist?: number;
limitLoadSearch?: number;
limitLoadRecommendations?: number;
limitLoadPlaylistPage?: number;
limitLoadAlbumPage?: number;
};
deezer?: {
maxSearchResults?: number;
Expand Down
41 changes: 29 additions & 12 deletions docs/content/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,9 @@ A showcase for our amazing community
::
::

## Contributors
## Meet the Team

### Development Team & Collaborators
::team-card-group
::team-card
---
Expand Down Expand Up @@ -421,31 +423,46 @@ A showcase for our amazing community
::team-card
---
center: false
avatar: https://cdn.discordapp.com/avatars/336885637934481409/371faca58eb88781b922d4967b91fab4.png?size=2048
name: xotakfr
title: Tester & Bug Hunter
avatar: https://avatars.githubusercontent.com/u/50148901?s=60&v=4
name: Comicallybad
title: Collaborator & Developer
links:
- icon: lucide:github
to: https://github.com/xotakfr
to: https://github.com/comicallybad
---
::
::team-card
---
center: false
avatar: https://images-ext-1.discordapp.net/external/EzD_6L_K28EMUN8RwQhssNUaZEyVN1H3dG6VIHczPvc/%3Fsize%3D2048/https/cdn.discordapp.com/avatars/389709853511122944/cd8fa0420ae13e16f5bfd87340da35d8.png?format=webp&quality=lossless&width=810&height=810
name: iamforster
title: Tester & Bug Hunter
avatar: https://avatars.githubusercontent.com/u/76094069?v=4
name: UnschooledGamer
title: Collaborator
links:
- icon: lucide:github
to: https://github.com/UnschooledGamer
---
::
::team-card
---
center: false
avatar: https://avatars.githubusercontent.com/u/50148901?s=60&v=4
name: Comicallybad
title: Bug Fixes
avatar: https://cdn.discordapp.com/avatars/336885637934481409/371faca58eb88781b922d4967b91fab4.png?size=2048
name: xotakfr
title: Collaborator
links:
- icon: lucide:github
to: https://github.com/comicallybad
to: https://github.com/xotakfr
---
::
::

### Our Amazing Contributors
::team-card-group
::team-card
---
center: false
avatar: https://images-ext-1.discordapp.net/external/EzD_6L_K28EMUN8RwQhssNUaZEyVN1H3dG6VIHczPvc/%3Fsize%3D2048/https/cdn.discordapp.com/avatars/389709853511122944/cd8fa0420ae13e16f5bfd87340da35d8.png?format=webp&quality=lossless&width=810&height=810
name: iamforster
title: Tester & Bug Hunter
---
::
::team-card
Expand Down
46 changes: 36 additions & 10 deletions src/sources/Spotify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,12 @@ export default class Spotify implements ISource {
case 'album':
case 'playlist': {
const base = link.type === 'album' ? 'albums' : 'playlists';
const data = await this.apiRequest(`/${base}/${link.id}`);
const pageLimit =
link.type === 'playlist'
? this.manager.options.spotify?.limitLoadPlaylistPage ?? 100
: this.manager.options.spotify?.limitLoadAlbumPage ?? 50;

const data = await this.apiRequest(`/${base}/${link.id}?limit=${pageLimit}`);
if (!data || data.error) {
return { loadType: 'error', data: { message: `${link.type} not found.` } };
}
Expand All @@ -228,14 +233,35 @@ export default class Spotify implements ISource {
: data.tracks.items;
items = items.filter(Boolean);

let next = data.tracks.next;
const max =
options?.limit ?? (link.type === 'playlist'
? this.manager.options.spotify?.limitLoadPlaylist ?? this.manager.options.playlistLoadLimit
: this.manager.options.spotify?.limitLoadAlbum ?? this.manager.options.playlistLoadLimit);
options?.limit ??
(link.type === 'playlist'
? this.manager.options.spotify?.limitLoadPlaylist ??
this.manager.options.playlistLoadLimit
: this.manager.options.spotify?.limitLoadAlbum ??
this.manager.options.playlistLoadLimit);

while (next && (!max || items.length < max)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The while loop condition !max is problematic when max is 0. In JavaScript, !0 evaluates to true, which causes the loop to run as if there's no limit, fetching all pages of a playlist/album. This is inefficient and doesn't respect the user's intent to load zero tracks. The loop should not execute if max is 0.

A better way to check for an unlimited scenario is max == null, which is true for both null and undefined but false for 0.

Suggested change
while (next && (!max || items.length < max)) {
while (next && (max == null || items.length < max)) {

const nextPage = await this.apiRequest(next);
if (!nextPage || nextPage.error) break;
const newItems =
link.type === 'playlist'
? nextPage.items.map((i: any) => i.track)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Using any for items from the Spotify API response bypasses TypeScript's type checking. This can lead to runtime errors if the API contract changes and reduces code maintainability. This pattern is also used on line 258.

Consider defining interfaces for the expected API response structures to leverage TypeScript's type safety. For example:

interface SpotifyPlaylistTrack {
  track: SpotifyTrackObject;
  // ... other fields from Spotify API
}

interface SpotifyTrackObject {
  id: string;
  name: string;
  external_urls?: { spotify?: string };
  // ... other fields from Spotify API
}

Using these interfaces would make the code more robust and self-documenting.

: nextPage.items;
items.push(...newItems.filter(Boolean));
next = nextPage.next;
}

if (max != null) items = items.slice(0, max);

const tracks = items.map((item: any) => this.buildTrack(item, item.external_urls.spotify));
return { loadType: 'playlist', data: { info: { name: data.name, selectedTrack: 0 }, tracks } };
const tracks = items.map((item: any) =>
this.buildTrack(item, item.external_urls?.spotify)
);
return {
loadType: 'playlist',
data: { info: { name: data.name, selectedTrack: 0 }, tracks },
};
}

default:
Expand All @@ -245,10 +271,10 @@ export default class Spotify implements ISource {

private getLinkType(url: string): { type: string; id: string } | null {
const regex: Record<string, RegExp> = {
track: /open\.spotify\.com\/(?:intl-[^/]+\/)?track\/(\w+)/,
album: /open\.spotify\.com\/(?:intl-[^/]+\/)?album\/(\w+)/,
playlist: /open\.spotify\.com\/(?:intl-[^/]+\/)?playlist\/(\w+)/,
artist: /open\.spotify\.com\/(?:intl-[^/]+\/)?artist\/(\w+)/,
track: /(?:open\.spotify\.com\/(?:intl-[^/]+\/)?track\/|spotify:track:)(\w+)/,
album: /(?:open\.spotify\.com\/(?:intl-[^/]+\/)?album\/|spotify:album:)(\w+)/,
playlist: /(?:open\.spotify\.com\/(?:intl-[^/]+\/)?playlist\/|spotify:playlist:)(\w+)/,
artist: /(?:open\.spotify\.com\/(?:intl-[^/]+\/)?artist\/|spotify:artist:)(\w+)/,
};

for (const type in regex) {
Expand Down
2 changes: 2 additions & 0 deletions src/typings/Interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ export interface IOptionsManager {
limitLoadArtist?: number;
limitLoadSearch?: number;
limitLoadRecommendations?: number;
limitLoadPlaylistPage?: number;
limitLoadAlbumPage?: number;
};
deezer?: {
maxSearchResults?: number;
Expand Down
2 changes: 1 addition & 1 deletion testBot/bot.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ client.manager = new Manager({
database: {
provider: "local",
},
playlistLoadLimit: 3,
playlistLoadLimit: 2000,
spotify: {
clientId: "c5a8160518fd4293b09f9bce0fcda0f0",
clientSecret: "3871150b7e13430db154cadb86277b02",
Expand Down
Loading