Dropped ytdl, YT audio now fetched with Android Client. Began work on YT Premium support
This commit is contained in:
@@ -5,26 +5,20 @@ export const GET: RequestHandler = async ({ url, request }) => {
|
||||
const connectionId = url.searchParams.get('connection')
|
||||
const id = url.searchParams.get('id')
|
||||
if (!(connectionId && id)) return new Response('Missing query parameter', { status: 400 })
|
||||
// Might want to re-evaluate how specific I make these ^ v error response messages
|
||||
const connection = Connections.getConnection(connectionId)
|
||||
if (!connection) return new Response('Invalid connection id', { status: 400 })
|
||||
|
||||
const range = request.headers.get('range')
|
||||
const connection = Connections.getConnections([connectionId])[0]
|
||||
const audioRequestHeaders = new Headers({ range: request.headers.get('range') ?? 'bytes=0-' })
|
||||
|
||||
const fetchStream = async (): Promise<Response> => {
|
||||
const MAX_TRIES = 5
|
||||
let tries = 0
|
||||
while (tries < MAX_TRIES) {
|
||||
++tries
|
||||
const stream = await connection.getAudioStream(id, range).catch((reason) => {
|
||||
console.error(`Audio stream fetch failed: ${reason}`)
|
||||
return null
|
||||
})
|
||||
if (!stream || !stream.ok) continue
|
||||
const response = await connection
|
||||
.getAudioStream(id, audioRequestHeaders)
|
||||
// * Withing the .getAudioStream() method of connections, a TypeError should be thrown if the request was invalid (e.g. non-existent id)
|
||||
// * A standard Error should be thrown if the fetch to the service's server failed or the request returned invalid data
|
||||
.catch((error: TypeError | Error) => {
|
||||
if (error instanceof TypeError) return new Response('Malformed Request', { status: 400 })
|
||||
return new Response('Failed to fetch valid audio stream', { status: 502 })
|
||||
})
|
||||
|
||||
return stream
|
||||
}
|
||||
|
||||
throw new Error(`Audio stream fetch to connection: ${connection.id} of id ${id} failed`)
|
||||
}
|
||||
|
||||
return await fetchStream()
|
||||
return response
|
||||
}
|
||||
|
||||
@@ -2,16 +2,21 @@ import type { RequestHandler } from '@sveltejs/kit'
|
||||
import { Connections } from '$lib/server/connections'
|
||||
|
||||
export const GET: RequestHandler = async ({ url }) => {
|
||||
const ids = url.searchParams.get('ids')?.replace(/\s/g, '').split(',')
|
||||
if (!ids) return new Response('Missing ids query parameter', { status: 400 })
|
||||
const ids = url.searchParams.get('id')?.replace(/\s/g, '').split(',')
|
||||
if (!ids) return new Response('Missing id query parameter', { status: 400 })
|
||||
|
||||
const connections: ConnectionInfo[] = []
|
||||
for (const connection of Connections.getConnections(ids)) {
|
||||
await connection
|
||||
.getConnectionInfo()
|
||||
.then((info) => connections.push(info))
|
||||
.catch((reason) => console.log(`Failed to fetch connection info: ${reason}`))
|
||||
}
|
||||
const connections = (
|
||||
await Promise.all(
|
||||
ids.map((id) =>
|
||||
Connections.getConnection(id)
|
||||
?.getConnectionInfo()
|
||||
.catch((reason) => {
|
||||
console.error(`Failed to fetch connection info: ${reason}`)
|
||||
return undefined
|
||||
}),
|
||||
),
|
||||
)
|
||||
).filter((connection): connection is ConnectionInfo => connection?.id !== undefined)
|
||||
|
||||
return Response.json({ connections })
|
||||
}
|
||||
|
||||
16
src/routes/api/connections/[connectionId]/album/+server.ts
Normal file
16
src/routes/api/connections/[connectionId]/album/+server.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import type { RequestHandler } from '@sveltejs/kit'
|
||||
import { Connections } from '$lib/server/connections'
|
||||
|
||||
export const GET: RequestHandler = async ({ params, url }) => {
|
||||
const connectionId = params.connectionId!
|
||||
const connection = Connections.getConnection(connectionId)
|
||||
if (!connection) return new Response('Invalid connection id', { status: 400 })
|
||||
|
||||
const albumId = url.searchParams.get('id')
|
||||
if (!albumId) return new Response(`Missing id search parameter`, { status: 400 })
|
||||
|
||||
const album = await connection.getAlbum(albumId).catch(() => undefined)
|
||||
if (!album) return new Response(`Failed to fetch album with id: ${albumId}`, { status: 400 })
|
||||
|
||||
return Response.json({ album })
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import type { RequestHandler } from '@sveltejs/kit'
|
||||
import { Connections } from '$lib/server/connections'
|
||||
|
||||
export const GET: RequestHandler = async ({ params }) => {
|
||||
const { connectionId, albumId } = params
|
||||
const connection = Connections.getConnection(connectionId!)
|
||||
if (!connection) return new Response('Invalid connection id', { status: 400 })
|
||||
|
||||
const items = await connection.getAlbumItems(albumId!).catch(() => undefined)
|
||||
if (!items) return new Response(`Failed to fetch album with id: ${albumId!}`, { status: 400 })
|
||||
|
||||
return Response.json({ items })
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import type { RequestHandler } from '@sveltejs/kit'
|
||||
import { Connections } from '$lib/server/connections'
|
||||
|
||||
export const GET: RequestHandler = async ({ params, url }) => {
|
||||
const connectionId = params.connectionId!
|
||||
const connection = Connections.getConnection(connectionId)
|
||||
if (!connection) return new Response('Invalid connection id', { status: 400 })
|
||||
|
||||
const playlistId = url.searchParams.get('id')
|
||||
if (!playlistId) return new Response(`Missing id search parameter`, { status: 400 })
|
||||
|
||||
const playlist = await connection.getPlaylist(playlistId).catch(() => undefined)
|
||||
if (!playlist) return new Response(`Failed to fetch playlist with id: ${playlistId}`, { status: 400 })
|
||||
|
||||
return Response.json({ playlist })
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import type { RequestHandler } from '@sveltejs/kit'
|
||||
import { Connections } from '$lib/server/connections'
|
||||
|
||||
export const GET: RequestHandler = async ({ params }) => {
|
||||
const { connectionId, playlistId } = params
|
||||
const connection = Connections.getConnection(connectionId!)
|
||||
if (!connection) return new Response('Invalid connection id', { status: 400 })
|
||||
|
||||
const items = await connection.getPlaylistItems(playlistId!).catch((reason) => console.error(reason))
|
||||
if (!items) return new Response(`Failed to fetch playlist with id: ${playlistId!}`, { status: 400 })
|
||||
|
||||
return Response.json({ items })
|
||||
}
|
||||
@@ -11,19 +11,16 @@ export const GET: RequestHandler = async ({ url }) => {
|
||||
let tries = 0
|
||||
while (tries < MAX_TRIES) {
|
||||
++tries
|
||||
const response = await fetch(imageUrl).catch((reason) => {
|
||||
console.error(`Image fetch to ${imageUrl} failed: ${reason}`)
|
||||
return null
|
||||
})
|
||||
const response = await fetch(imageUrl).catch(() => null)
|
||||
if (!response || !response.ok) continue
|
||||
|
||||
const contentType = response.headers.get('content-type')
|
||||
if (!contentType || !contentType.startsWith('image')) throw new Error(`Url ${imageUrl} does not link to an image`)
|
||||
if (!contentType || !contentType.startsWith('image')) throw Error(`Url ${imageUrl} does not link to an image`)
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
throw new Error('Exceed Max Retires')
|
||||
throw Error(`Failed to fetch image at ${url} Exceed Max Retires`)
|
||||
}
|
||||
|
||||
return await fetchImage()
|
||||
|
||||
@@ -2,18 +2,27 @@ import type { RequestHandler } from '@sveltejs/kit'
|
||||
import { Connections } from '$lib/server/connections'
|
||||
|
||||
export const GET: RequestHandler = async ({ url }) => {
|
||||
const query = url.searchParams.get('query')
|
||||
if (!query) return new Response('Missing query parameter', { status: 400 })
|
||||
const userId = url.searchParams.get('userId')
|
||||
if (!userId) return new Response('Missing userId parameter', { status: 400 })
|
||||
const { query, userId, filter } = Object.fromEntries(url.searchParams) as { [k: string]: string | undefined }
|
||||
if (!(query && userId)) return new Response('Missing search parameter', { status: 400 })
|
||||
|
||||
const searchResults: (Song | Album | Artist | Playlist)[] = []
|
||||
for (const connection of Connections.getUserConnections(userId)) {
|
||||
await connection
|
||||
.search(query)
|
||||
.then((results) => searchResults.push(...results))
|
||||
.catch((reason) => console.error(`Failed to search "${query}" from connection ${connection.id}: ${reason}`))
|
||||
}
|
||||
const userConnections = Connections.getUserConnections(userId)
|
||||
if (!userConnections) return new Response('Invalid user id', { status: 400 })
|
||||
|
||||
let checkedFilter: 'song' | 'album' | 'artist' | 'playlist' | undefined
|
||||
if (filter === 'song' || filter === 'album' || filter === 'artist' || filter === 'playlist') checkedFilter = filter
|
||||
|
||||
const searchResults = (
|
||||
await Promise.all(
|
||||
userConnections.map((connection) =>
|
||||
connection.search(query, checkedFilter).catch((reason) => {
|
||||
console.error(`Failed to search "${query}" from connection ${connection.id}: ${reason}`)
|
||||
return undefined
|
||||
}),
|
||||
),
|
||||
)
|
||||
)
|
||||
.flat()
|
||||
.filter((result): result is Song | Album | Artist | Playlist => result?.id !== undefined)
|
||||
|
||||
return Response.json({ searchResults })
|
||||
}
|
||||
|
||||
@@ -4,13 +4,19 @@ import { Connections } from '$lib/server/connections'
|
||||
export const GET: RequestHandler = async ({ params }) => {
|
||||
const userId = params.userId!
|
||||
|
||||
const connections: ConnectionInfo[] = []
|
||||
for (const connection of Connections.getUserConnections(userId)) {
|
||||
await connection
|
||||
.getConnectionInfo()
|
||||
.then((info) => connections.push(info))
|
||||
.catch((reason) => console.log(`Failed to fetch connection info: ${reason}`))
|
||||
}
|
||||
const userConnections = Connections.getUserConnections(userId)
|
||||
if (!userConnections) return new Response('Invalid user id', { status: 400 })
|
||||
|
||||
const connections = (
|
||||
await Promise.all(
|
||||
userConnections.map((connection) =>
|
||||
connection.getConnectionInfo().catch((reason) => {
|
||||
console.log(`Failed to fetch connection info: ${reason}`)
|
||||
return undefined
|
||||
}),
|
||||
),
|
||||
)
|
||||
).filter((info): info is ConnectionInfo => info !== undefined)
|
||||
|
||||
return Response.json({ connections })
|
||||
}
|
||||
|
||||
@@ -6,13 +6,21 @@ import { Connections } from '$lib/server/connections'
|
||||
export const GET: RequestHandler = async ({ params }) => {
|
||||
const userId = params.userId!
|
||||
|
||||
const recommendations: (Song | Album | Artist | Playlist)[] = []
|
||||
for (const connection of Connections.getUserConnections(userId)) {
|
||||
await connection
|
||||
.getRecommendations()
|
||||
.then((connectionRecommendations) => recommendations.push(...connectionRecommendations))
|
||||
.catch((reason) => console.log(`Failed to fetch recommendations: ${reason}`))
|
||||
}
|
||||
const userConnections = Connections.getUserConnections(userId)
|
||||
if (!userConnections) return new Response('Invalid user id', { status: 400 })
|
||||
|
||||
const recommendations = (
|
||||
await Promise.all(
|
||||
userConnections.map((connection) =>
|
||||
connection.getRecommendations().catch((reason) => {
|
||||
console.log(`Failed to fetch recommendations: ${reason}`)
|
||||
return undefined
|
||||
}),
|
||||
),
|
||||
)
|
||||
)
|
||||
.flat()
|
||||
.filter((recommendation): recommendation is Song | Album | Artist | Playlist => recommendation?.id !== undefined)
|
||||
|
||||
return Response.json({ recommendations })
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user