Plugin: Genesis studio (#1038)

* genesis: started implementation

* genesis: wip

* genesis: implemented parse novel

* genesis: added icon

* genesis: wip

* genesis: added chapters

* genesis: wip

* genesis: updated chapter name

* genesis: parse chapter

* genesis: revert version

* genesis: fixed pages and custom css

* genesis: update

* genesis: edit ta-center

* genesis: remove line-height

* genesis: old genesis deprecated
This commit is contained in:
Batorian
2024-07-12 17:52:24 +02:00
committed by GitHub
parent fe84561c9c
commit 19f8b681eb
5 changed files with 535 additions and 2 deletions
+168
View File
@@ -0,0 +1,168 @@
/* eslint-disable no-case-declarations */
import { fetchApi } from '@libs/fetch';
import { Filters, FilterTypes } from '@libs/filterInputs';
import { Plugin } from '@typings/plugin';
class Genesis implements Plugin.PluginBase {
id = 'genesistudio';
name = 'Genesis';
icon = 'src/en/genesis/icon.png';
customCSS = 'src/en/genesis/customCSS.css';
site = 'https://genesistudio.com';
version = '1.0.0';
imageRequestInit?: Plugin.ImageRequestInit | undefined = {
headers: {
'referrer': this.site,
},
};
async parseNovels(json: any[]): Promise<Plugin.NovelItem[]> {
const assets = 'https://edit.genesistudio.com/assets/';
const format = '?format=auto&quality=70&width=400&height=600';
return json.map((novel: any) => {
return {
name: novel.novel_title,
path: `/novels/${novel.abbreviation}`,
cover: `${assets}${novel.cover}${format}`,
};
});
}
async popularNovels(
pageNo: number,
{
showLatestNovels,
filters,
}: Plugin.PopularNovelsOptions<typeof this.filters>,
): Promise<Plugin.NovelItem[]> {
if (pageNo !== 1) return [];
let link = `https://genesistudio.com/api/search?`;
if (showLatestNovels) {
link += 'sort=Recent';
} else {
if (filters!.genres.value.length) {
link += filters!.genres.value.join('&');
}
link += `&${filters!.storyStatus.value}&${filters!.sort.value}`;
}
const json = await fetchApi(link).then(r => r.json());
return this.parseNovels(json);
}
async parseNovel(novelPath: string): Promise<Plugin.SourceNovel> {
const url = `${this.site}${novelPath}/__data.json?x-sveltekit-invalidated=001`;
const json = await fetchApi(url).then(r => r.json());
const nodes = json.nodes;
const data = nodes
.filter((node: { type: string }) => node.type === 'data')
.map((node: { data: any }) => node.data)[0];
const novelData = data[data[0].novel];
const assets = 'https://edit.genesistudio.com/assets/';
const format = '?format=auto&quality=70&width=400&height=600';
const novel: Plugin.SourceNovel = {
path: novelPath,
name: data[novelData.novel_title],
cover: `${assets}${data[novelData.cover]}${format}`,
summary: data[novelData.synopsis],
author: data[novelData.author],
status: data[novelData.serialization],
};
novel.genres = data[novelData.genres]
.map((index: number) => data[index])
.join(',');
const chapterData = data[data[0].chapters];
const freeChapterData = chapterData.free;
// const premiumChapterData = chapterData.premium;
novel.chapters = data[freeChapterData]
.map((index: number) => data[index])
.map((chapter: any) => {
return {
name: `Chapter ${data[chapter.chapter_number]}: ${data[chapter.chapter_title]}`,
path: `/viewer/${data[chapter.id]}`,
releaseTime: data[chapter.date_created],
chapterNumber: data[chapter.chapter_number],
};
})
.reverse();
return novel;
}
async parseChapter(chapterPath: string): Promise<string> {
const url = `${this.site}${chapterPath}/__data.json?x-sveltekit-invalidated=001`;
const json = await fetchApi(url).then(r => r.json());
const nodes = json.nodes;
const data = nodes
.filter((node: { type: string }) => node.type === 'data')
.map((node: { data: any }) => node.data)[0];
return data[data[0].content];
}
async searchNovels(
searchTerm: string,
pageNo: number,
): Promise<Plugin.NovelItem[]> {
if (pageNo !== 1) return [];
const url = `${this.site}/api/search?serialization=All&sort=Popular&title=${searchTerm}`;
const json = await fetchApi(url).then(r => r.json());
return this.parseNovels(json);
}
filters = {
sort: {
label: 'Sort Results By',
value: 'sort=Popular',
options: [
{ label: 'Popular', value: 'sort=Popular' },
{ label: 'Recent', value: 'sort=Recent' },
{ label: 'Views', value: 'sort=Views' },
],
type: FilterTypes.Picker,
},
storyStatus: {
label: 'Status',
value: 'serialization=All',
options: [
{ label: 'All', value: 'serialization=All' },
{ label: 'Ongoing', value: 'serialization=Ongoing' },
{ label: 'Completed', value: 'serialization=Completed' },
],
type: FilterTypes.Picker,
},
genres: {
label: 'Genres',
value: [],
options: [
{ label: 'Action', value: 'genres=Action' },
{ label: 'Comedy', value: 'genres=Comedy' },
{ label: 'Drama', value: 'genres=Drama' },
{ label: 'Fantasy', value: 'genres=Fantasy' },
{ label: 'Harem', value: 'genres=Harem' },
{ label: 'Martial Arts', value: 'genres=Martial+Arts' },
{ label: 'Modern', value: 'genres=Modern' },
{ label: 'Mystery', value: 'genres=Mystery' },
{ label: 'Psychological', value: 'genres=Psychological' },
{ label: 'Romance', value: 'genres=Romance' },
{ label: 'Slice of life', value: 'genres=Slice+of+Life' },
{ label: 'Tragedy', value: 'genres=Tragedy' },
],
type: FilterTypes.CheckboxGroup,
},
} satisfies Filters;
}
export default new Genesis();