* add prettier

* lint-staged

* prettier

* upgrade husky
This commit is contained in:
nyagami
2024-03-23 22:00:29 +07:00
committed by GitHub
parent c22979b10f
commit 5f9a067ab9
113 changed files with 79244 additions and 50841 deletions
+191 -192
View File
@@ -1,215 +1,214 @@
import { CheerioAPI, load as parseHTML } from "cheerio";
import { fetchApi, fetchFile } from "@libs/fetch";
import { FilterTypes, Filters } from "@libs/filterInputs";
import { Plugin } from "@typings/plugin";
import { isUrlAbsolute } from "@libs/isAbsoluteUrl";
import { CheerioAPI, load as parseHTML } from 'cheerio';
import { fetchApi, fetchFile } from '@libs/fetch';
import { FilterTypes, Filters } from '@libs/filterInputs';
import { Plugin } from '@typings/plugin';
import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
class AllNovelFullPlugin implements Plugin.PluginBase {
id = "anf.net";
name = "AllNovelFull";
icon = "src/en/allnovelfull/icon.png";
site = "https://allnovelfull.net";
version = "1.0.0";
id = 'anf.net';
name = 'AllNovelFull';
icon = 'src/en/allnovelfull/icon.png';
site = 'https://allnovelfull.net';
version = '1.0.0';
parseNovels(loadedCheerio: CheerioAPI) {
const novels: Plugin.NovelItem[] = [];
parseNovels(loadedCheerio: CheerioAPI) {
const novels: Plugin.NovelItem[] = [];
loadedCheerio(".col-truyen-main .list-truyen .row").each((i,el) => {
const novelUrl = loadedCheerio(el).find("h3.truyen-title > a").attr("href");
if (!novelUrl) return;
loadedCheerio('.col-truyen-main .list-truyen .row').each((i, el) => {
const novelUrl = loadedCheerio(el)
.find('h3.truyen-title > a')
.attr('href');
if (!novelUrl) return;
const novelName = loadedCheerio(el)
.find("h3.truyen-title > a")
.text();
const novelName = loadedCheerio(el).find('h3.truyen-title > a').text();
let novelCover = loadedCheerio(el).find("img.cover").attr("src");
if (novelCover && !isUrlAbsolute(novelCover)){
novelCover = this.site + novelCover;
}
let novelCover = loadedCheerio(el).find('img.cover').attr('src');
if (novelCover && !isUrlAbsolute(novelCover)) {
novelCover = this.site + novelCover;
}
const novel = {
path: novelUrl,
name: novelName,
cover: novelCover,
};
novels.push(novel);
const novel = {
path: novelUrl,
name: novelName,
cover: novelCover,
};
novels.push(novel);
});
return novels;
}
async popularNovels(
pageNo: number,
{ filters }: Plugin.PopularNovelsOptions<typeof this.filters>,
): Promise<Plugin.NovelItem[]> {
let link = this.site;
if (filters.genres.value.length) link += filters.genres.value;
else link += filters.order.value;
link += `?page=${pageNo}`;
const result = await fetchApi(link);
const body = await result.text();
const loadedCheerio = parseHTML(body);
return this.parseNovels(loadedCheerio);
}
async parseNovel(novelPath: string): Promise<Plugin.SourceNovel> {
const url = this.site + novelPath;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
const novel: Plugin.SourceNovel = {
path: novelPath,
name: loadedCheerio('.book > img').attr('alt') || 'Untitled',
cover: this.site + loadedCheerio('.book > img').attr('src'),
summary: loadedCheerio('.desc-text').text().trim(),
chapters: [],
};
loadedCheerio('.info > div').each((i, el) => {
const detailName = loadedCheerio(el).find('h3').text();
const detail = loadedCheerio(el)
.find('a')
.map((a, ex) => loadedCheerio(ex).text())
.toArray()
.join(',');
switch (detailName) {
case 'Author:':
novel.author = detail;
break;
case 'Status:':
novel.status = detail;
break;
case 'Genre:':
novel.genres = detail;
break;
}
});
const novelId = loadedCheerio('#rating').attr('data-novel-id');
const getChapters = async (id: string) => {
const chaptersUrl = this.site + '/ajax/chapter-option?novelId=' + id;
const data = await fetchApi(chaptersUrl);
const chapters = await data.text();
loadedCheerio = parseHTML(chapters);
const chapter: Plugin.ChapterItem[] = [];
loadedCheerio('select > option').each((i, el) => {
const chapterName = loadedCheerio(el).text();
const chapterUrl = loadedCheerio(el).attr('value');
if (!chapterUrl) return;
chapter.push({
name: chapterName,
path: chapterUrl,
});
return novels;
});
return chapter;
};
async popularNovels(
pageNo: number,
{ filters }: Plugin.PopularNovelsOptions<typeof this.filters>
): Promise<Plugin.NovelItem[]> {
let link = this.site;
if (filters.genres.value.length)
link += filters.genres.value;
else
link += filters.order.value;
link += `?page=${pageNo}`;
const result = await fetchApi(link);
const body = await result.text();
const loadedCheerio = parseHTML(body);
return this.parseNovels(loadedCheerio);
if (novelId) {
novel.chapters = await getChapters(novelId);
}
async parseNovel(novelPath: string): Promise<Plugin.SourceNovel> {
const url = this.site + novelPath;
const result = await fetchApi(url);
const body = await result.text();
return novel;
}
let loadedCheerio = parseHTML(body);
async parseChapter(chapterPath: string): Promise<string> {
const result = await fetchApi(this.site + chapterPath);
const body = await result.text();
const novel: Plugin.SourceNovel = {
path: novelPath,
name: loadedCheerio(".book > img").attr("alt") || 'Untitled',
cover: this.site + loadedCheerio(".book > img").attr("src"),
summary: loadedCheerio(".desc-text").text().trim(),
chapters: [],
};
const loadedCheerio = parseHTML(body);
loadedCheerio(".info > div").each((i,el) => {
const detailName = loadedCheerio(el).find("h3").text();
const detail = loadedCheerio(el)
.find('a')
.map((a,ex) => loadedCheerio(ex).text())
.toArray()
.join(',');
const chapterText = loadedCheerio('#chapter-content').html() || '';
switch (detailName) {
case 'Author:':
novel.author = detail;
break;
case 'Status:':
novel.status = detail;
break;
case 'Genre:':
novel.genres = detail;
break;
}});
return chapterText;
}
const novelId = loadedCheerio("#rating").attr("data-novel-id");
async searchNovels(
searchTerm: string,
page: number,
): Promise<Plugin.NovelItem[]> {
const url = `${this.site}/search?keyword=${searchTerm}&page=${page}`;
const result = await fetchApi(url);
const body = await result.text();
const getChapters = async (id: string) => {
const chaptersUrl = this.site + "/ajax/chapter-option?novelId=" + id;
const loadedCheerio = parseHTML(body);
return this.parseNovels(loadedCheerio);
}
const data = await fetchApi(chaptersUrl);
const chapters = await data.text();
async fetchImage(url: string): Promise<string | undefined> {
return await fetchFile(url);
}
loadedCheerio = parseHTML(chapters);
const chapter: Plugin.ChapterItem[] = [];
loadedCheerio("select > option").each((i,el) => {
const chapterName = loadedCheerio(el).text();
const chapterUrl = loadedCheerio(el).attr("value");
if (!chapterUrl ) return;
chapter.push({
name: chapterName,
path: chapterUrl,
});
});
return chapter;
}
if (novelId) {
novel.chapters = await getChapters(novelId);
}
return novel;
};
async parseChapter(chapterPath: string): Promise<string> {
const result = await fetchApi(this.site + chapterPath);
const body = await result.text();
const loadedCheerio = parseHTML(body);
const chapterText = loadedCheerio("#chapter-content").html() || "";
return chapterText;
};
async searchNovels(
searchTerm: string,
page: number
): Promise<Plugin.NovelItem[]> {
const url = `${this.site}/search?keyword=${searchTerm}&page=${page}`;
const result = await fetchApi(url);
const body = await result.text();
const loadedCheerio = parseHTML(body);
return this.parseNovels(loadedCheerio);
};
async fetchImage(url: string): Promise<string | undefined> {
return await fetchFile(url);
}
filters = {
order: {
value: "/most-popular",
label: "Order by",
options: [
{ label: "Latest Release", value: "/latest-release-novel" },
{ label: "Hot Novel", value: "/hot-novel" },
{ label: "Completed Novel", value: "/completed-novel" },
{ label: "Most Popular", value: "/most-popular" },
],
type: FilterTypes.Picker,
},
genres: {
value: "",
label: "Genre",
options: [
{ label: "None", value: "" },
{ label: "Shounen", value: "/genre/Shounen" },
{ label: "Harem", value: "/genre/Harem" },
{ label: "Comedy", value: "/genre/Comedy" },
{ label: "Martial Arts", value: "/genre/Martial+Arts" },
{ label: "School Life", value: "/genre/School+Life" },
{ label: "Mystery", value: "/genre/Mystery" },
{ label: "Shoujo", value: "/genre/Shoujo" },
{ label: "Romance", value: "/genre/Romance" },
{ label: "Sci-fi", value: "/genre/Sci-fi" },
{ label: "Gender Bender", value: "/genre/Gender+Bender" },
{ label: "Mature", value: "/genre/Mature" },
{ label: "Fantasy", value: "/genre/Fantasy" },
{ label: "Horror", value: "/genre/Horror" },
{ label: "Drama", value: "/genre/Drama" },
{ label: "Tragedy", value: "/genre/Tragedy" },
{ label: "Supernatural", value: "/genre/Supernatural" },
{ label: "Ecchi", value: "/genre/Ecchi" },
{ label: "Xuanhuan", value: "/genre/Xuanhuan" },
{ label: "Adventure", value: "/genre/Adventure" },
{ label: "Action", value: "/genre/Action" },
{ label: "Psychological", value: "/genre/Psychological" },
{ label: "Xianxia", value: "/genre/Xianxia" },
{ label: "Wuxia", value: "/genre/Wuxia" },
{ label: "Historical", value: "/genre/Historical" },
{ label: "Slice of Life", value: "/genre/Slice+of+Life" },
{ label: "Seinen", value: "/genre/Seinen" },
{ label: "Lolicon", value: "/genre/Lolicon" },
{ label: "Adult", value: "/genre/Adult" },
{ label: "Josei", value: "/genre/Josei" },
{ label: "Sports", value: "/genre/Sports" },
{ label: "Smut", value: "/genre/Smut" },
{ label: "Mecha", value: "/genre/Mecha" },
{ label: "Yaoi", value: "/genre/Yaoi" },
{ label: "Shounen Ai", value: "/genre/Shounen+Ai" },
{ label: "Magical Realism", value: "/genre/Magical+Realism" },
{ label: "Video Games", value: "/genre/Video+Games" },
],
type: FilterTypes.Picker,
},
} satisfies Filters;
filters = {
order: {
value: '/most-popular',
label: 'Order by',
options: [
{ label: 'Latest Release', value: '/latest-release-novel' },
{ label: 'Hot Novel', value: '/hot-novel' },
{ label: 'Completed Novel', value: '/completed-novel' },
{ label: 'Most Popular', value: '/most-popular' },
],
type: FilterTypes.Picker,
},
genres: {
value: '',
label: 'Genre',
options: [
{ label: 'None', value: '' },
{ label: 'Shounen', value: '/genre/Shounen' },
{ label: 'Harem', value: '/genre/Harem' },
{ label: 'Comedy', value: '/genre/Comedy' },
{ label: 'Martial Arts', value: '/genre/Martial+Arts' },
{ label: 'School Life', value: '/genre/School+Life' },
{ label: 'Mystery', value: '/genre/Mystery' },
{ label: 'Shoujo', value: '/genre/Shoujo' },
{ label: 'Romance', value: '/genre/Romance' },
{ label: 'Sci-fi', value: '/genre/Sci-fi' },
{ label: 'Gender Bender', value: '/genre/Gender+Bender' },
{ label: 'Mature', value: '/genre/Mature' },
{ label: 'Fantasy', value: '/genre/Fantasy' },
{ label: 'Horror', value: '/genre/Horror' },
{ label: 'Drama', value: '/genre/Drama' },
{ label: 'Tragedy', value: '/genre/Tragedy' },
{ label: 'Supernatural', value: '/genre/Supernatural' },
{ label: 'Ecchi', value: '/genre/Ecchi' },
{ label: 'Xuanhuan', value: '/genre/Xuanhuan' },
{ label: 'Adventure', value: '/genre/Adventure' },
{ label: 'Action', value: '/genre/Action' },
{ label: 'Psychological', value: '/genre/Psychological' },
{ label: 'Xianxia', value: '/genre/Xianxia' },
{ label: 'Wuxia', value: '/genre/Wuxia' },
{ label: 'Historical', value: '/genre/Historical' },
{ label: 'Slice of Life', value: '/genre/Slice+of+Life' },
{ label: 'Seinen', value: '/genre/Seinen' },
{ label: 'Lolicon', value: '/genre/Lolicon' },
{ label: 'Adult', value: '/genre/Adult' },
{ label: 'Josei', value: '/genre/Josei' },
{ label: 'Sports', value: '/genre/Sports' },
{ label: 'Smut', value: '/genre/Smut' },
{ label: 'Mecha', value: '/genre/Mecha' },
{ label: 'Yaoi', value: '/genre/Yaoi' },
{ label: 'Shounen Ai', value: '/genre/Shounen+Ai' },
{ label: 'Magical Realism', value: '/genre/Magical+Realism' },
{ label: 'Video Games', value: '/genre/Video+Games' },
],
type: FilterTypes.Picker,
},
} satisfies Filters;
}
export default new AllNovelFullPlugin();