diff --git a/src/components/LanguageSelector.astro b/src/components/LanguageSelector.astro
index 7b376c0..7f4ba68 100644
--- a/src/components/LanguageSelector.astro
+++ b/src/components/LanguageSelector.astro
@@ -1,50 +1,34 @@
---
-import { availableLanguages, availableContentTypes, getLanguageName } from '../lib/api';
+import { availableLanguages, languageMap } from '../lib/api';
interface Props {
currentLang: string;
currentType: string;
+ contentType: string;
}
-const { currentLang, currentType } = Astro.props;
+const { currentLang, currentType, contentType } = Astro.props;
---
-
-
-
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/src/components/RSSLink.astro b/src/components/RSSLink.astro
index 1adabe2..4a32ab2 100644
--- a/src/components/RSSLink.astro
+++ b/src/components/RSSLink.astro
@@ -1,31 +1,31 @@
---
interface Props {
lang: string;
+ contentType: string;
type: string;
}
-const { lang, type } = Astro.props;
+const { lang, contentType, type } = Astro.props;
---
-
-
RSS Feed
\ No newline at end of file
diff --git a/src/components/TypeFilter.astro b/src/components/TypeFilter.astro
index 0519ecb..8ea63d3 100644
--- a/src/components/TypeFilter.astro
+++ b/src/components/TypeFilter.astro
@@ -1 +1,31 @@
-
\ No newline at end of file
+---
+interface Props {
+ currentType: string;
+ lang: string;
+ contentType: string;
+}
+
+const { currentType, lang, contentType } = Astro.props;
+
+const types = [
+ { id: 'all', label: 'All' },
+ { id: 'manga', label: 'Manga' },
+ { id: 'manhwa', label: 'Manhwa' },
+ { id: 'manhua', label: 'Manhua' },
+];
+---
+
+
\ No newline at end of file
diff --git a/src/lib/api.ts b/src/lib/api.ts
index 2c66bfe..131f8ec 100644
--- a/src/lib/api.ts
+++ b/src/lib/api.ts
@@ -1,4 +1,4 @@
-import type { Comic, Genre } from './types';
+import type { Comic, Genre, ComicType } from './types';
const languageMap = {
"en": "English",
@@ -16,6 +16,7 @@ const languageMap = {
const languages = new Set(Object.keys(languageMap));
const contentTypes = new Set(["sfw", "nsfw"]);
+const comicTypes = new Set(['manga', 'manhwa', 'manhua', 'all']);
const urlBase = "https://api.comick.fun/chapter";
let genreCache: Genre[] = [];
@@ -67,9 +68,18 @@ export function getGenreNames(genreIds: number[], genres: Genre[]): string[] {
.filter(name => name !== '');
}
-export async function fetchComics(language: string = 'en', contentType: string = 'sfw', page: number = 1): Promise {
+export async function fetchComics(
+ language: string = 'en',
+ contentType: string = 'sfw',
+ comicType: ComicType = 'all',
+ page: number = 1
+): Promise {
try {
- const apiUrl = `${urlBase}?lang=${language}&page=${page}&order=new&accept_erotic_content=${contentType === 'nsfw'}`;
+ 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();
@@ -93,12 +103,17 @@ export function isValidContentType(type: string): boolean {
return contentTypes.has(type);
}
+export function isValidComicType(type: string): boolean {
+ return comicTypes.has(type);
+}
+
export function getLanguageName(code: string): string {
return languageMap[code as keyof typeof languageMap] || code.toUpperCase();
}
export const availableLanguages = Array.from(languages);
export const availableContentTypes = Array.from(contentTypes);
+export const availableComicTypes = Array.from(comicTypes);
export { languageMap };
interface ComicDetail {
diff --git a/src/lib/types.ts b/src/lib/types.ts
index 2efb35d..69b3f03 100644
--- a/src/lib/types.ts
+++ b/src/lib/types.ts
@@ -10,6 +10,7 @@ export interface Comic {
b2key: string;
}[];
content_rating: string;
+ comic_type: string;
};
}
@@ -21,4 +22,6 @@ export interface Genre {
export interface FeedMapping {
slugs: string[];
lang: string;
-}
\ No newline at end of file
+}
+
+export type ComicType = 'manga' | 'manhwa' | 'manhua' | 'all';
\ No newline at end of file
diff --git a/src/pages/[lang]/[contentType]/[type].astro b/src/pages/[lang]/[contentType]/[type].astro
index 0519ecb..0eca550 100644
--- a/src/pages/[lang]/[contentType]/[type].astro
+++ b/src/pages/[lang]/[contentType]/[type].astro
@@ -1 +1,117 @@
-
\ No newline at end of file
+---
+import Layout from '../../../layouts/Layout.astro';
+import ComicCard from '../../../components/ComicCard.astro';
+import LoadingCard from '../../../components/LoadingCard.astro';
+import RSSLink from '../../../components/RSSLink.astro';
+import TypeFilter from '../../../components/TypeFilter.astro';
+import LanguageSelector from '../../../components/LanguageSelector.astro';
+import { fetchComics, fetchGenres, isValidLanguage, isValidContentType, isValidComicType, getLanguageName } from '../../../lib/api';
+import type { Comic, Genre } from '../../../lib/types';
+
+export const prerender = false;
+
+const { lang, contentType, type } = Astro.params;
+
+if (!isValidLanguage(lang!) || !isValidContentType(contentType!) || !isValidComicType(type!)) {
+ return Astro.redirect('/en/sfw/all');
+}
+
+let comics: Comic[] = [];
+let genres: Genre[] = [];
+let error: string | null = null;
+
+try {
+ [comics, genres] = await Promise.all([
+ fetchComics(lang, contentType, type as any),
+ fetchGenres(),
+ ]);
+} catch (e) {
+ error = e instanceof Error ? e.message : 'Failed to fetch comics';
+}
+
+const title = `ComicK - ${getLanguageName(lang!)} ${contentType?.toUpperCase()} ${type?.toUpperCase()}`;
+---
+
+
+
+
+
+
+
+ {error && (
+
+
Error: {error}
+
+
+ )}
+
+
+ {comics.length > 0 ? (
+ comics.map(comic => (
+
+ ))
+ ) : !error ? (
+ Array(10).fill(null).map(() => (
+
+ ))
+ ) : (
+
+ )}
+
+
+
\ No newline at end of file
diff --git a/src/pages/[lang]/[type].astro b/src/pages/[lang]/[type].astro
index 45b5112..876fd49 100644
--- a/src/pages/[lang]/[type].astro
+++ b/src/pages/[lang]/[type].astro
@@ -7,6 +7,11 @@ import RSSLink from '../../components/RSSLink.astro';
import { fetchComics, isValidLanguage, isValidContentType, fetchGenres, getLanguageName } from '../../lib/api';
import type { Comic } from '../../lib/types';
+export const prerender = false;
+
+// Redirect old URLs to new structure
+return Astro.redirect(`/${Astro.params.lang}/${Astro.params.type}/all`);
+
export async function getStaticPaths() {
const languages = ['en', 'fr', 'es', 'it', 'pl', 'tr', 'ja', 'zh', 'sv'];
const types = ['sfw', 'nsfw'];
diff --git a/src/pages/index.astro b/src/pages/index.astro
index 02082cd..f6fc030 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -11,5 +11,5 @@ export const prerender = false;
-
+
\ No newline at end of file
diff --git a/src/pages/rss/[lang]/[contentType]/[type].xml.ts b/src/pages/rss/[lang]/[contentType]/[type].xml.ts
new file mode 100644
index 0000000..c7bfd55
--- /dev/null
+++ b/src/pages/rss/[lang]/[contentType]/[type].xml.ts
@@ -0,0 +1,53 @@
+import rss from "@astrojs/rss";
+import {
+ fetchComics,
+ isValidLanguage,
+ isValidContentType,
+ isValidComicType,
+ fetchGenres,
+ getGenreNames,
+} from "../../../../lib/api";
+import type { APIRoute } from "astro";
+import type { ComicType } from "../../../../lib/types";
+
+export const GET: APIRoute = async ({ params, request }) => {
+ const { lang = "en", contentType = "sfw", type = "all" } = params;
+
+ if (!isValidLanguage(lang) || !isValidContentType(contentType) || !isValidComicType(type)) {
+ return new Response("Invalid parameters", { status: 400 });
+ }
+
+ const [comics, genres] = await Promise.all([
+ fetchComics(lang, contentType, type as ComicType),
+ fetchGenres(),
+ ]);
+
+ const siteURL = new URL(request.url).origin;
+
+ return rss({
+ title: `ComicK - ${lang.toUpperCase()} ${contentType.toUpperCase()} ${type.toUpperCase()}`,
+ description: `A simple RSS feed for ComicK!`,
+ site: "https://github.com/ld3z/manga-rss",
+ items: comics.map((comic) => {
+ const genreNames = getGenreNames(comic.md_comics.genres, genres);
+ const genresHtml = genreNames.length > 0
+ ? `Genres: ${genreNames.join(', ')}
`
+ : '';
+
+ return {
+ title: `${comic.md_comics.title} - Chapter ${comic.chap}`,
+ link: `https://comick.io/comic/${comic.md_comics.slug}`,
+ pubDate: new Date(comic.updated_at),
+ description: `Chapter ${comic.chap} of ${comic.md_comics.title} is now available on ComicK!
+ ${genresHtml}
+ ${
+ comic.md_comics.md_covers[0]
+ ? `
`
+ : ""
+ }
+ `,
+ };
+ }),
+ });
+};
\ No newline at end of file