Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 13 additions & 45 deletions app/src/lib/global/state.svelte.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -18,6 +19,7 @@ interface UserState {
}

export const userState: UserState = $state({
// TODO: Make this less dumb
id: '',
activeSong: null,
activeSongRelease: null,
Expand All @@ -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,
Expand All @@ -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;
Expand All @@ -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);
};
30 changes: 30 additions & 0 deletions app/src/lib/remote-functions/listening.remote.ts
Original file line number Diff line number Diff line change
@@ -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);
}
}
);
24 changes: 23 additions & 1 deletion app/src/lib/remote-functions/user.remote.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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) };
}
);
3 changes: 2 additions & 1 deletion app/src/routes/+layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down