refactor: Novelfire popularNovels and Fix Summary (#2100)
* fix: change novel.totalPages calculation to divide by 50 instead of 100 * update version number * fix: refactor novelfire popular,search and summary --------- Co-authored-by: G0yp <goupsoup2@gmail.com>
This commit is contained in:
+96
-100
@@ -9,11 +9,11 @@ import { storage } from '@libs/storage';
|
|||||||
class NovelFire implements Plugin.PluginBase {
|
class NovelFire implements Plugin.PluginBase {
|
||||||
id = 'novelfire';
|
id = 'novelfire';
|
||||||
name = 'Novel Fire';
|
name = 'Novel Fire';
|
||||||
version = '1.1.8';
|
version = '1.2.0';
|
||||||
icon = 'src/en/novelfire/icon.png';
|
icon = 'src/en/novelfire/icon.png';
|
||||||
site = 'https://novelfire.net/';
|
site = 'https://novelfire.net/';
|
||||||
|
|
||||||
novelList = [];
|
novelList: string[] = [];
|
||||||
|
|
||||||
singlePage = storage.get('singlePage');
|
singlePage = storage.get('singlePage');
|
||||||
pluginSettings = {
|
pluginSettings = {
|
||||||
@@ -40,63 +40,29 @@ class NovelFire implements Plugin.PluginBase {
|
|||||||
return $;
|
return $;
|
||||||
}
|
}
|
||||||
|
|
||||||
async popularNovels(
|
parseNovels(
|
||||||
pageNo: number,
|
loadedCheerio: CheerioAPI,
|
||||||
{
|
selector = '.novel-item',
|
||||||
showLatestNovels,
|
): Plugin.NovelItem[] {
|
||||||
filters,
|
return loadedCheerio(selector)
|
||||||
}: Plugin.PopularNovelsOptions<typeof this.filters>,
|
.map((_, el) => {
|
||||||
): Promise<Plugin.NovelItem[]> {
|
const titleElement = loadedCheerio(el).find('.novel-title > a');
|
||||||
if (pageNo == 1) {
|
const fallbackElement = loadedCheerio(el).find('a');
|
||||||
this.novelList = [];
|
|
||||||
}
|
|
||||||
let url = this.site + 'search-adv';
|
|
||||||
if (showLatestNovels) {
|
|
||||||
url += `?ctgcon=and&totalchapter=0&ratcon=min&rating=0&status=-1&sort=date&tagcon=and&page=${pageNo}`;
|
|
||||||
} else if (filters) {
|
|
||||||
const params = new URLSearchParams();
|
|
||||||
for (const language of filters.language.value) {
|
|
||||||
params.append('country_id[]', language);
|
|
||||||
}
|
|
||||||
params.append('ctgcon', filters.genre_operator.value);
|
|
||||||
for (const genre of filters.genres.value) {
|
|
||||||
params.append('categories[]', genre);
|
|
||||||
}
|
|
||||||
params.append('totalchapter', filters.chapters.value);
|
|
||||||
params.append('ratcon', filters.rating_operator.value);
|
|
||||||
params.append('rating', filters.rating.value);
|
|
||||||
params.append('status', filters.status.value);
|
|
||||||
params.append('sort', filters.sort.value);
|
|
||||||
params.append('page', pageNo.toString());
|
|
||||||
url += `?${params.toString()}`;
|
|
||||||
} else {
|
|
||||||
url += `?ctgcon=and&totalchapter=0&ratcon=min&rating=0&status=-1&sort=rank-top&page=${pageNo}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const loadedCheerio = await this.getCheerio(url, false);
|
|
||||||
|
|
||||||
return loadedCheerio('.novel-item')
|
|
||||||
.map((index, ele) => {
|
|
||||||
const novelName =
|
const novelName =
|
||||||
loadedCheerio(ele).find('.novel-title > a').text() ||
|
titleElement.text() ||
|
||||||
|
fallbackElement.attr('title') ||
|
||||||
'No Title Found';
|
'No Title Found';
|
||||||
|
|
||||||
|
const imgElement = loadedCheerio(el).find('.novel-cover > img');
|
||||||
const novelCover =
|
const novelCover =
|
||||||
this.site +
|
this.site +
|
||||||
deSlash(
|
deSlash(imgElement.attr('data-src') || imgElement.attr('src') || '');
|
||||||
loadedCheerio(ele).find('.novel-cover > img').attr('data-src') ||
|
|
||||||
'',
|
|
||||||
);
|
|
||||||
const novelPath = loadedCheerio(ele)
|
|
||||||
.find('.novel-title > a')
|
|
||||||
.attr('href');
|
|
||||||
|
|
||||||
if (!novelPath) return;
|
const novelPath =
|
||||||
|
titleElement.attr('href') || fallbackElement.attr('href');
|
||||||
|
|
||||||
if (this.novelList.includes(novelPath)) {
|
if (!novelPath) return null;
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
this.novelList.push(novelPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: novelName,
|
name: novelName,
|
||||||
@@ -105,15 +71,57 @@ class NovelFire implements Plugin.PluginBase {
|
|||||||
};
|
};
|
||||||
})
|
})
|
||||||
.get()
|
.get()
|
||||||
.filter(novel => novel !== null);
|
.filter(novel => novel !== null)
|
||||||
|
.filter(novel => {
|
||||||
|
if (this.novelList.includes(novel.path)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
this.novelList.push(novel.path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async popularNovels(
|
||||||
|
pageNo: number,
|
||||||
|
{
|
||||||
|
showLatestNovels,
|
||||||
|
filters,
|
||||||
|
}: Plugin.PopularNovelsOptions<typeof this.filters>,
|
||||||
|
): Promise<Plugin.NovelItem[]> {
|
||||||
|
if (pageNo === 1) {
|
||||||
|
this.novelList = [];
|
||||||
|
}
|
||||||
|
const url = this.site + 'search-adv';
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
|
||||||
|
for (const language of filters.language.value) {
|
||||||
|
params.append('country_id[]', language);
|
||||||
|
}
|
||||||
|
params.append('ctgcon', filters.genre_operator.value);
|
||||||
|
for (const genre of filters.genres.value) {
|
||||||
|
params.append('categories[]', genre);
|
||||||
|
}
|
||||||
|
params.append('totalchapter', filters.chapters.value);
|
||||||
|
params.append('ratcon', filters.rating_operator.value);
|
||||||
|
params.append('rating', filters.rating.value);
|
||||||
|
params.append('status', filters.status.value);
|
||||||
|
params.append('sort', showLatestNovels ? 'date' : filters.sort.value);
|
||||||
|
params.append('tagcon', 'and');
|
||||||
|
params.append('page', pageNo.toString());
|
||||||
|
|
||||||
|
const loadedCheerio = await this.getCheerio(
|
||||||
|
`${url}?${params.toString()}`,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
return this.parseNovels(loadedCheerio);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAllChapters(
|
async getAllChapters(
|
||||||
novelPath: string,
|
novelPath: string,
|
||||||
post_id: string,
|
post_id: string,
|
||||||
): Promise<Plugin.ChapterItem[]> {
|
): Promise<Plugin.ChapterItem[]> {
|
||||||
const allChapters: Plugin.ChapterItem[] = [];
|
|
||||||
|
|
||||||
const url = `${this.site}listChapterDataAjax?post_id=${post_id}`;
|
const url = `${this.site}listChapterDataAjax?post_id=${post_id}`;
|
||||||
const result = await fetchApi(url);
|
const result = await fetchApi(url);
|
||||||
const body = await result.text();
|
const body = await result.text();
|
||||||
@@ -128,7 +136,7 @@ class NovelFire implements Plugin.PluginBase {
|
|||||||
|
|
||||||
const json = JSON.parse(body);
|
const json = JSON.parse(body);
|
||||||
const chapters = json.data
|
const chapters = json.data
|
||||||
.map(index => {
|
.map((index: { title?: string; slug: string; n_sort: number }) => {
|
||||||
const chapterName = load(index.title || index.slug).text();
|
const chapterName = load(index.title || index.slug).text();
|
||||||
const chapterPath = `${novelPath}/chapter-${index.n_sort}`;
|
const chapterPath = `${novelPath}/chapter-${index.n_sort}`;
|
||||||
const sortNumber = index.n_sort;
|
const sortNumber = index.n_sort;
|
||||||
@@ -141,9 +149,11 @@ class NovelFire implements Plugin.PluginBase {
|
|||||||
chapterNumber: Number(sortNumber),
|
chapterNumber: Number(sortNumber),
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter(chapter => chapter !== null) as Plugin.ChapterItem[];
|
.filter(
|
||||||
|
(chapter: Plugin.ChapterItem | null) => chapter !== null,
|
||||||
|
) as Plugin.ChapterItem[];
|
||||||
const sortedChapters = chapters.sort(function (a, b) {
|
const sortedChapters = chapters.sort(function (a, b) {
|
||||||
return a.chapterNumber - b.chapterNumber;
|
return (a.chapterNumber || 0) - (b.chapterNumber || 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
return sortedChapters;
|
return sortedChapters;
|
||||||
@@ -161,7 +171,7 @@ class NovelFire implements Plugin.PluginBase {
|
|||||||
const retryCount = 10;
|
const retryCount = 10;
|
||||||
const sleepTime = 3.5; // Rate limit seems to be around ~10s, so usually 3 retries should be enough for another ~30 pages.
|
const sleepTime = 3.5; // Rate limit seems to be around ~10s, so usually 3 retries should be enough for another ~30 pages.
|
||||||
|
|
||||||
const chaptersArray: Plugin.ChapterItem[][] = [];
|
const chaptersArray: Plugin.SourcePage[] = [];
|
||||||
|
|
||||||
for (let i = 0; i < pagesArray.length; i += chunkSize) {
|
for (let i = 0; i < pagesArray.length; i += chunkSize) {
|
||||||
const pagesArrayChunk = pagesArray.slice(i, i + chunkSize);
|
const pagesArrayChunk = pagesArray.slice(i, i + chunkSize);
|
||||||
@@ -202,11 +212,11 @@ class NovelFire implements Plugin.PluginBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Merge all chapters into a single array
|
// Merge all chapters into a single array
|
||||||
for (let chapters of chaptersArray) {
|
for (const page of chaptersArray) {
|
||||||
// For some reason it's formatted this way, this fixes it.
|
if (page.chapters) {
|
||||||
chapters = chapters.chapters;
|
for (const chapter of page.chapters) {
|
||||||
for (let i = 0; i < Object.keys(chapters).length; i++) {
|
allChapters.push(chapter);
|
||||||
allChapters.push(chapters[i]);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return allChapters;
|
return allChapters;
|
||||||
@@ -244,19 +254,19 @@ class NovelFire implements Plugin.PluginBase {
|
|||||||
.toArray()
|
.toArray()
|
||||||
.join(',');
|
.join(',');
|
||||||
|
|
||||||
let summary = $('.summary .content')
|
const summary = $('.summary .content');
|
||||||
.find('br')
|
summary.find('.expand').remove();
|
||||||
.replaceWith('\n')
|
summary.find('br').replaceWith('\n');
|
||||||
.end()
|
summary.find('p').before('\n').after('\n\n');
|
||||||
.text()
|
|
||||||
.trim();
|
|
||||||
|
|
||||||
if (summary) {
|
novel.summary =
|
||||||
summary = summary.replace('Show More', '');
|
summary
|
||||||
novel.summary = summary;
|
.text()
|
||||||
} else {
|
.split('\n')
|
||||||
novel.summary = 'No Summary Found';
|
.map(line => line.trim())
|
||||||
}
|
.join('\n')
|
||||||
|
?.replace(/\n{3,}/g, '\n\n')
|
||||||
|
.trim() || 'Summary Not Found';
|
||||||
|
|
||||||
novel.author = $('.author .property-item > span').text();
|
novel.author = $('.author .property-item > span').text();
|
||||||
|
|
||||||
@@ -285,13 +295,13 @@ class NovelFire implements Plugin.PluginBase {
|
|||||||
.parent()
|
.parent()
|
||||||
.text()
|
.text()
|
||||||
.trim();
|
.trim();
|
||||||
novel.totalPages = Math.ceil(parseInt(totalChapters) / 100);
|
novel.totalPages = Math.ceil(parseInt(totalChapters) / 50);
|
||||||
if (this.singlePage) {
|
if (this.singlePage) {
|
||||||
novel.chapters = await this.getAllChaptersForce(
|
novel.chapters = await this.getAllChaptersForce(
|
||||||
novelPath,
|
novelPath,
|
||||||
novel.totalPages,
|
novel.totalPages,
|
||||||
);
|
);
|
||||||
if (novel.totalPages > 1 && novel.chapters.length > 100) {
|
if (novel.totalPages > 1 && novel.chapters.length > 50) {
|
||||||
novel.totalPages = 1;
|
novel.totalPages = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -350,33 +360,19 @@ class NovelFire implements Plugin.PluginBase {
|
|||||||
searchTerm: string,
|
searchTerm: string,
|
||||||
page: number,
|
page: number,
|
||||||
): Promise<Plugin.NovelItem[]> {
|
): Promise<Plugin.NovelItem[]> {
|
||||||
const url = `${this.site}search?keyword=${encodeURIComponent(searchTerm)}&page=${page}`;
|
if (page === 1) {
|
||||||
|
this.novelList = [];
|
||||||
|
}
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
params.append('keyword', searchTerm);
|
||||||
|
params.append('page', page.toString());
|
||||||
|
const url = `${this.site}search?${params.toString()}`;
|
||||||
const result = await fetchApi(url);
|
const result = await fetchApi(url);
|
||||||
const body = await result.text();
|
const body = await result.text();
|
||||||
|
|
||||||
const loadedCheerio = load(body);
|
const loadedCheerio = load(body);
|
||||||
|
|
||||||
return loadedCheerio('.novel-list.chapters .novel-item')
|
return this.parseNovels(loadedCheerio, '.novel-list.chapters .novel-item');
|
||||||
.map((index, ele) => {
|
|
||||||
const novelName =
|
|
||||||
loadedCheerio(ele).find('a').attr('title') || 'No Title Found';
|
|
||||||
const novelCover =
|
|
||||||
this.site +
|
|
||||||
deSlash(
|
|
||||||
loadedCheerio(ele).find('.novel-cover > img').attr('src') || '',
|
|
||||||
);
|
|
||||||
const novelPath = loadedCheerio(ele).find('a').attr('href');
|
|
||||||
|
|
||||||
if (!novelPath) return null;
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: novelName,
|
|
||||||
cover: novelCover,
|
|
||||||
path: deSlash(novelPath.replace(this.site, '')),
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.get()
|
|
||||||
.filter(novel => novel !== null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
filters = {
|
filters = {
|
||||||
|
|||||||
Reference in New Issue
Block a user