diff --git a/app/src/lib/global/state.svelte.ts b/app/src/lib/global/state.svelte.ts index 28ed3d9..f0ac1e2 100644 --- a/app/src/lib/global/state.svelte.ts +++ b/app/src/lib/global/state.svelte.ts @@ -1,6 +1,7 @@ +import { getTrackUrl, logStream } from '$lib/remote-functions/listening.remote'; +import { updateUserTokensBalance } from '$lib/remote-functions/user.remote'; import type { Mixtape, Release, Track } from '../../../../shared/types/core'; import type { TrackHydrated } from '../../../../shared/types/hydrated'; -import { API_BASE } from './config'; interface UserState { id: string; @@ -18,6 +19,7 @@ interface UserState { } export const userState: UserState = $state({ + // TODO: Make this less dumb id: '', activeSong: null, activeSongRelease: null, @@ -32,46 +34,6 @@ export const userState: UserState = $state({ } }); -const logStream = async (userId: string, artistId: string, trackId: string, tokensUsed: number) => { - console.log(`Logging stream for '${trackId}' by user ${userId}`); - const { status } = await fetch(`${API_BASE}/streams`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ userId, artistId, trackId, tokensUsed }) - }); - if (status === 200) { - console.log('Stream logged successfully'); - } else { - console.error('Error logging stream:', status); - } -}; - -export const updateUserTokensBalance = async ( - userId: string, - tokens: number, - addOrSubtract: 'add' | 'subtract' -) => { - const balanceChange = addOrSubtract === 'add' ? tokens : -tokens; - const response = await fetch(`${API_BASE}/users/${userId}`, { - method: 'PATCH', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ balanceChange }) - }); - - if (!response.ok) { - console.error('Error updating user balance:', response.statusText); - } - const data = await response.json(); - if (userState.liveBalance !== null) { - userState.liveBalance += balanceChange; - } - return { data, error: response.ok ? null : new Error(response.statusText) }; -}; - export const setActiveSong = async ( song: Track, release: Release, @@ -83,7 +45,7 @@ export const setActiveSong = async ( throw new Error('Not enough balance to play this song'); } - const songUrl = await fetch(`${API_BASE}/links/${song.ipfs_cid}`).then((res) => res.text()); + const songUrl = await getTrackUrl(song.ipfs_cid); userState.activeSong = song; userState.activeSongRelease = release; @@ -92,7 +54,13 @@ export const setActiveSong = async ( // TODO: Improve this to use a more accurate timer // Deduct the pay per stream after 30 of playtime setTimeout(() => { - updateUserTokensBalance(userId, userPayPerStream, 'subtract'); - logStream(userId, release.artist_id, song.id, userPayPerStream); - }, 30000); + updateUserTokensBalance({ userId, tokens: userPayPerStream, addOrSubtract: 'subtract' }); + userState.liveBalance -= userPayPerStream; + logStream({ + userId, + artistId: release.artist_id, + trackId: song.id, + tokensUsed: userPayPerStream + }); + }, 10000); }; diff --git a/app/src/lib/remote-functions/listening.remote.ts b/app/src/lib/remote-functions/listening.remote.ts new file mode 100644 index 0000000..4c6711e --- /dev/null +++ b/app/src/lib/remote-functions/listening.remote.ts @@ -0,0 +1,30 @@ +import { query } from '$app/server'; +import { API_BASE, REQUEST_HEADER_BOILERPLATE } from '$lib/global/config'; +import * as z from 'zod'; + +export const getTrackUrl = query(z.string(), async (trackId: string) => { + return await fetch(`${API_BASE}/links/${trackId}`, { + headers: REQUEST_HEADER_BOILERPLATE + }).then((res) => res.text()); +}); + +export const logStream = query( + z.object({ + userId: z.string(), + artistId: z.string(), + trackId: z.string(), + tokensUsed: z.number() + }), + async ({ userId, artistId, trackId, tokensUsed }) => { + const { status } = await fetch(`${API_BASE}/streams`, { + method: 'POST', + headers: REQUEST_HEADER_BOILERPLATE, + body: JSON.stringify({ userId, artistId, trackId, tokensUsed }) + }); + if (status === 200) { + console.log('Stream logged successfully'); + } else { + console.error('Error logging stream:', status); + } + } +); diff --git a/app/src/lib/remote-functions/user.remote.ts b/app/src/lib/remote-functions/user.remote.ts index d93e20c..52b67e1 100644 --- a/app/src/lib/remote-functions/user.remote.ts +++ b/app/src/lib/remote-functions/user.remote.ts @@ -1,4 +1,4 @@ -import { form } from '$app/server'; +import { form, query } from '$app/server'; import { API_BASE, REQUEST_HEADER_BOILERPLATE } from '$lib/global/config'; import * as z from 'zod'; import { requireAuth } from './auth-check'; @@ -35,3 +35,25 @@ export const toggleLikedTrack = form(ToggleLikedTrackForm, async ({ trackId, add body: JSON.stringify({ trackId }) }); }); + +export const updateUserTokensBalance = query( + z.object({ + userId: z.string(), + tokens: z.number(), + addOrSubtract: z.enum(['add', 'subtract']) + }), + async ({ userId, tokens, addOrSubtract }) => { + const balanceChange = addOrSubtract === 'add' ? tokens : -tokens; + const response = await fetch(`${API_BASE}/users/${userId}`, { + method: 'PATCH', + headers: REQUEST_HEADER_BOILERPLATE, + body: JSON.stringify({ balanceChange }) + }); + + if (!response.ok) { + console.error('Error updating user balance:', response.statusText); + } + const data = await response.json(); + return { data, error: response.ok ? null : new Error(response.statusText) }; + } +); diff --git a/app/src/routes/+layout.ts b/app/src/routes/+layout.ts index 9b3ed28..041d4f9 100644 --- a/app/src/routes/+layout.ts +++ b/app/src/routes/+layout.ts @@ -36,7 +36,8 @@ export const load: LayoutLoad = async ({ fetch, data, depends }) => { data: { user } } = await supabase.auth.getUser(); - if (data.profileData) { + if (data.profileData && session) { + userState.id = session.user.id; userState.liveBalance = data.profileData.tokens_balance; userState.payPerStream = data.profileData.pay_per_stream; userState.music.likedTracks = data.likedTracks;