-
Couldn't load subscription status.
- Fork 17
feat: Soundcloud Support #156
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
12bbba7
353a0bb
01641e1
187d4d1
99d450d
d9c97e7
a4701ca
bdc0f04
943a02b
c8ae12d
f339b38
df02363
1ac64fa
4dd484d
bf0554b
f1684f4
33e8047
6aa35c7
a6c1ddc
5b604aa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| export const snapshot = {}; | ||
|
|
||
| snapshot[`SoundCloud provider > release lookup > track release with downloads enabled 1`] = ` | ||
| { | ||
| artists: [ | ||
| { | ||
| creditedName: "League of Legends", | ||
| externalIds: [ | ||
| { | ||
| id: "leagueoflegends", | ||
| provider: "soundcloud", | ||
| type: "artist", | ||
| }, | ||
| ], | ||
| name: "League of Legends", | ||
| }, | ||
| ], | ||
| availableIn: undefined, | ||
| externalLinks: [ | ||
| { | ||
| types: [ | ||
| "free streaming", | ||
| "free download", | ||
| ], | ||
| url: "https://soundcloud.com/leagueoflegends/piercing-light-mako-remix", | ||
| }, | ||
| ], | ||
| images: [ | ||
| { | ||
| provider: "SoundCloud", | ||
| thumbUrl: "https://i1.sndcdn.com/artworks-000142912000-f05col-t300x300.jpg", | ||
| types: [ | ||
| "front", | ||
| ], | ||
| url: "https://i1.sndcdn.com/artworks-000142912000-f05col-t500x500.jpg", | ||
| }, | ||
| ], | ||
| info: { | ||
| messages: [], | ||
| providers: [ | ||
| { | ||
| apiUrl: "https://api.soundcloud.com/resolve?url=https%3A%2F%2Fsoundcloud.com%2Fleagueoflegends%2Fpiercing-light-mako-remix", | ||
| id: "leagueoflegends/track/piercing-light-mako-remix", | ||
| internalName: "soundcloud", | ||
| lookup: { | ||
| method: "id", | ||
| value: "leagueoflegends/track/piercing-light-mako-remix", | ||
| }, | ||
| name: "SoundCloud", | ||
| url: "https://soundcloud.com/leagueoflegends/piercing-light-mako-remix", | ||
| }, | ||
| ], | ||
| }, | ||
| labels: undefined, | ||
| media: [ | ||
| { | ||
| format: "Digital Media", | ||
| tracklist: [ | ||
| { | ||
| artists: [ | ||
| { | ||
| creditedName: "League of Legends", | ||
| externalIds: [ | ||
| { | ||
| id: "leagueoflegends", | ||
| provider: "soundcloud", | ||
| type: "artist", | ||
| }, | ||
| ], | ||
| name: "League of Legends", | ||
| }, | ||
| ], | ||
| availableIn: undefined, | ||
| isrc: undefined, | ||
| length: 291422, | ||
| number: 1, | ||
| recording: { | ||
| externalIds: [ | ||
| { | ||
| id: "leagueoflegends/piercing-light-mako-remix", | ||
| provider: "soundcloud", | ||
| type: "track", | ||
| }, | ||
| ], | ||
| }, | ||
| title: "Piercing Light (Mako Remix)", | ||
| }, | ||
| ], | ||
| }, | ||
| ], | ||
| packaging: "None", | ||
| releaseDate: { | ||
| day: 12, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The website says 14 January 2016 when I hover the "9 years ago". Even if there is a timezone offset, it can't be two days? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As it turns out, SoundCloud entities have 4 "release" dates... the most reliable being the dedicated release fields, as those are manually entered by the artist (usually pretty rarely, similar to ISRC and UPC data). The date that appears on the website is the |
||
| month: 1, | ||
| year: 2016, | ||
| }, | ||
| title: "Piercing Light (Mako Remix)", | ||
| types: [ | ||
| "Single", | ||
| ], | ||
| } | ||
| `; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,206 @@ | ||
| // Classes from https://github.com/Moebytes/soundcloud.ts | ||
| // MIT License | ||
| export type SoundcloudImageFormats = | ||
| | 't500x500' | ||
| | 'crop' | ||
| | 't300x300' | ||
| | 'large' | ||
| | 't67x67' | ||
| | 'badge' | ||
| | 'small' | ||
| | 'tiny' | ||
| | 'mini'; | ||
|
|
||
| export type SoundcloudLicense = | ||
| | 'no-rights-reserved' | ||
| | 'all-rights-reserved' | ||
| | 'cc-by' | ||
| | 'cc-by-nc' | ||
| | 'cc-by-nd' | ||
| | 'cc-by-sa' | ||
| | 'cc-by-nc-nd' | ||
| | 'cc-by-nc-sa'; | ||
|
|
||
| export type SoundcloudTrackType = | ||
| | 'original' | ||
| | 'remix' | ||
| | 'live' | ||
| | 'recording' | ||
| | 'spoken' | ||
| | 'podcast' | ||
| | 'demo' | ||
| | 'in progress' | ||
| | 'stem' | ||
| | 'loop' | ||
| | 'sound effect' | ||
| | 'sample' | ||
| | 'other'; | ||
|
|
||
| export interface SoundcloudTrack { | ||
| artwork_url: string; | ||
| comment_count: number; | ||
| commentable: boolean; | ||
| created_at: string; | ||
| description: string; | ||
| display_date: string; | ||
| download_count: number; | ||
| downloadable: boolean; | ||
| duration: number; | ||
| embeddable_by: 'all' | 'me' | 'none'; | ||
| full_duration: number; | ||
| genre: string; | ||
| has_downloads_left: boolean; | ||
| id: number; | ||
| kind: string; | ||
| label_name: string; | ||
| last_modified: string; | ||
| license: SoundcloudLicense; | ||
| likes_count: number; | ||
| monetization_model: string; | ||
| permalink: string; | ||
| permalink_url: string; | ||
| playback_count: number; | ||
| policy: string; | ||
| public: boolean; | ||
| purchase_title: string; | ||
| purchase_url: string; | ||
| reposts_count: number; | ||
| secret_token: string; | ||
| sharing: 'private' | 'public'; | ||
| state: 'processing' | 'failed' | 'finished'; | ||
| streamable: boolean; | ||
| tag_list: string; | ||
| title: string; | ||
| uri: string; | ||
| urn: string; | ||
| user: SoundcloudUser; | ||
| user_id: number; | ||
| visuals: string; | ||
| waveform_url: string; | ||
| release: string | null; | ||
| key_signature: string | null; | ||
| isrc: string | null; | ||
| bpm: number | null; | ||
| release_year: number | null; | ||
| release_month: number | null; | ||
| release_day: number | null; | ||
| stream_url: string; | ||
| download_url: string | null; | ||
| available_country_codes: string[] | null; | ||
| secret_uri: string | null; | ||
| user_favorite: boolean | null; | ||
| user_playback_count: number | null; | ||
| favoritings_count: number; | ||
| access: string; | ||
| metadata_artist: string; | ||
| } | ||
|
|
||
| export interface SoundcloudPlaylist { | ||
| duration: number; | ||
| permalink_url: string; | ||
| reposts_count: number; | ||
| genre: string | null; | ||
| permalink: string; | ||
| purchase_url: string | null; | ||
| description: string | null; | ||
| uri: string; | ||
| urn: string; | ||
| label_name: string | null; | ||
| tag_list: string; | ||
| set_type: string; | ||
| public: boolean; | ||
| track_count: number; | ||
| user_id: number; | ||
| last_modified: string; | ||
| license: SoundcloudLicense; | ||
| tracks: SoundcloudTrack[]; | ||
| id: number; | ||
| display_date: string; | ||
| sharing: 'public' | 'private'; | ||
| secret_token: string | null; | ||
| created_at: string; | ||
| likes_count: number; | ||
| kind: string; | ||
| title: string; | ||
| purchase_title: string | null; | ||
| managed_by_feeds: boolean; | ||
| artwork_url: string | null; | ||
| is_album: boolean; | ||
| user: SoundcloudUser; | ||
| published_at: string | null; | ||
| embeddable_by: 'all' | 'me' | 'none'; | ||
| release_year: number | null; | ||
| release_month: number | null; | ||
| release_day: number | null; | ||
| type: string | null; | ||
| playlist_type: string | null; | ||
| } | ||
|
|
||
| export interface SoundcloudUser { | ||
| avatar_url: string; | ||
| city: string; | ||
| comments_count: number; | ||
| country_code: number | null; | ||
| created_at: string; | ||
| creator_subscriptions: SoundcloudCreatorSubscription[]; | ||
| creator_subscription: SoundcloudCreatorSubscription; | ||
| description: string; | ||
| followers_count: number; | ||
| followings_count: number; | ||
| first_name: string; | ||
| full_name: string; | ||
| groups_count: number; | ||
| id: number; | ||
| kind: string; | ||
| last_modified: string; | ||
| last_name: string; | ||
| likes_count: number; | ||
| playlist_likes_count: number; | ||
| permalink: string; | ||
| permalink_url: string; | ||
| playlist_count: number; | ||
| reposts_count: number | null; | ||
| track_count: number; | ||
| uri: string; | ||
| urn: string; | ||
| username: string; | ||
| verified: boolean; | ||
| visuals: { | ||
| urn: string; | ||
| enabled: boolean; | ||
| visuals: SoundcloudVisual[]; | ||
| tracking: null; | ||
| }; | ||
| } | ||
|
|
||
| export interface SoundcloudVisual { | ||
| urn: string; | ||
| entry_time: number; | ||
| visual_url: string; | ||
| } | ||
|
|
||
| export interface SoundcloudCreatorSubscription { | ||
| product: { | ||
| id: string; | ||
| }; | ||
| } | ||
|
|
||
| //Custom Classes | ||
|
|
||
| export type ApiError = { | ||
| code: number; | ||
| message: string; | ||
| link: string; | ||
| status: string; | ||
| errors: string[]; | ||
| error: string | null; | ||
| }; | ||
|
|
||
| export type RawReponse = { | ||
| /** Raw Data from the soundcloud API */ | ||
| apiResponse: SoundcloudTrack | SoundcloudPlaylist; | ||
| /** The type of release, either 'track' or 'playlist' */ | ||
| type: 'track' | 'playlist'; | ||
| /** Url of the release */ | ||
| href: string; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| import { describeProvider, makeProviderOptions } from '@/providers/test_spec.ts'; | ||
| import { stubProviderLookups } from '@/providers/test_stubs.ts'; | ||
| import { assert } from 'std/assert/assert.ts'; | ||
| import { afterAll, describe } from '@std/testing/bdd'; | ||
| import { assertSnapshot } from '@std/testing/snapshot'; | ||
|
|
||
| import SoundCloudProvider from './mod.ts'; | ||
|
|
||
| describe('SoundCloud provider', () => { | ||
| const sc = new SoundCloudProvider(makeProviderOptions()); | ||
| const lookupStub = stubProviderLookups(sc); | ||
|
|
||
| describeProvider(sc, { | ||
| urls: [{ | ||
| description: 'album page', | ||
| url: new URL('https://soundcloud.com/ivycomb/sets/crimsongalaxies'), | ||
| id: { type: 'playlist', id: 'ivycomb/crimsongalaxies' }, | ||
| isCanonical: true, | ||
| }, { | ||
| description: 'standalone track page', | ||
| url: new URL('https://soundcloud.com/lonealphamusic/magazines'), | ||
| id: { type: 'track', id: 'lonealphamusic/magazines' }, | ||
| serializedId: 'lonealphamusic/track/magazines', | ||
| isCanonical: true, | ||
| }, { | ||
| description: 'artist page', | ||
| url: new URL('https://soundcloud.com/vocalokat'), | ||
| id: { type: 'artist', id: 'vocalokat' }, | ||
| isCanonical: true, | ||
| }], | ||
| releaseLookup: [{ | ||
| description: 'track release with downloads enabled', | ||
| release: 'leagueoflegends/track/piercing-light-mako-remix', | ||
| assert: async (release, ctx) => { | ||
| await assertSnapshot(ctx, release); | ||
| const isFree = release.externalLinks.some((link) => link.types?.includes('free download')); | ||
| assert(isFree, 'Release should be downloadable for free'); | ||
| }, | ||
| }], | ||
| }); | ||
|
|
||
| afterAll(() => { | ||
| lookupStub.restore(); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do the URLs ever have a www subdomain? The provider implementation doesn't accept it at least.