Add Api for song upload

This commit is contained in:
Esa Kataja
2024-10-12 16:21:06 +03:00
parent 6bf57ff672
commit d47631abe9
6 changed files with 315 additions and 8 deletions
+87 -7
View File
@@ -1,27 +1,107 @@
<script>
import NewEntryDetailForm from './newEntry/NewEntryDetailForm.svelte';
let artist = '';
let songName = '';
let isEntered = false;
async function handleUploadSubmit(event) {
event.preventDefault();
const formData = new FormData(event.target);
const response = await fetch('/api/fileUpload', {
method: 'POST',
body: formData
});
const data = await response.json();
if (data.error) {
console.error(data.error);
} else {
console.log(data.metadata);
artist = data.metadata.common.artist || '';
songName = data.metadata.common.title || '';
isEntered = true;
}
}
async function handleYTLinkSubmit(event) {
event.preventDefault();
const formData = new FormData(event.target);
const ytLink = formData.get('ytlink');
if (!ytLink) {
console.error('No YouTube link provided');
return;
}
try {
const id = extractYouTubeId(ytLink);
if (!id) {
console.error('Invalid YouTube link');
return;
}
const response = await fetch('/api/ytUpload', {
method: 'POST',
body: JSON.stringify({ id })
});
if (!response.ok) {
console.error('Error uploading YouTube link:', response.status, response.statusText);
return;
}
const data = await response.json();
if (data.error) {
console.error('Error uploading YouTube link:', data.error);
} else {
artist = data.body.metadata.author_name || 'Artisti';
songName = data.body.metadata.title || 'Kappale';
isEntered = true;
}
} catch (error) {
console.error('Error handling YouTube link submission:', error);
}
}
function extractYouTubeId(link) {
const regex = /^(?:https?:\/\/)?(?:www\.)?youtu(?:be\.com|\.be)\/(?:watch\?v=)?([^&\s]+)/;
const match = link.match(regex);
return match && match[1];
}
</script>
<div class="my-20">
<h2 class="text-center text-2xl font-semibold">🎉🎉🎉 Uusi kierros on alkanut! 🎉🎉🎉</h2>
<h2 class="flex justify-center gap-4 items-center text-center text-2xl font-semibold">
<span class="hidden sm:inline">🎉🎉🎉</span><span>Uusi kierros on alkanut!</span><span
class="hidden sm:inline">🎉🎉🎉</span
>
</h2>
<p class="my-10">
Uusi kierros on alkanut. Et ole kuitenkaan vielä laittanut omaa ehdokasta sisään. Voit tehdä sen
alla olevan lomakkeen avulla.
</p>
<div id="upload-status" class={isEntered ? '' : 'hidden'}>
<NewEntryDetailForm {artist} {songName} />
</div>
<div
class="flex flex-col items-center border-2 border-zinc-500 rounded-xl p-10 text-center bg-zinc-700"
class={`flex flex-col md:flex-row md:justify-between items-center border-2 border-zinc-500 rounded-xl p-10 text-center bg-zinc-700 ${isEntered ? 'hidden' : ''}`}
>
<form action="/api/newentry" method="post">
<form on:submit|preventDefault={handleYTLinkSubmit} method="post" class="w-2/5">
<label for="ytlink" class="my-2">Youtube-linkki:</label>
<input
type="text"
name="ytlink"
class="input-text-field block w-full my-6"
placeholder="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
placeholder="https://www.youtube.com/watch?v=nxMMElT61A8"
/>
<p class="my-6 text-2xl font-bold">--- TAI ---</p>
<button type="submit" class="button-primary mt-4">Lataa</button>
</form>
<p class="my-6 text-2xl font-bold">--- TAI ---</p>
<form on:submit|preventDefault={handleUploadSubmit} method="post" class="w-2/5 text-center">
<label for="upload" class="mb-2">Tiedosto:</label>
<input type="file" name="upload" accept="audio/*" class="block w-full my-6" />
<button type="submit" class="button-primary mt-4">Liity mukaan</button>
<input type="file" name="upload" id="upload" accept="audio/*" class="block w-full my-6" />
<button type="submit" class="button-primary mt-4">Lataa</button>
</form>
</div>
</div>
@@ -0,0 +1,35 @@
<script>
export let artist = '';
export let songName = '';
export let isEntered;
function cancel() {
artist = '';
songName = '';
isEntered = false;
}
</script>
<div class="flex flex-col max-w-md mx-auto my-6 gap-4">
<label for="artist">Artisti:</label>
<input
type="text"
bind:value={artist}
name="artist"
id="artist"
class="input-text-field"
required
/>
<label for="songName">Kappale:</label>
<input
type="text"
bind:value={songName}
name="songName"
id="songName"
class="input-text-field"
required
/>
<button class="button-cancel mt-4" on:click={cancel}>Tyhjennä</button>
<button type="submit" class="button-primary">Läheta</button>
</div>
+39
View File
@@ -0,0 +1,39 @@
import { json } from '@sveltejs/kit';
import { parseBuffer } from 'music-metadata';
import { writeFile } from 'fs/promises';
import { join } from 'path';
import { unlink } from 'fs/promises';
export const config = {
api: {
bodyParser: false
}
};
export async function POST({ request }) {
try {
const formData = await request.formData();
const file = formData.get('upload');
if (!file) {
return json({ error: 'No file uploaded' }, { status: 400 });
}
// Save the file temporarily
const buffer = await file.arrayBuffer();
const tempPath = join('/tmp', `upload_${Date.now()}_${file.name}`);
await writeFile(tempPath, Buffer.from(buffer));
// Parse metadata
const metadata = await parseBuffer(Buffer.from(buffer));
// Clean up the temporary file
// You might want to handle this asynchronously or use a try-finally block
await unlink(tempPath);
return json({ metadata });
} catch (error) {
console.error('Error processing file:', error);
return json({ error: 'Failed to process file' }, { status: 500 });
}
}
+37
View File
@@ -0,0 +1,37 @@
export async function POST({ request }) {
console.log('ytUpload API endpoint hit');
const body = await request.json();
const ytId = body.id;
if (!ytId) {
return {
status: 400,
body: { error: 'No id provided' }
};
}
try {
console.log('Fetching YouTube metadata...');
const response = await fetch(
`https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=${ytId}&format=json`
);
const data = await response.json();
console.log('Response from YouTube:', data);
if (data.error) {
return Response.json({
status: 400,
body: { error: data.error.message }
});
}
return Response.json({
status: 200,
body: { metadata: data }
});
} catch (error) {
console.error('Error fetching YouTube metadata:', error);
return Response.json({
status: 500,
body: { error: 'Internal Server Error' }
});
}
}