Files
2026-05-18 10:39:07 +05:00

126 lines
3.4 KiB
TypeScript

import { CheerioAPI, load as parseHTML } from 'cheerio';
import { Plugin } from '@/types/plugin';
import { defaultCover } from '@libs/defaultCover';
import { fetchApi } from '@libs/fetch';
import { Filters } from '@libs/filterInputs';
class LeafStudio implements Plugin.PluginBase {
id = 'LeafStudio';
name = 'LeafStudio';
icon = 'src/en/leafstudio/icon.png';
site = 'https://leafstudio.site/';
version = '1.0.0';
filters: Filters | undefined = undefined;
parseNovelsList(cheerio: CheerioAPI): Plugin.NovelItem[] {
return cheerio('a.novel-item')
.map((i, el) => {
const elc = parseHTML(el);
return {
name: elc('p.novel-item-title').text().trim(),
path: cheerio(el).attr('href')!.replace(this.site, ''),
cover: elc('img.novel-item-Cover').attr('src'),
};
})
.toArray();
}
async popularNovels(
page: number,
// { filters }: Plugin.PopularNovelsOptions<typeof this.filters>,
): Promise<Plugin.NovelItem[]> {
let link = this.site + 'novels';
if (page > 1) {
link += '/page/' + page;
}
const result = await fetchApi(link);
const body = await result.text();
const loadedCheerio = parseHTML(body);
return this.parseNovelsList(loadedCheerio);
}
async parseNovel(novelPath: string): Promise<Plugin.SourceNovel> {
const result = await fetchApi(this.site + novelPath);
const body = await result.text();
const loadedCheerio = parseHTML(body);
const novel: Plugin.SourceNovel = {
path: novelPath,
name: loadedCheerio('h1.title').text().trim() || '',
cover: loadedCheerio('img#novel_cover').attr('src') || defaultCover,
summary: loadedCheerio('div.desc_div > p')
.map((i, el) => parseHTML(el).text())
.toArray()
.join('\n\n'),
chapters: [],
author: '',
genres: loadedCheerio('div#tags_div > a.novel_genre')
.map((i, el) => parseHTML(el).text().trim())
.toArray()
.join(', '),
};
const status = loadedCheerio('a#novel_status').text().trim();
if (status == 'Active') {
novel.status = 'Ongoing';
} else {
novel.status = status;
}
const chapter: Plugin.ChapterItem[] = [];
loadedCheerio('a.free_chap.chap').each((i, el) => {
const path =
loadedCheerio(el).attr('href')?.trim()?.replace(this.site, '') || '';
const name = loadedCheerio(el).text();
chapter.push({
name,
path,
});
});
novel.chapters = chapter.reverse();
return novel;
}
async parseChapter(chapterPath: string): Promise<string> {
const result = await fetchApi(this.site + chapterPath);
const body = await result.text();
const loadedCheerio = parseHTML(body);
return loadedCheerio('article > p.chapter_content')
.map((i, el) => parseHTML(el).html())
.toArray()
.join('<br>');
}
async searchNovels(
searchTerm: string,
page: number,
): Promise<Plugin.NovelItem[]> {
let link = this.site + 'novels';
if (page > 1) {
link += '/page/' + page;
}
link +=
'?search=' +
encodeURIComponent(searchTerm) +
'&type=&language=&status=&sort=';
const result = await fetchApi(link);
const body = await result.text();
const loadedCheerio = parseHTML(body);
return this.parseNovelsList(loadedCheerio);
}
}
export default new LeafStudio();