diff --git a/package-lock.json b/package-lock.json index 853b281..340d133 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@astrojs/tailwind": "^6.0.0", "@astrojs/vercel": "^8.1.0", "@floating-ui/dom": "^1.6.13", - "@types/node": "^22.13.9", + "@types/node": "^22.13.7", "@vercel/analytics": "^1.5.0", "@vercel/kv": "^3.0.0", "astro": "^5.4.1", @@ -1465,9 +1465,9 @@ } }, "node_modules/@types/node": { - "version": "22.13.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.9.tgz", - "integrity": "sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw==", + "version": "22.13.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.7.tgz", + "integrity": "sha512-oU2q+BsQldB9lYxHNp/5aZO+/Bs0Usa74Abo9mAKulz4ahQyXRHK6UVKYIN8KSC8HXwhWSi7b49JnX+txuac0w==", "dependencies": { "undici-types": "~6.20.0" } diff --git a/package.json b/package.json index de31832..04cbc25 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "@astrojs/tailwind": "^6.0.0", "@astrojs/vercel": "^8.1.0", "@floating-ui/dom": "^1.6.13", - "@types/node": "^22.13.9", + "@types/node": "^22.13.7", "@vercel/analytics": "^1.5.0", "@vercel/kv": "^3.0.0", "astro": "^5.4.1", diff --git a/public/genshin.webp b/public/genshin.webp deleted file mode 100644 index b93365a..0000000 Binary files a/public/genshin.webp and /dev/null differ diff --git a/public/meata.webp b/public/meata.webp deleted file mode 100644 index 08a2e74..0000000 Binary files a/public/meata.webp and /dev/null differ diff --git a/public/sleepy.webp b/public/sleepy.webp deleted file mode 100644 index 494c25a..0000000 Binary files a/public/sleepy.webp and /dev/null differ diff --git a/src/components/SlugInput.astro b/src/components/SlugInput.astro index c20b255..3a5b5d3 100644 --- a/src/components/SlugInput.astro +++ b/src/components/SlugInput.astro @@ -476,51 +476,17 @@ const languages = [ `; const response = await fetch(`/api/feed/${feedId}`); - if (!response.ok) { - const errorText = await response.text(); - console.error(`Feed import failed with status ${response.status}: ${errorText}`); - throw new Error(`Failed to fetch feed: ${response.status} ${response.statusText}`); - } + if (!response.ok) throw new Error('Failed to fetch feed'); - const data = await response.json(); - console.log('Feed import data:', data); // Diagnostic log - - // Validate response structure - if (!data || typeof data !== 'object') { - throw new Error('Invalid feed data format: not an object'); - } + const { slugs: feedSlugs, lang } = await response.json(); - const feedSlugs = data.slugs; - const lang = data.lang; - - // Validate slugs array - if (!feedSlugs || !Array.isArray(feedSlugs)) { - throw new Error('Invalid feed data: missing or invalid slugs array'); - } - - // Validate language - if (!lang || typeof lang !== 'string') { - console.warn('Feed has missing or invalid language, using default'); - } else if (langSelect) { - // Only update language if it's valid - const validLanguages = Array.from(langSelect.options).map(opt => opt.value); - if (validLanguages.includes(lang)) { - langSelect.value = lang; - } else { - console.warn(`Feed has unsupported language: ${lang}`); - } + // Update language if provided + if (lang && langSelect) { + langSelect.value = lang; } // Add new slugs to existing collection - let importCount = 0; - feedSlugs.forEach((slug: string) => { - if (typeof slug === 'string' && slug.trim()) { - slugs.add(slug.trim()); - importCount++; - } else { - console.warn('Skipping invalid slug in feed:', slug); - } - }); + feedSlugs.forEach((slug: string) => slugs.add(slug)); // Update UI updateSlugs(); @@ -529,7 +495,7 @@ const languages = [ // Show success message const successDiv = document.createElement('div'); successDiv.className = 'text-sm text-green-500 mt-1'; - successDiv.textContent = `Feed imported successfully! Added ${importCount} comics.`; + successDiv.textContent = 'Feed imported successfully!'; feedIdInput.parentNode?.appendChild(successDiv); setTimeout(() => successDiv.remove(), 3000); @@ -537,11 +503,9 @@ const languages = [ console.error('Failed to import feed:', error); const errorDiv = document.createElement('div'); errorDiv.className = 'text-sm text-red-500 mt-1'; - errorDiv.textContent = error instanceof Error - ? `Import failed: ${error.message}` - : 'Failed to import feed. Please check the feed ID and try again.'; + errorDiv.textContent = 'Failed to import feed. Please check the feed ID and try again.'; feedIdInput.parentNode?.appendChild(errorDiv); - setTimeout(() => errorDiv.remove(), 5000); + setTimeout(() => errorDiv.remove(), 3000); } finally { importFeedButton.disabled = false; importFeedButton.innerHTML = ` diff --git a/src/config/backgrounds.ts b/src/config/backgrounds.ts index e85074f..38d2851 100644 --- a/src/config/backgrounds.ts +++ b/src/config/backgrounds.ts @@ -74,43 +74,6 @@ export const backgrounds: BackgroundImage[] = [ }, ], }, - { - url: "/sleepy.webp", - title: "???", - artist: "soaphisoap", - source: "https://safebooru.org/index.php?page=post&s=view&id=5418793", - socials: [ - { - name: "Twitter", - link: "https://x.com/soaphisoap", - }, - ], - }, - { - url: "/genshin.webp", - title: "???", - artist: "charlieinoni", - source: "https://safebooru.org/index.php?page=post&s=view&id=5531630", - socials: [ - { - name: "Twitter", - link: "https://x.com/charlieinoni", - }, - ], - }, - { - url: "/meata.webp", - title: "???", - artist: "???", - source: - "https://i.pximg.net/img-original/img/2025/03/03/15/13/24/127822472_p0.png", - socials: [ - { - name: "Twitter", - link: "https://x.com/", - }, - ], - }, // Add more backgrounds here! // { // url: 'your-image-url', @@ -142,4 +105,4 @@ export function preloadBackgrounds() { const img = new Image(); img.src = bg.url; }); -} +} \ No newline at end of file diff --git a/src/lib/db.ts b/src/lib/db.ts index 3b4b04b..bb34a83 100644 --- a/src/lib/db.ts +++ b/src/lib/db.ts @@ -284,82 +284,19 @@ export async function checkCacheStatus(slugs: string[], lang: string): Promise { - let foundMapping: string | null = null; - let sourceRedisName: string = ""; + const redis = await getRedisClient(); - // First try primary try { - // Check primary database if available - if (primaryClient?.status === 'ready') { - try { - await primaryClient.ping(); - const mapping = await primaryClient.get(feedId); - if (mapping) { - await primaryClient.expire(feedId, DEFAULT_CACHE_TTL); - foundMapping = mapping; - sourceRedisName = "Primary"; - } - } catch (error) { - console.warn('Primary Redis connection failed while retrieving mapping:', error); - // Fall through to try replicas - } - } - - // If not found in primary, check replicas - if (!foundMapping) { - for (const [url, client] of replicaClients.entries()) { - if (client.status === 'ready') { - try { - await client.ping(); - console.log(`Trying to get key from ${getRedisName(url)}`); - const mapping = await client.get(feedId); - if (mapping) { - await client.expire(feedId, DEFAULT_CACHE_TTL); - foundMapping = mapping; - sourceRedisName = getRedisName(url); - break; // Exit the loop once we find the mapping - } - } catch (error) { - console.warn(`${getRedisName(url)} connection failed while retrieving mapping:`, error); - // Continue to next replica - } - } - } - } - - // If we found the mapping in any database, re-synchronize to all other databases - if (foundMapping) { - console.log(`Found mapping in ${sourceRedisName}. Re-synchronizing to all Redis instances...`); - - // Parse data for returning - const data = JSON.parse(foundMapping); - const result = { - slugs: data.slugs, - lang: data.lang - }; - - // Fire-and-forget re-sync to all databases - (async () => { - try { - await writeToAllRedis(async (redis) => { - await redis.set( - feedId, - foundMapping!, - 'EX', - DEFAULT_CACHE_TTL - ); - }); - console.log(`Successfully re-synchronized mapping for ${feedId} to all Redis instances`); - } catch (syncError) { - console.error('Error during Redis re-synchronization:', syncError); - } - })(); - - return result; - } - - // If we get here, the key wasn't found in any database - return null; + const mapping = await redis.get(feedId); + if (!mapping) return null; + + await redis.expire(feedId, DEFAULT_CACHE_TTL); + + const data = JSON.parse(mapping); + return { + slugs: data.slugs, + lang: data.lang + }; } catch (error) { console.error('Error retrieving feed mapping:', error); throw new Error('Failed to retrieve feed mapping'); diff --git a/src/pages/api/feed/[feedId].ts b/src/pages/api/feed/[feedId].ts index bf7a29d..2fe7c8f 100644 --- a/src/pages/api/feed/[feedId].ts +++ b/src/pages/api/feed/[feedId].ts @@ -9,43 +9,20 @@ export const GET: APIRoute = async ({ params }) => { } try { - console.log(`Fetching feed mapping for ID: ${feedId}`); const mapping = await getFeedMapping(feedId); if (!mapping) { - console.error(`Feed not found for ID: ${feedId}`); - return new Response(`Feed with ID "${feedId}" not found`, { status: 404 }); + return new Response("Feed not found", { status: 404 }); } - // Validate mapping structure before returning - if (!Array.isArray(mapping.slugs)) { - console.error(`Invalid slugs in feed mapping for ID: ${feedId}`, mapping); - return new Response(`Feed data corruption: invalid slugs format`, { - status: 500 - }); - } - - // Ensure consistent response format - const response = { - slugs: mapping.slugs.filter(slug => typeof slug === 'string' && slug.trim()), - lang: typeof mapping.lang === 'string' ? mapping.lang : 'en' - }; - - console.log(`Successfully retrieved feed mapping for ID: ${feedId}`, response); - - return new Response(JSON.stringify(response), { + return new Response(JSON.stringify(mapping), { status: 200, headers: { 'Content-Type': 'application/json' } }); } catch (error) { - console.error(`Error fetching feed ${feedId}:`, error); - - const errorMessage = error instanceof Error - ? `Internal server error: ${error.message}` - : "Internal server error"; - - return new Response(errorMessage, { status: 500 }); + console.error('Error fetching feed:', error); + return new Response("Internal server error", { status: 500 }); } }; \ No newline at end of file