Add SQLite library with API, library desktop apps and MobyGames scraper

This commit is contained in:
SirBlob committed 2026-11-02 23:26:31 -05:00
1 parent 6674428346
commit a16444451a
69 files changed
+2988 -1026

No files matched your search

+5 -16
View File
@@ -1,25 +1,14 @@
import { error } from '@sveltejs/kit';
import { readFile } from 'node:fs/promises';
import path from 'node:path';
import { loadCovers, savedCoverPath } from '#lib/server/lastfm/covers';
import { readCoverImage } from '#lib/server/lastfm/covers';
import type { RequestHandler } from './$types';
const contentTypes: Record<string, string> = {
'.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.png': 'image/png',
'.webp': 'image/webp',
'.gif': 'image/gif'
};
export const GET: RequestHandler = async ({ params }) => {
await loadCovers();
const filePath = savedCoverPath(params.id);
if (!filePath) error(404, 'Cover not found');
const image = await readCoverImage(params.id);
if (!image) error(404, 'Cover not found');
return new Response(await readFile(filePath), {
return new Response(new Uint8Array(image.data), {
headers: {
'Content-Type': contentTypes[path.extname(filePath)] ?? 'image/jpeg',
'Content-Type': image.contentType,
'Cache-Control': 'public, max-age=31536000, immutable'
}
});
+7
View File
@@ -0,0 +1,7 @@
import { json } from '@sveltejs/kit';
import { getLibrary } from '#lib/server/library';
import type { RequestHandler } from './$types';
export const GET: RequestHandler = async () => {
return json(await getLibrary(), { headers: { 'Cache-Control': 'no-cache' } });
};
@@ -0,0 +1,24 @@
import { error, json } from '@sveltejs/kit';
import { requireApiKey } from '#lib/server/library/auth';
import { libraryDatabase } from '#lib/server/library/database';
import { readBody } from '#lib/server/library/input';
import { deleteBook, isGoodreadsId, saveBook } from '#lib/server/library/books';
import type { RequestHandler } from './$types';
function checkedId(goodreadsId: string): string {
if (!isGoodreadsId(goodreadsId)) error(400, `${goodreadsId} is not a Goodreads ID`);
return goodreadsId;
}
export const PUT: RequestHandler = async ({ params, request }) => {
requireApiKey(request);
const goodreadsId = checkedId(params.goodreadsId);
return json(await saveBook(await libraryDatabase(), goodreadsId, await readBody(request)));
};
export const DELETE: RequestHandler = async ({ params, request }) => {
requireApiKey(request);
const goodreadsId = checkedId(params.goodreadsId);
if (!deleteBook(await libraryDatabase(), goodreadsId)) error(404, `${goodreadsId} is not listed`);
return new Response(null, { status: 204 });
};
@@ -0,0 +1,16 @@
import { error } from '@sveltejs/kit';
import { libraryDatabase } from '#lib/server/library/database';
import { readImage } from '#lib/server/library/images';
import type { RequestHandler } from './$types';
export const GET: RequestHandler = async ({ params }) => {
const image = readImage(await libraryDatabase(), params.id);
if (!image) error(404, 'Image not found');
return new Response(new Uint8Array(image.data), {
headers: {
'Content-Type': image.contentType,
'Cache-Control': 'public, max-age=86400'
}
});
};
@@ -0,0 +1,24 @@
import { error, json } from '@sveltejs/kit';
import { requireApiKey } from '#lib/server/library/auth';
import { libraryDatabase } from '#lib/server/library/database';
import { readBody } from '#lib/server/library/input';
import { deleteMedia, isImdbId, saveMedia } from '#lib/server/library/media';
import type { RequestHandler } from './$types';
function checkedId(imdbId: string): string {
if (!isImdbId(imdbId)) error(400, `${imdbId} is not an IMDb ID`);
return imdbId;
}
export const PUT: RequestHandler = async ({ params, request }) => {
requireApiKey(request);
const imdbId = checkedId(params.imdbId);
return json(await saveMedia(await libraryDatabase(), imdbId, await readBody(request)));
};
export const DELETE: RequestHandler = async ({ params, request }) => {
requireApiKey(request);
const imdbId = checkedId(params.imdbId);
if (!deleteMedia(await libraryDatabase(), imdbId)) error(404, `${imdbId} is not listed`);
return new Response(null, { status: 204 });
};