Last active
May 3, 2023 11:57
-
-
Save Sans3108/80950adef9d5970bf2bceac7cd850619 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { BaseExtractor, ExtractorInfo, ExtractorSearchContext, Playlist, QueryType, SearchQueryType, Track, Util } from 'discord-player'; | |
import SoundCloud from 'soundcloud.ts'; | |
//@ts-ignore Idk why but it doesnt work if I just do `new SoundCloud()` | |
const soundcloud: SoundCloud = new SoundCloud.default(); | |
export class SoundCloudExtractor extends BaseExtractor { | |
public static identifier = 'apiBasedSoundCloudExtractor' as const; | |
public async validate(query: string, type?: SearchQueryType | null | undefined): Promise<boolean> { | |
if (typeof query !== 'string') return false; | |
// prettier-ignore | |
const queryTypes = [ | |
QueryType.SOUNDCLOUD, | |
QueryType.SOUNDCLOUD_PLAYLIST, | |
QueryType.SOUNDCLOUD_SEARCH, | |
QueryType.SOUNDCLOUD_TRACK, | |
QueryType.AUTO, | |
QueryType.AUTO_SEARCH | |
] as SearchQueryType[]; | |
return queryTypes.some(r => r === type); | |
} | |
public async handle(query: string, context: ExtractorSearchContext): Promise<ExtractorInfo> { | |
switch (context.type) { | |
case QueryType.SOUNDCLOUD_TRACK: { | |
const trackInfo = await soundcloud.tracks.getV2(query).catch(Util.noop); | |
if (!trackInfo) return this.emptyResponse(); | |
const track = new Track(this.context.player, { | |
title: trackInfo.title, | |
url: trackInfo.permalink_url, | |
duration: Util.buildTimeCode(Util.parseMS(trackInfo.duration)), | |
description: trackInfo.description ?? '', | |
thumbnail: trackInfo.artwork_url, | |
views: trackInfo.playback_count, | |
author: trackInfo.user.username, | |
requestedBy: context.requestedBy, | |
source: 'soundcloud', | |
engine: trackInfo, | |
queryType: context.type | |
}); | |
track.extractor = this; | |
return { playlist: null, tracks: [track] }; | |
} | |
case QueryType.SOUNDCLOUD_PLAYLIST: { | |
const data = await soundcloud.playlists.getV2(query).catch(Util.noop); | |
if (!data) return { playlist: null, tracks: [] }; | |
const res = new Playlist(this.context.player, { | |
title: data.title, | |
description: data.description ?? '', | |
thumbnail: data.artwork_url ?? data.tracks[0].artwork_url, | |
type: 'playlist', | |
source: 'soundcloud', | |
author: { | |
name: data.user.username, | |
url: data.user.permalink_url | |
}, | |
tracks: [], | |
id: `${data.id}`, | |
url: data.permalink_url, | |
rawPlaylist: data | |
}); | |
for (const song of data.tracks) { | |
const track = new Track(this.context.player, { | |
title: song.title, | |
description: song.description ?? '', | |
author: song.user.username, | |
url: song.permalink_url, | |
thumbnail: song.artwork_url, | |
duration: Util.buildTimeCode(Util.parseMS(song.duration)), | |
views: song.playback_count, | |
requestedBy: context.requestedBy, | |
playlist: res, | |
source: 'soundcloud', | |
engine: song, | |
queryType: context.type | |
}); | |
track.extractor = this; | |
res.tracks.push(track); | |
} | |
return { playlist: res, tracks: res.tracks }; | |
} | |
default: { | |
const tracks = await soundcloud.tracks.searchV2({ q: query }).catch(Util.noop); | |
if (!tracks || !tracks.collection.length) return this.emptyResponse(); | |
const resolvedTracks: Track[] = []; | |
for (const searchedTrack of tracks.collection) { | |
const trackInfo = await soundcloud.tracks.getV2(searchedTrack.permalink_url).catch(Util.noop); | |
if (!trackInfo) continue; | |
const track = new Track(this.context.player, { | |
title: trackInfo.title, | |
url: trackInfo.permalink_url, | |
duration: Util.buildTimeCode(Util.parseMS(trackInfo.duration)), | |
description: trackInfo.description ?? '', | |
thumbnail: trackInfo.artwork_url, | |
views: trackInfo.playback_count, | |
author: trackInfo.user.username, | |
requestedBy: context.requestedBy, | |
source: 'soundcloud', | |
engine: trackInfo, | |
queryType: 'soundcloudTrack' | |
}); | |
track.extractor = this; | |
resolvedTracks.push(track); | |
} | |
return { playlist: null, tracks: resolvedTracks }; | |
} | |
} | |
} | |
public async getRelatedTracks(track: Track) { | |
if (track.queryType === QueryType.SOUNDCLOUD_TRACK) | |
return this.handle(track.author || track.title, { | |
requestedBy: track.requestedBy, | |
type: QueryType.SOUNDCLOUD_SEARCH | |
}); | |
return this.createResponse(); | |
} | |
public emptyResponse(): ExtractorInfo { | |
return { playlist: null, tracks: [] }; | |
} | |
public async stream(info: Track) { | |
const url = await soundcloud.util.streamLink(info.url).catch(Util.noop); | |
if (!url) throw new Error('Could not extract stream from this track source'); | |
return url; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment