@@ -52,7 +50,7 @@ const isNSFW = comic.md_comics.content_rating === 'erotica';
-
+
{comic.md_comics.title}
diff --git a/src/config/backgrounds.ts b/src/config/backgrounds.ts
index 4179bc8..329fce9 100644
--- a/src/config/backgrounds.ts
+++ b/src/config/backgrounds.ts
@@ -75,10 +75,3 @@ export function getRandomBackground(): BackgroundImage {
}
return backgrounds[Math.floor(Math.random() * backgrounds.length)];
}
-
-export function preloadBackgrounds() {
- backgrounds.forEach(bg => {
- const img = new Image();
- img.src = bg.url;
- });
-}
diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro
index 7ce0919..7c27522 100644
--- a/src/layouts/Layout.astro
+++ b/src/layouts/Layout.astro
@@ -147,12 +147,11 @@ const isCreditsPage = Astro.url.pathname === '/credits';
}
};
- // Add theme initialization to prevent flash of wrong theme
- const themeScript = `
- const theme = localStorage.getItem('theme') ??
- (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
- document.documentElement.setAttribute('data-theme', theme);
- `;
+ // Initialize theme
+ const savedTheme = localStorage.getItem('theme') as 'light' | 'dark' | null;
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
+ const initialTheme = savedTheme || (prefersDark ? 'dark' : 'light');
+ updateThemeToggle(initialTheme);
// Event listeners
settingsButton?.addEventListener('click', () => {
diff --git a/src/lib/api.ts b/src/lib/api.ts
index 3d482f1..d566cbe 100644
--- a/src/lib/api.ts
+++ b/src/lib/api.ts
@@ -69,43 +69,30 @@ export function getGenreNames(genreIds: number[], genres: Genre[]): string[] {
.filter(name => name !== '');
}
-export class APIError extends Error {
- constructor(
- message: string,
- public statusCode?: number,
- public endpoint?: string
- ) {
- super(message);
- this.name = 'APIError';
- }
-}
-
export async function fetchComics(
language: string = 'en',
contentType: string = 'sfw',
comicType: ComicType = 'all',
page: number = 1
): Promise
{
- const apiUrl = `${urlBase}?lang=${language}&page=${page}&order=new&accept_erotic_content=${contentType === 'nsfw'}${comicType === 'all' ? '' : `&type=${comicType}`}`;
-
try {
+ const typeParam = comicType === 'all' ? '' : `&type=${comicType}`;
+ const apiUrl = `${urlBase}?lang=${language}&page=${page}&order=new&accept_erotic_content=${contentType === 'nsfw'}${typeParam}`;
+
console.log('Fetching comics from:', apiUrl);
const response = await fetchWithRetry(apiUrl);
const data = await response.json();
if (!Array.isArray(data)) {
- throw new APIError('Invalid API response format', undefined, apiUrl);
+ console.error('Unexpected API response format:', data);
+ return [];
}
return data;
} catch (error) {
- if (error instanceof APIError) throw error;
- throw new APIError(
- 'Failed to fetch comics',
- error instanceof Response ? error.status : undefined,
- apiUrl
- );
+ console.error('Error fetching comics:', error);
+ return [];
}
}
diff --git a/src/lib/db.ts b/src/lib/db.ts
index ffcc509..84a8deb 100644
--- a/src/lib/db.ts
+++ b/src/lib/db.ts
@@ -3,8 +3,6 @@ import type { FeedMapping } from './types';
const REDIS_URL = import.meta.env.REDIS_URL || process.env.REDIS_URL;
let redis: Redis | null = null;
-let redisRetryCount = 0;
-const MAX_RETRIES = 3;
try {
console.log('Environment check:', {
@@ -25,14 +23,11 @@ try {
console.log(`Retry attempt ${times} with delay ${delay}ms`);
return delay;
},
- maxRetriesPerRequest: 2,
+ maxRetriesPerRequest: 3,
enableReadyCheck: true,
- reconnectOnError: (err) => {
- const targetError = 'READONLY';
- if (err.message.includes(targetError)) {
- return true;
- }
- return false;
+ reconnectOnError(err) {
+ console.log('Reconnect on error:', err.message);
+ return true;
}
});
@@ -60,38 +55,6 @@ try {
}
}
-async function getRedisClient(): Promise {
- if (redis?.status === 'ready') return redis;
-
- if (redisRetryCount >= MAX_RETRIES) {
- throw new Error('Failed to connect to Redis after multiple attempts');
- }
-
- try {
- redis = new Redis(REDIS_URL, {
- retryStrategy(times) {
- const delay = Math.min(times * 50, 2000);
- console.log(`Retry attempt ${times} with delay ${delay}ms`);
- return delay;
- },
- maxRetriesPerRequest: 2,
- enableReadyCheck: true,
- reconnectOnError: (err) => {
- const targetError = 'READONLY';
- if (err.message.includes(targetError)) {
- return true;
- }
- return false;
- }
- });
- redisRetryCount = 0;
- return redis;
- } catch (error) {
- redisRetryCount++;
- throw error;
- }
-}
-
export async function storeFeedMapping(feedId: string, slugs: string[], lang: string): Promise {
if (!redis) {
console.error('Redis client not initialized');
diff --git a/src/lib/types.ts b/src/lib/types.ts
index 2970743..69b3f03 100644
--- a/src/lib/types.ts
+++ b/src/lib/types.ts
@@ -6,9 +6,11 @@ export interface Comic {
title: string;
slug: string;
genres: number[];
- md_covers: ComicCover[];
- content_rating: 'safe' | 'suggestive' | 'erotica';
- comic_type: ComicType;
+ md_covers: {
+ b2key: string;
+ }[];
+ content_rating: string;
+ comic_type: string;
};
}
@@ -22,10 +24,4 @@ export interface FeedMapping {
lang: string;
}
-export type ComicType = 'manga' | 'manhwa' | 'manhua' | 'all';
-
-export interface ComicCover {
- b2key: string;
- width?: number;
- height?: number;
-}
\ No newline at end of file
+export type ComicType = 'manga' | 'manhwa' | 'manhua' | 'all';
\ No newline at end of file
diff --git a/src/pages/rss/[feedId].xml.ts b/src/pages/rss/[feedId].xml.ts
index 9429878..d589c17 100644
--- a/src/pages/rss/[feedId].xml.ts
+++ b/src/pages/rss/[feedId].xml.ts
@@ -1,9 +1,9 @@
-import { Feed } from 'feed';
+import rss from "@astrojs/rss";
import { getChaptersForSlugs, isValidLanguage } from "../../lib/api";
import { getFeedMapping } from "../../lib/db";
import type { APIRoute } from "astro";
-export const GET: APIRoute = async ({ params, request }) => {
+export const GET: APIRoute = async ({ params }) => {
const feedId = params.feedId?.replace('.xml', '');
if (!feedId) {
@@ -28,29 +28,14 @@ export const GET: APIRoute = async ({ params, request }) => {
return new Response("No chapters found for the provided comics", { status: 404 });
}
- const siteUrl = new URL(request.url).origin;
- const feedUrl = new URL(request.url).href;
-
- const feed = new Feed({
+ return rss({
title: `ComicK - Custom Feed (${lang.toUpperCase()})`,
description: `Custom RSS feed for selected comics: ${slugs.join(', ')}`,
- id: feedUrl,
- link: siteUrl,
- feedLinks: {
- rss2: feedUrl
- },
- language: lang,
- copyright: "All rights reserved",
- updated: new Date(),
- generator: 'ComicK RSS Generator',
- });
-
- chapters.forEach((chapter) => {
- const chapterUrl = `https://comick.io/comic/${chapter.md_comics.slug}`;
- feed.addItem({
+ site: "https://github.com/ld3z/manga-rss",
+ items: chapters.map((chapter) => ({
title: `${chapter.md_comics.title} - Chapter ${chapter.chap}`,
- id: `${chapter.md_comics.slug}-${chapter.chap}`,
- link: chapterUrl,
+ link: `https://comick.io/comic/${chapter.md_comics.slug}`,
+ pubDate: new Date(chapter.updated_at),
description: `
${
@@ -62,13 +47,6 @@ export const GET: APIRoute = async ({ params, request }) => {
New chapter available: Chapter ${chapter.chap}
`,
- date: new Date(chapter.updated_at),
- });
- });
-
- return new Response(feed.rss2(), {
- headers: {
- 'Content-Type': 'application/xml; charset=utf-8',
- },
+ })),
});
};
\ No newline at end of file
diff --git a/src/pages/rss/custom/[slugs].xml.ts b/src/pages/rss/custom/[slugs].xml.ts
index d29f95c..f5bb501 100644
--- a/src/pages/rss/custom/[slugs].xml.ts
+++ b/src/pages/rss/custom/[slugs].xml.ts
@@ -1,4 +1,4 @@
-import { Feed } from 'feed';
+import rss from "@astrojs/rss";
import { getChaptersForSlugs, isValidLanguage } from "../../../lib/api";
import type { APIRoute } from "astro";
@@ -22,37 +22,15 @@ export const GET: APIRoute = async ({ params, url }) => {
return new Response("No chapters found for the provided comics", { status: 404 });
}
- const siteUrl = new URL(url).origin;
- const feedUrl = new URL(url).href;
-
- const feed = new Feed({
+ return rss({
title: `ComicK - Custom Feed (${lang.toUpperCase()})`,
description: `Custom RSS feed for selected comics: ${slugs.join(', ')}`,
- id: feedUrl,
- link: siteUrl,
- feedLinks: {
- rss2: feedUrl
- },
- language: lang,
- copyright: "All rights reserved",
- updated: new Date(),
- generator: 'ComicK RSS Generator',
- });
-
- chapters.forEach((chapter) => {
- const chapterUrl = `https://comick.io/comic/${chapter.md_comics.slug}`;
- feed.addItem({
+ site: "https://github.com/ld3z/manga-rss",
+ items: chapters.map((chapter) => ({
title: `${chapter.md_comics.title} - Chapter ${chapter.chap}`,
- id: `${chapter.md_comics.slug}-${chapter.chap}`,
- link: chapterUrl,
+ link: `https://comick.io/comic/${chapter.md_comics.slug}`,
+ pubDate: new Date(chapter.updated_at),
description: `New chapter available: Chapter ${chapter.chap}`,
- date: new Date(chapter.updated_at),
- });
- });
-
- return new Response(feed.rss2(), {
- headers: {
- 'Content-Type': 'application/xml; charset=utf-8',
- },
+ })),
});
};
\ No newline at end of file