mirror of
https://codeberg.org/lucida/lucida.git
synced 2026-11-12 14:47:24 -05:00
Merge pull request 'Add Soundcloud Go+ support' (#1) from a/lucida:main into main
Reviewed-on: https://git.gay/h/lucida/pulls/1
This commit is contained in:
@@ -9,6 +9,7 @@ export const DEFAULT_HEADERS = {
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
'Sec-Fetch-Site': 'same-site',
|
||||
'Sec-GPC': '1',
|
||||
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/113.0'
|
||||
'User-Agent':
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36'
|
||||
}
|
||||
export const SC_VERSION = '1686222762'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import fetch from 'node-fetch'
|
||||
import fetch, { HeadersInit } from 'node-fetch'
|
||||
import { DEFAULT_HEADERS, SC_VERSION } from './constants.js'
|
||||
import { Streamer, SearchResults, GetByUrlResponse, GetStreamResponse } from '../../types.js'
|
||||
import {
|
||||
@@ -12,12 +12,16 @@ import {
|
||||
ScClient
|
||||
} from './parse.js'
|
||||
|
||||
function headers(token?: string): HeadersInit {
|
||||
function headers(oauthToken?: string | undefined): HeadersInit {
|
||||
const headers: HeadersInit = DEFAULT_HEADERS
|
||||
if (token) headers['Authentication'] = 'OAuth' + token
|
||||
if (oauthToken) headers['Authorization'] = 'OAuth ' + oauthToken
|
||||
return headers
|
||||
}
|
||||
|
||||
interface SoundcloudOptions {
|
||||
oauthToken?: string
|
||||
}
|
||||
|
||||
interface SoundcloudTranscoding {
|
||||
url: string
|
||||
preset: string
|
||||
@@ -33,10 +37,11 @@ interface SoundcloudTranscoding {
|
||||
export default class Soundcloud implements Streamer {
|
||||
hostnames = ['soundcloud.com', 'm.soundcloud.com', 'www.soundcloud.com']
|
||||
oauthToken?: string
|
||||
token?: string
|
||||
constructor(options: SoundcloudOptions) {
|
||||
this.oauthToken = options.oauthToken
|
||||
}
|
||||
async search(query: string, limit = 20): Promise<SearchResults> {
|
||||
const client = await this.#getClient()
|
||||
if (this.oauthToken) client.id = this.oauthToken
|
||||
|
||||
const response = await fetch(
|
||||
this.#formatURL(
|
||||
@@ -45,7 +50,7 @@ export default class Soundcloud implements Streamer {
|
||||
)}&app_locale=en&limit=${limit}`,
|
||||
client
|
||||
),
|
||||
{ method: 'get', headers: headers(this.token) }
|
||||
{ method: 'get', headers: headers(this.oauthToken) }
|
||||
)
|
||||
if (!response.ok) {
|
||||
const errMsg = await response.text()
|
||||
@@ -80,7 +85,7 @@ export default class Soundcloud implements Streamer {
|
||||
const response = await (
|
||||
await fetch(`https://soundcloud.com/`, {
|
||||
method: 'get',
|
||||
headers: headers(this.token)
|
||||
headers: headers()
|
||||
})
|
||||
).text()
|
||||
|
||||
@@ -123,10 +128,9 @@ export default class Soundcloud implements Streamer {
|
||||
|
||||
const type = this.getTypeFromUrl(url)
|
||||
const client = await this.#getClient()
|
||||
if (this.oauthToken) client.id = this.oauthToken
|
||||
|
||||
// getting the IDs and track authorization
|
||||
const html = await (await fetch(url, { method: 'get', headers: headers(this.token) })).text()
|
||||
const html = await (await fetch(url, { method: 'get', headers: headers() })).text()
|
||||
|
||||
switch (type) {
|
||||
case 'track': {
|
||||
@@ -135,13 +139,11 @@ export default class Soundcloud implements Streamer {
|
||||
?.split(`"id":`)?.[1]
|
||||
?.split(',')?.[0]
|
||||
|
||||
const trackAuthorization = html.split(`"track_authorization":"`)[1].split(`"`)[0]
|
||||
|
||||
const api = JSON.parse(
|
||||
await (
|
||||
await fetch(
|
||||
this.#formatURL(`https://api-v2.soundcloud.com/tracks?ids=${trackId}`, client),
|
||||
{ method: 'get', headers: headers(this.token) }
|
||||
{ method: 'get', headers: headers(this.oauthToken) }
|
||||
)
|
||||
).text()
|
||||
)[0]
|
||||
@@ -149,7 +151,12 @@ export default class Soundcloud implements Streamer {
|
||||
return {
|
||||
type: 'track',
|
||||
getStream: async () => {
|
||||
return await getStream(api.media.transcodings, trackAuthorization, client)
|
||||
return await getStream(
|
||||
api.media.transcodings,
|
||||
api.track_authorization,
|
||||
client,
|
||||
this.oauthToken
|
||||
)
|
||||
},
|
||||
metadata: await parseTrack(api)
|
||||
}
|
||||
@@ -206,7 +213,7 @@ export default class Soundcloud implements Streamer {
|
||||
await (
|
||||
await fetch(this.#formatURL(`https://api-v2.soundcloud.com/tracks?ids=${id}`, client), {
|
||||
method: 'get',
|
||||
headers: headers(this.token)
|
||||
headers: headers(this.oauthToken)
|
||||
})
|
||||
).text()
|
||||
)[0]
|
||||
@@ -239,14 +246,18 @@ async function fetchKey(response: string) {
|
||||
async function getStream(
|
||||
transcodings: Array<SoundcloudTranscoding>,
|
||||
trackAuth: string,
|
||||
client: ScClient
|
||||
client: ScClient,
|
||||
oauthToken?: string | undefined
|
||||
): Promise<GetStreamResponse> {
|
||||
const progressive = transcodings.filter((x) => x.format?.protocol == 'progressive')[0]
|
||||
const streamUrlResp = await fetch(
|
||||
`${progressive.url}?client_id=${client.id}&track_authorization=${trackAuth}`
|
||||
`${progressive.url}?client_id=${client.id}&track_authorization=${trackAuth}`,
|
||||
{
|
||||
headers: headers(oauthToken)
|
||||
}
|
||||
)
|
||||
const { url } = <{ url: string }>await streamUrlResp.json()
|
||||
const streamResp = await fetch(url)
|
||||
const json = <{ url: string }>await streamUrlResp.json()
|
||||
const streamResp = await fetch(json.url)
|
||||
return {
|
||||
mimeType: progressive.format.mime_type,
|
||||
sizeBytes: parseInt(<string>streamResp.headers.get('Content-Length')),
|
||||
|
||||
@@ -27,6 +27,11 @@ export interface RawArtist {
|
||||
kind: 'user'
|
||||
}
|
||||
|
||||
export interface Headers {
|
||||
Authorization?: string
|
||||
'User-Agent': string
|
||||
}
|
||||
|
||||
export function parseArtist(raw: RawArtist): Artist {
|
||||
const artist: Artist = {
|
||||
id: raw.id,
|
||||
|
||||
Reference in New Issue
Block a user