fix: [Genesis]: Update Source URL and Parsing Logic (#1204)
* New Source dreambigtl (Dream Big Translations) * Apply suggestions from code review Co-authored-by: nyagami <hoangquan05112002@gmail.com> * Update dreambigtl.ts * gensis fix, they obfuscated their api...dont be suprised chapter names are missing... * Update galaxy translations new domain * version increment * they changed their code again --------- Co-authored-by: Ridi <ridi.culous.progger@gmail.com> Co-authored-by: nyagami <hoangquan05112002@gmail.com>
This commit is contained in:
@@ -347,11 +347,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "galaxytranslations",
|
"id": "galaxytranslations",
|
||||||
"sourceSite": "https://galaxytranslations11.com/",
|
"sourceSite": "https://darkstartranslations.com/",
|
||||||
"sourceName": "Galaxy Translations",
|
"sourceName": "Galaxy Translations",
|
||||||
"options": {
|
"options": {
|
||||||
"useNewChapterEndpoint": true,
|
"useNewChapterEndpoint": true,
|
||||||
"versionIncrements": 2,
|
"versionIncrements": 3,
|
||||||
"lang": "English"
|
"lang": "English"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -18,87 +18,103 @@ class Genesis implements Plugin.PluginBase {
|
|||||||
icon = 'src/en/genesis/icon.png';
|
icon = 'src/en/genesis/icon.png';
|
||||||
customCSS = 'src/en/genesis/customCSS.css';
|
customCSS = 'src/en/genesis/customCSS.css';
|
||||||
site = 'https://genesistudio.com';
|
site = 'https://genesistudio.com';
|
||||||
version = '1.0.3';
|
version = '1.0.4';
|
||||||
|
|
||||||
imageRequestInit?: Plugin.ImageRequestInit | undefined = {
|
imageRequestInit?: Plugin.ImageRequestInit | undefined = {
|
||||||
headers: {
|
headers: {
|
||||||
'referrer': this.site,
|
'referrer': this.site,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
async parseNovels(json: any[]): Promise<Plugin.NovelItem[]> {
|
async parseNovels(json: any[]): Promise<Plugin.SourceNovel[]> {
|
||||||
return json.map((novel: any) => {
|
return json.map((novel: any) => ({
|
||||||
return {
|
name: novel.novel_title,
|
||||||
name: novel.novel_title,
|
path: `/novels/${novel.abbreviation}`,
|
||||||
path: `/novels/${novel.abbreviation}`,
|
cover: novel.cover,
|
||||||
cover: novel.cover,
|
}));
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async popularNovels(
|
async popularNovels(
|
||||||
pageNo: number,
|
pageNo: number,
|
||||||
{
|
{ showLatestNovels, filters }: Plugin.PopularNovelsOptions,
|
||||||
showLatestNovels,
|
): Promise<Plugin.SourceNovel[]> {
|
||||||
filters,
|
|
||||||
}: Plugin.PopularNovelsOptions<typeof this.filters>,
|
|
||||||
): Promise<Plugin.NovelItem[]> {
|
|
||||||
if (pageNo !== 1) return [];
|
if (pageNo !== 1) return [];
|
||||||
|
let link = `${this.site}/api/search?`;
|
||||||
let link = `https://genesistudio.com/api/search?`;
|
|
||||||
if (showLatestNovels) {
|
if (showLatestNovels) {
|
||||||
link += 'sort=Recent';
|
link += 'sort=Recent';
|
||||||
} else {
|
} else {
|
||||||
if (filters!.genres.value.length) {
|
if (filters!.genres.value) {
|
||||||
link += filters!.genres.value.join('&');
|
link += filters!.genres.value;
|
||||||
}
|
}
|
||||||
link += `&${filters!.storyStatus.value}&${filters!.sort.value}`;
|
link += `&${filters!.storyStatus.value}&${filters!.sort.value}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const json = await fetchApi(link).then(r => r.json());
|
const json = await fetchApi(link).then(r => r.json());
|
||||||
|
|
||||||
return this.parseNovels(json);
|
return this.parseNovels(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
async parseNovel(novelPath: string): Promise<Plugin.SourceNovel> {
|
async parseNovel(novelPath: string): Promise<Plugin.SourceNovel> {
|
||||||
const url = `${this.site}${novelPath}/__data.json?x-sveltekit-invalidated=001`;
|
const url = `${this.site}${novelPath}/__data.json?x-sveltekit-invalidated=001`;
|
||||||
const json = await fetchApi(url).then(r => r.json());
|
const json = await fetchApi(url).then(r => r.json());
|
||||||
|
|
||||||
const nodes = json.nodes;
|
const nodes = json.nodes;
|
||||||
const data = nodes
|
const data = nodes
|
||||||
.filter((node: { type: string }) => node.type === 'data')
|
.filter((node: { type: string }) => node.type === 'data')
|
||||||
.map((node: { data: any }) => node.data)[0];
|
.map((node: { data: any }) => node.data)[0];
|
||||||
const novelData = data[data[0].novel];
|
|
||||||
|
|
||||||
const novel: Plugin.SourceNovel = {
|
const novel: Plugin.SourceNovel = {
|
||||||
path: novelPath,
|
path: novelPath,
|
||||||
name: data[novelData.novel_title],
|
name: '',
|
||||||
cover: data[novelData.cover],
|
cover: '',
|
||||||
summary: data[novelData.synopsis],
|
summary: '',
|
||||||
author: data[novelData.author],
|
author: '',
|
||||||
|
status: 'Unknown',
|
||||||
|
chapters: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
novel.genres = data[novelData.genres]
|
for (const key in data) {
|
||||||
.map((index: number) => data[index])
|
const value = data[key];
|
||||||
.join(',');
|
if (typeof value === 'object' && value !== null) {
|
||||||
|
if ('novel_title' in value) {
|
||||||
|
novel.name = data[value.novel_title];
|
||||||
|
novel.cover = data[value.cover];
|
||||||
|
novel.summary = data[value.synopsis];
|
||||||
|
novel.author = data[value.author];
|
||||||
|
novel.genres = (data[value.genres] as number[])
|
||||||
|
.map((genreId: number) => data[genreId])
|
||||||
|
.join(', ');
|
||||||
|
novel.status = value.release_days ? 'Ongoing' : 'Completed';
|
||||||
|
} else if ('chapters_list' in value) {
|
||||||
|
const chaptersFunction = data[value.chapters_list];
|
||||||
|
const chapterMatches = chaptersFunction.match(
|
||||||
|
/'id':((?!_)\w+),'chapter_title':(?:'([^'\\]*(?:\\.[^'\\]*)*)'|(\w+\([^\)]+\))),'chapter_number':(\w+),'required_tier':(\w+),'date_created':([^,]*),/g,
|
||||||
|
);
|
||||||
|
|
||||||
novel.status = data[novelData.release_days] ? 'Ongoing' : 'Completed';
|
if (chapterMatches) {
|
||||||
|
novel.chapters = chapterMatches
|
||||||
|
.map((match: string) => {
|
||||||
|
const [, id, title, , number, requiredTier, dateCreated] =
|
||||||
|
match.match(
|
||||||
|
/'id':(\w+),'chapter_title':(?:'([^'\\]*(?:\\.[^'\\]*)*)'|(\w+\([^\)]+\))),'chapter_number':(\w+),'required_tier':(\w+),'date_created':([^,]*),/,
|
||||||
|
)!;
|
||||||
|
|
||||||
const chapterData = data[data[0].chapters];
|
if (parseInt(requiredTier, 16) === 0) {
|
||||||
const freeChapterData = chapterData.free_chapters;
|
return {
|
||||||
|
name: `Chapter ${parseInt(number, 16)}: ${title || 'Unknown Title'}`,
|
||||||
/** Premium chapters not yet implemented */
|
path: `/viewer/${parseInt(id, 16)}`,
|
||||||
// const premiumChapterData = chapterData.premium_chapters;
|
releaseTime: dateCreated.replace(/^'|'$/g, ''),
|
||||||
|
chapterNumber: parseInt(number, 16),
|
||||||
novel.chapters = data[freeChapterData]
|
};
|
||||||
.map((index: number) => data[index])
|
}
|
||||||
.map((chapter: any) => {
|
return null;
|
||||||
return {
|
})
|
||||||
name: `Chapter ${data[chapter.chapter_number]}: ${data[chapter.chapter_title]}`,
|
.filter(
|
||||||
path: `/viewer/${data[chapter.id]}`,
|
(
|
||||||
releaseTime: data[chapter.date_created],
|
chapter: Plugin.ChapterItem | null,
|
||||||
chapterNumber: data[chapter.chapter_number],
|
): chapter is Plugin.ChapterItem => chapter !== null,
|
||||||
};
|
);
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return novel;
|
return novel;
|
||||||
}
|
}
|
||||||
@@ -106,28 +122,22 @@ class Genesis implements Plugin.PluginBase {
|
|||||||
async parseChapter(chapterPath: string): Promise<string> {
|
async parseChapter(chapterPath: string): Promise<string> {
|
||||||
const url = `${this.site}${chapterPath}/__data.json?x-sveltekit-invalidated=001`;
|
const url = `${this.site}${chapterPath}/__data.json?x-sveltekit-invalidated=001`;
|
||||||
const json = await fetchApi(url).then(r => r.json());
|
const json = await fetchApi(url).then(r => r.json());
|
||||||
|
|
||||||
const nodes = json.nodes;
|
const nodes = json.nodes;
|
||||||
const data = nodes
|
const data = nodes
|
||||||
.filter((node: { type: string }) => node.type === 'data')
|
.filter((node: { type: string }) => node.type === 'data')
|
||||||
.map((node: { data: any }) => node.data)[0];
|
.map((node: { data: any }) => node.data)[0];
|
||||||
|
|
||||||
/** May change in the future */
|
|
||||||
const content = data[19];
|
const content = data[19];
|
||||||
const footnotes = data[data[0].footnotes];
|
const footnotes = data[data[0].footnotes];
|
||||||
|
return content + (footnotes ?? '');
|
||||||
return content + footnotes ?? '';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async searchNovels(
|
async searchNovels(
|
||||||
searchTerm: string,
|
searchTerm: string,
|
||||||
pageNo: number,
|
pageNo: number,
|
||||||
): Promise<Plugin.NovelItem[]> {
|
): Promise<Plugin.SourceNovel[]> {
|
||||||
if (pageNo !== 1) return [];
|
if (pageNo !== 1) return [];
|
||||||
|
|
||||||
const url = `${this.site}/api/search?serialization=All&sort=Popular&title=${searchTerm}`;
|
const url = `${this.site}/api/search?serialization=All&sort=Popular&title=${searchTerm}`;
|
||||||
const json = await fetchApi(url).then(r => r.json());
|
const json = await fetchApi(url).then(r => r.json());
|
||||||
|
|
||||||
return this.parseNovels(json);
|
return this.parseNovels(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user