feat(fucknovelpia): implement showLatestNovels (#2326)
Signed-off-by: K1ngfish3r <26593485+K1ngfish3r@users.noreply.github.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import { CheerioAPI, load as parseHTML } from 'cheerio';
|
import { CheerioAPI, load as parseHTML } from 'cheerio';
|
||||||
|
import { Parser } from 'htmlparser2';
|
||||||
import { Plugin } from '@/types/plugin';
|
import { Plugin } from '@/types/plugin';
|
||||||
import { defaultCover } from '@libs/defaultCover';
|
import { defaultCover } from '@libs/defaultCover';
|
||||||
import { NovelStatus } from '@libs/novelStatus';
|
import { NovelStatus } from '@libs/novelStatus';
|
||||||
@@ -10,7 +11,7 @@ class FuckNovelpia implements Plugin.PluginBase {
|
|||||||
name = 'FuckNovelpia';
|
name = 'FuckNovelpia';
|
||||||
icon = 'src/en/fucknovelpia/icon.png';
|
icon = 'src/en/fucknovelpia/icon.png';
|
||||||
site = 'https://fucknovelpia.com/';
|
site = 'https://fucknovelpia.com/';
|
||||||
version = '1.1.0';
|
version = '1.1.1';
|
||||||
|
|
||||||
// Returns false once the site has silently clamped us past the real last page.
|
// Returns false once the site has silently clamped us past the real last page.
|
||||||
hasRequestedPage(cheerio: CheerioAPI, requestedPage: number): boolean {
|
hasRequestedPage(cheerio: CheerioAPI, requestedPage: number): boolean {
|
||||||
@@ -49,6 +50,64 @@ class FuckNovelpia implements Plugin.PluginBase {
|
|||||||
return novels;
|
return novels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async parseLatestUpdates() {
|
||||||
|
const link = this.site + 'updates.php';
|
||||||
|
const response = await fetchApi(link);
|
||||||
|
const html = await response.text();
|
||||||
|
const novels: Plugin.NovelItem[] = [];
|
||||||
|
let tempNovel: Partial<Plugin.NovelItem> = {};
|
||||||
|
const seen = new Set<string>();
|
||||||
|
|
||||||
|
const stateStack: ParsingState[] = [ParsingState.Idle];
|
||||||
|
const currentState = () => stateStack[stateStack.length - 1];
|
||||||
|
const pushState = (state: ParsingState) => stateStack.push(state);
|
||||||
|
const popState = () =>
|
||||||
|
stateStack.length > 1 ? stateStack.pop() : currentState();
|
||||||
|
|
||||||
|
const parser = new Parser({
|
||||||
|
onopentag: (name, attribs) => {
|
||||||
|
const state = currentState();
|
||||||
|
if (attribs.class === 'updates-list') {
|
||||||
|
pushState(ParsingState.NovelList);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state === ParsingState.Idle) return;
|
||||||
|
|
||||||
|
switch (name) {
|
||||||
|
case 'a':
|
||||||
|
if (seen.has(attribs.href)) return;
|
||||||
|
seen.add(attribs.href);
|
||||||
|
pushState(ParsingState.Novel);
|
||||||
|
tempNovel.path = attribs.href.substring(1);
|
||||||
|
break;
|
||||||
|
case 'img':
|
||||||
|
tempNovel.cover = attribs.src;
|
||||||
|
tempNovel.name = attribs.alt;
|
||||||
|
break;
|
||||||
|
case 'div':
|
||||||
|
switch (attribs.class) {
|
||||||
|
case 'copy':
|
||||||
|
if (tempNovel.name && tempNovel.path) {
|
||||||
|
novels.push({ ...tempNovel } as Plugin.NovelItem);
|
||||||
|
popState();
|
||||||
|
}
|
||||||
|
tempNovel = {};
|
||||||
|
break;
|
||||||
|
case 'install-banner':
|
||||||
|
popState();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
parser.write(html);
|
||||||
|
parser.end();
|
||||||
|
|
||||||
|
return novels;
|
||||||
|
}
|
||||||
|
|
||||||
async popularNovels(
|
async popularNovels(
|
||||||
page: number,
|
page: number,
|
||||||
{
|
{
|
||||||
@@ -56,15 +115,14 @@ class FuckNovelpia implements Plugin.PluginBase {
|
|||||||
filters,
|
filters,
|
||||||
}: Plugin.PopularNovelsOptions<typeof this.filters>,
|
}: Plugin.PopularNovelsOptions<typeof this.filters>,
|
||||||
): Promise<Plugin.NovelItem[]> {
|
): Promise<Plugin.NovelItem[]> {
|
||||||
|
if (showLatestNovels) {
|
||||||
|
return this.parseLatestUpdates();
|
||||||
|
}
|
||||||
|
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
|
|
||||||
params.set('q', '');
|
params.set('q', '');
|
||||||
|
params.set('sort', filters.sort.value);
|
||||||
if (showLatestNovels) {
|
|
||||||
params.set('sort', 'latest');
|
|
||||||
} else {
|
|
||||||
params.set('sort', filters.sort.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search metadata filters (appears all the time)
|
// Search metadata filters (appears all the time)
|
||||||
for (const key of [
|
for (const key of [
|
||||||
@@ -672,3 +730,9 @@ class FuckNovelpia implements Plugin.PluginBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default new FuckNovelpia();
|
export default new FuckNovelpia();
|
||||||
|
|
||||||
|
enum ParsingState {
|
||||||
|
Idle,
|
||||||
|
Novel,
|
||||||
|
NovelList,
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user