From 416803af81df983fa1eebe6fca9fd047f81a16fe Mon Sep 17 00:00:00 2001 From: Eclypsed Date: Wed, 14 Feb 2024 00:11:04 -0500 Subject: [PATCH] Added ConnectionInfo --- src/app.d.ts | 16 +++-- src/lib/server/users.db | Bin 24576 -> 24576 bytes .../users/[userId]/connectionInfo/+server.ts | 60 ++++++++++++++++++ .../settings/connections/+page.server.ts | 16 +---- 4 files changed, 72 insertions(+), 20 deletions(-) create mode 100644 src/routes/api/users/[userId]/connectionInfo/+server.ts diff --git a/src/app.d.ts b/src/app.d.ts index cad46de..a1e9f5e 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -45,6 +45,12 @@ declare global { tokens: Tokens } + interface ConnectionInfo { + connectionId: string + serviceType: serviceType + username: string + } + // These Schemas should only contain general info data that is necessary for data fetching purposes. // They are NOT meant to be stores for large amounts of data, i.e. Don't include the data for every single song the Playlist type. // Big data should be fetched as needed in the app, these exist to ensure that the info necessary to fetch that data is there. @@ -111,9 +117,9 @@ declare global { tokens: JFTokens } - interface AccountInfo { - username: string - servername?: string + interface JFConnectionInfo extends ConnectionInfo { + serviceType: 'jellyfin' + servername: string } interface AuthData { @@ -199,8 +205,8 @@ declare global { tokens: YTTokens } - interface AccountInfo { - username: string + interface YTConnectionInfo extends ConnectionInfo { + serviceType: 'youtube-music' profilePicture?: string } } diff --git a/src/lib/server/users.db b/src/lib/server/users.db index c1dfafcb281b70d892a3a3289ececeb6fcb236eb..b050acc4ed97279e817cee3dc5b7d971e431e859 100644 GIT binary patch delta 845 zcma))&2G~`0EClPEdo^v95_*_RTKdSjCO6W?JW|>DflOjoj8fx#1abYzt~CR{5VN% zP}NpK+>k(d1Wuf)mKW%q2Pg*~hP(kek47`2Z!T{07q|IuPx4#ecMtPh*B^wv5OD$H zB95al&2kh=6NVzb%TS160KXCh;PFP}hNBablxR|dpp>9McVc1Tp|lbqaw-IjZM`Hm zJeqI~7lidFt5khlQ-vt%1QMRME0Dg~|63@n6Ltf(A8y~}3Xga0t}lP@G(NxDxMx|H z!!KJb#0WS7qFmQwC>DB{!XD>S4(rjJk09eZtHS@Ev$U$Omp`j;8R~oIN~R5ZhRn~B zcnGQ)UN{YidD0=PIa|zSGZ<)WaFNkw24-W zTK%-4p;^`+CRnMPDQ?c8)tW<_6@w!x;QEK{1!pH|M0HdSCDW*(q{H@L&Y#5byq*D9 zmfVHLNEOp-y-mw9CWpO_CI+LX*wCAjsmN_wkJ75U=$juM!82_zop*U#kt$2W*gfx# za7O{P3<6_iRK^})v2Jy<)C&v>*zgkNY7MrG8i96a#M9A|72_e4;+i# znVfV(sy~jUiDXpYg_;usz&BZ9h=3%;7ezlEN7Jl$0C~Xk0uKSh(ahOpnBUe{oZe56 z03mWcjsn;r6pI{x^(a4}d_+4m<(SbvQ;@N{-F1Jy*$`!5(e||mM|4}fXZ(8|v4z%%X)4IRT FgntH}`pEzQ delta 1093 zcma)*O>g5=6owNzEfPhOffW)XF^akX)Z1R$*I$(e$!+u1iIdoln>d?reSNR(IEfv{ z`7$aUM!*`B1wVlONHhF_`4?>1@*CKa83~Em3N^ODL#Kw{N?lF@vo1s zipQ_MRlW!?!wQB710G=l5EVIqJy8ZokdOpTEz}o&-5Z?APJLFr^nz$rqtMBX5CwfB=)HdOSLtLQv)AzG(a}NS?ImX1)VwAI_r zrSWvGD1d+n5V(E_A$vDq8iRDS{Y`&zKN(#|wY2Gn_HfostW_nCav6vdQ_ibwjYy>j z7wuss?_SI6nMmS_3`ZUDvY$+Co~ME~j=N%xQ)NMJWxml=V_>3T*Ih+^J6g>oE^FPW zb|==%h0Y{swmbUzw!4%%N@z;yDykc->I54n7^79JHM;H8Ss3=Db;V%`(>A{Hoo5;` zEX~xds!^}?c|9CqY(=gZq&@}q_N`Lnjc?H(JNscALMwpyzy zXsV60=k#N9z2j%Gp{kyB6K=R}*f>%=BhS;@Wq)DiOUrKxmc$v}fR7ubPn`KRFs+-w zG8T@fmru)dorLM8e8I_3mL&*PQQ_g;i_Z>^blZOMbfySMq*UMm6w!`!ceh+DbHG&* zMZAYqCeyt@Vr}hzApKX9?eFccozwD;uq91f??F}#r{%lv%9s#3pLgSkPIrJ|(US<} z3C}SOAp#Y`alGouf*^?;_PFxhM}Ce*3KR$Vsm+~(U?4rUD5qVVs45_;q e47os2kpeKJ9`Tsx@sPgL?Gg9zt#F@$J@^*{fKS-~ diff --git a/src/routes/api/users/[userId]/connectionInfo/+server.ts b/src/routes/api/users/[userId]/connectionInfo/+server.ts new file mode 100644 index 0000000..0a55391 --- /dev/null +++ b/src/routes/api/users/[userId]/connectionInfo/+server.ts @@ -0,0 +1,60 @@ +import type { RequestHandler } from '@sveltejs/kit' +import { Connections } from '$lib/server/users' +import { google } from 'googleapis' + +const jellyfinInfo = async (connection: Jellyfin.JFConnection): Promise => { + const reqHeaders = new Headers({ Authorization: `MediaBrowser Token="${connection.tokens.accessToken}"` }) + + const userUrl = new URL(`Users/${connection.service.userId}`, connection.service.urlOrigin).href + const systemUrl = new URL('System/Info', connection.service.urlOrigin).href + + const userResponse = await fetch(userUrl, { headers: reqHeaders }) + const systemResponse = await fetch(systemUrl, { headers: reqHeaders }) + + const userData: Jellyfin.User = await userResponse.json() + const systemData: Jellyfin.System = await systemResponse.json() + + return { + connectionId: connection.id, + serviceType: 'jellyfin', + username: userData.Name, + servername: systemData.ServerName, + } +} + +const youtubeInfo = async (connection: YouTubeMusic.YTConnection): Promise => { + const youtube = google.youtube('v3') + const userChannelResponse = await youtube.channels.list({ mine: true, part: ['snippet'], access_token: connection.tokens.accessToken }) + const userChannel = userChannelResponse.data.items![0] + + return { + connectionId: connection.id, + serviceType: connection.service.type, + username: userChannel.snippet?.title as string, + profilePicture: userChannel.snippet?.thumbnails?.default?.url as string | undefined, + } +} + +export const GET: RequestHandler = async ({ params, url }) => { + const userId = params.userId as string + const requestedConnectionIds = url.searchParams.get('connectionIds')?.split(',') + + const connectionInfo: ConnectionInfo[] = [] + + const userConnections: Connection[] = requestedConnectionIds ? Array.from(requestedConnectionIds, (id) => Connections.getConnection(id)) : Connections.getUserConnections(userId) + + for (const connection of userConnections) { + let info: ConnectionInfo + switch (connection.service.type) { + case 'jellyfin': + info = await jellyfinInfo(connection as Jellyfin.JFConnection) + break + case 'youtube-music': + info = await youtubeInfo(connection as YouTubeMusic.YTConnection) + break + } + connectionInfo.push(info) + } + + return Response.json({ connectionInfo }) +} diff --git a/src/routes/settings/connections/+page.server.ts b/src/routes/settings/connections/+page.server.ts index 2ba1d9f..bac692a 100644 --- a/src/routes/settings/connections/+page.server.ts +++ b/src/routes/settings/connections/+page.server.ts @@ -10,6 +10,7 @@ export const load: PageServerLoad = async ({ fetch, locals }) => { headers: { apikey: SECRET_INTERNAL_API_KEY }, }) + console.log(locals.user.id) const userConnections: Connection[] = await connectionsResponse.json() return { userConnections } } @@ -37,23 +38,10 @@ export const actions: Actions = { const authData: Jellyfin.AuthData = await jellyfinAuthResponse.json() - const userUrl = new URL(`Users/${authData.User.Id}`, serverUrl.toString()).href - const systemUrl = new URL('System/Info', serverUrl.toString()).href - - const reqHeaders = new Headers({ Authorization: `MediaBrowser Token="${authData.AccessToken}"` }) - - const userResponse = await fetch(userUrl, { headers: reqHeaders }) - const systemResponse = await fetch(systemUrl, { headers: reqHeaders }) - - const userData: Jellyfin.User = await userResponse.json() - const systemData: Jellyfin.System = await systemResponse.json() - const serviceData: Jellyfin.JFService = { type: 'jellyfin', userId: authData.User.Id, - // username: userData.Name, urlOrigin: serverUrl.toString(), - // serverName: systemData.ServerName, } const tokenData: Jellyfin.JFTokens = { accessToken: authData.AccessToken, @@ -89,9 +77,7 @@ export const actions: Actions = { const serviceData: YouTubeMusic.YTService = { type: 'youtube-music', userId: userChannel.id as string, - // username: userChannel.snippet?.title as string, urlOrigin: 'https://www.googleapis.com/youtube/v3', - // profilePicture: userChannel.snippet?.thumbnails?.default?.url as string | undefined, } const newConnectionResponse = await fetch(`/api/users/${locals.user.id}/connections`, {