introduce sqlite db

This commit is contained in:
ld3zian 2025-01-25 20:30:56 -07:00
parent d71a1da5aa
commit 806f6dc07b
7 changed files with 428 additions and 7 deletions

49
src/lib/db.ts Normal file
View file

@ -0,0 +1,49 @@
import Database from 'better-sqlite3';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import type { FeedMapping } from './types';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const dbPath = join(__dirname, '../../feed-mappings.db');
const db = new Database(dbPath);
// Initialize the database with the required table
db.exec(`
CREATE TABLE IF NOT EXISTS feed_mappings (
feed_id TEXT PRIMARY KEY,
slugs TEXT NOT NULL,
lang TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
export function storeFeedMapping(feedId: string, slugs: string[], lang: string): void {
const stmt = db.prepare('INSERT OR REPLACE INTO feed_mappings (feed_id, slugs, lang) VALUES (?, ?, ?)');
stmt.run(feedId, JSON.stringify(slugs), lang);
}
export function getFeedMapping(feedId: string): FeedMapping | null {
const stmt = db.prepare('SELECT slugs, lang FROM feed_mappings WHERE feed_id = ?');
const result = stmt.get(feedId);
if (!result) return null;
return {
slugs: JSON.parse(result.slugs),
lang: result.lang
};
}
// Optional: Clean up old mappings (older than 30 days)
export function cleanupOldMappings(): void {
const stmt = db.prepare(`
DELETE FROM feed_mappings
WHERE created_at < datetime('now', '-30 days')
`);
stmt.run();
}
// Run cleanup periodically (every 24 hours)
setInterval(cleanupOldMappings, 24 * 60 * 60 * 1000);

View file

@ -15,4 +15,9 @@ export interface Comic {
export interface Genre {
id: number;
name: string;
}
export interface FeedMapping {
slugs: string[];
lang: string;
}

View file

@ -1,5 +1,6 @@
import type { APIRoute } from "astro";
import { createHash } from 'crypto';
import { storeFeedMapping } from '../../lib/db';
// In-memory storage (replace with database in production)
const feedMappings = new Map<string, { slugs: string[], lang: string }>();
@ -16,8 +17,8 @@ export const POST: APIRoute = async ({ request }) => {
const dataString = `${slugs.sort().join(',')}:${lang}`;
const hash = createHash('md5').update(dataString).digest('hex').slice(0, 8);
// Store the mapping
feedMappings.set(hash, { slugs, lang });
// Store the mapping in the database
storeFeedMapping(hash, slugs, lang);
return new Response(JSON.stringify({ feedId: hash }), {
status: 200,

View file

@ -1,16 +1,22 @@
import rss from "@astrojs/rss";
import { getChaptersForSlugs, isValidLanguage } from "../../lib/api";
import { getFeedMapping } from "../../lib/db";
import type { APIRoute } from "astro";
import { feedMappings } from "../api/create-feed";
export const GET: APIRoute = async ({ params }) => {
const feedId = params.feedId?.replace('.xml', '');
if (!feedId || !feedMappings.has(feedId)) {
if (!feedId) {
return new Response("Feed ID not provided", { status: 400 });
}
const mapping = getFeedMapping(feedId);
if (!mapping) {
return new Response("Feed not found", { status: 404 });
}
const { slugs, lang } = feedMappings.get(feedId)!;
const { slugs, lang } = mapping;
if (!isValidLanguage(lang)) {
return new Response("Invalid language", { status: 400 });