LighnovelWP update (#900)

* multisrc lightnovelwp:
 - customJs from sources.json
 - Genesis Tls fix werid spaceing and fix copyright

* multisrc lightnovelwp:
 - custom seriesPath for sources
 - added moonlightnovel
 - added sektenovel filter
 - updated README.md

* lightnovelWP: - customJs in file instead of eval

* lightnovelWP: - fix images size

* update daotranslate & remove check for tld
This commit is contained in:
Justin COLLON
2024-04-28 16:05:13 +02:00
committed by GitHub
parent 1ca7009d26
commit 593fa2f206
7 changed files with 489 additions and 21 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

+6
View File
@@ -20,6 +20,12 @@ To add a new source you need to add it to sources.json:
exists in the languages (check folder names in "plugins/")) exists in the languages (check folder names in "plugins/"))
- reverseChapter: if the chapters are in reverse order - reverseChapter: if the chapters are in reverse order
(if the first chapter of the list is 1 set it to false) (if the first chapter of the list is 1 set it to false)
- versionIncrements: needs to be incremented if the url is changed or customJS
is changed or a change to the template affects only this source
- seriesPath: the path to the series page (if the "Novels"/"All Series" button
doesn't go to /series/ (ex: https://site.com/novels/ set it to "/novels/"))
- customJS: custom javascript that will be excuted when getting the text (if
the site has a custom copyright that need to be removed (the cherrio is $))
To add an icon to the source you need to find the icon of the site \ To add an icon to the source you need to find the icon of the site \
(try the favicon of the site (https://site.com/favicon.ico) most of the times it redirects you to an image named something like "cropped-site-32x32.png" try to access "cropped-site.png" or "site.png" if that did not work you can try to access "https://site.com/wp-json/" at the end of this very long file there should be a "site_icon_url" value (try the favicon of the site (https://site.com/favicon.ico) most of the times it redirects you to an image named something like "cropped-site-32x32.png" try to access "cropped-site.png" or "site.png" if that did not work you can try to access "https://site.com/wp-json/" at the end of this very long file there should be a "site_icon_url" value
@@ -0,0 +1,296 @@
{
"filters": {
"genre[]": {
"type": "Checkbox",
"label": "Genre",
"value": [],
"options": [
{
"label": "Action",
"value": "action"
},
{
"label": "Adult",
"value": "adult"
},
{
"label": "Adventure",
"value": "adventure"
},
{
"label": "Amnesia",
"value": "amnesia"
},
{
"label": "Childcare",
"value": "childcare"
},
{
"label": "Comedy",
"value": "comedy"
},
{
"label": "Drama",
"value": "drama"
},
{
"label": "Fantasy",
"value": "fantasy"
},
{
"label": "fantasy of",
"value": "fantasy-of"
},
{
"label": "Fate",
"value": "fate"
},
{
"label": "Fiction",
"value": "fiction"
},
{
"label": "Gender Bender",
"value": "gender-bender"
},
{
"label": "Harem",
"value": "harem"
},
{
"label": "Historical",
"value": "historical"
},
{
"label": "Horror",
"value": "horror"
},
{
"label": "Idol",
"value": "idol"
},
{
"label": "Josei",
"value": "josei"
},
{
"label": "Magic",
"value": "magic"
},
{
"label": "Martial Arts",
"value": "martial-arts"
},
{
"label": "Mature",
"value": "mature"
},
{
"label": "Mecha",
"value": "mecha"
},
{
"label": "Modern",
"value": "modern"
},
{
"label": "Mystery",
"value": "mystery"
},
{
"label": "Psychological",
"value": "psychological"
},
{
"label": "Rebirth",
"value": "rebirth"
},
{
"label": "Revenge",
"value": "revenge"
},
{
"label": "Rofan",
"value": "rofan"
},
{
"label": "Romance",
"value": "romance"
},
{
"label": "Romance Fantasy",
"value": "romance-fantasy"
},
{
"label": "Romantic Comedy",
"value": "romantic-comedy"
},
{
"label": "Royalty",
"value": "royalty"
},
{
"label": "School Life",
"value": "school-life"
},
{
"label": "Sci-fi",
"value": "sci-fi"
},
{
"label": "Shoujo",
"value": "shoujo"
},
{
"label": "Shounen",
"value": "shounen"
},
{
"label": "Shounen Ai",
"value": "shounen-ai"
},
{
"label": "Slice of Life",
"value": "slice-of-life"
},
{
"label": "Smut",
"value": "smut"
},
{
"label": "Supernatural",
"value": "supernatural"
},
{
"label": "Suspense",
"value": "suspense"
},
{
"label": "Tragedy",
"value": "tragedy"
},
{
"label": "Transmigration",
"value": "transmigration"
},
{
"label": "Xianxia",
"value": "xianxia"
},
{
"label": "Xuanhuan",
"value": "xuanhuan"
},
{
"label": "Yaoi",
"value": "yaoi"
},
{
"label": "Younger Man",
"value": "younger-man"
},
{
"label": "Yuri",
"value": "yuri"
}
]
},
"type[]": {
"type": "Checkbox",
"label": "Type",
"value": [],
"options": [
{
"label": "Chinese",
"value": "chinese"
},
{
"label": "Indonesian",
"value": "indonesian"
},
{
"label": "Japanese",
"value": "japanese"
},
{
"label": "Korean",
"value": "korean"
},
{
"label": "Original",
"value": "original"
},
{
"label": "Web Novel",
"value": "web-novel"
},
{
"label": "Web Novel (KR)",
"value": "web-novel-kr"
},
{
"label": "Webnovel",
"value": "webnovel"
}
]
},
"status": {
"type": "Picker",
"label": "Status",
"value": "",
"options": [
{
"label": "All",
"value": ""
},
{
"label": "Ongoing",
"value": "ongoing"
},
{
"label": "Hiatus",
"value": "hiatus"
},
{
"label": "Completed",
"value": "completed"
}
]
},
"order": {
"type": "Picker",
"label": "Order by",
"value": "",
"options": [
{
"label": "Default",
"value": ""
},
{
"label": "A-Z",
"value": "title"
},
{
"label": "Z-A",
"value": "titlereverse"
},
{
"label": "Latest Update",
"value": "update"
},
{
"label": "Latest Added",
"value": "latest"
},
{
"label": "Popular",
"value": "popular"
},
{
"label": "Rating",
"value": "rating"
}
]
}
}
}
@@ -0,0 +1,152 @@
{
"filters": {
"genre[]": {
"type": "Checkbox",
"label": "Genre",
"value": [],
"options": [
{
"label": "Action",
"value": "action"
},
{
"label": "Adventure",
"value": "adventure"
},
{
"label": "Comedy",
"value": "comedy"
},
{
"label": "Drama",
"value": "drama"
},
{
"label": "Fantasy",
"value": "fantasy"
},
{
"label": "Harem",
"value": "harem"
},
{
"label": "Josei",
"value": "josei"
},
{
"label": "Martial Arts",
"value": "martial-arts"
},
{
"label": "Mature",
"value": "mature"
},
{
"label": "Psychological",
"value": "psychological"
},
{
"label": "Romance",
"value": "romance"
},
{
"label": "School Life",
"value": "school-life"
},
{
"label": "Shounen",
"value": "shounen"
},
{
"label": "Slice of Life",
"value": "slice-of-life"
},
{
"label": "Supernatural",
"value": "supernatural"
},
{
"label": "Wuxia",
"value": "wuxia"
},
{
"label": "Xuanhuan",
"value": "xuanhuan"
}
]
},
"type[]": {
"type": "Checkbox",
"label": "Type",
"value": [],
"options": [
{
"label": "Light Novel (JP)",
"value": "light-novel-jp"
},
{
"label": "Web Novel",
"value": "web-novel"
}
]
},
"status": {
"type": "Picker",
"label": "Status",
"value": "",
"options": [
{
"label": "All",
"value": ""
},
{
"label": "Ongoing",
"value": "ongoing"
},
{
"label": "Hiatus",
"value": "hiatus"
},
{
"label": "Completed",
"value": "completed"
}
]
},
"order": {
"type": "Picker",
"label": "Order by",
"value": "",
"options": [
{
"label": "Default",
"value": ""
},
{
"label": "A-Z",
"value": "title"
},
{
"label": "Z-A",
"value": "titlereverse"
},
{
"label": "Latest Update",
"value": "update"
},
{
"label": "Latest Added",
"value": "latest"
},
{
"label": "Popular",
"value": "popular"
},
{
"label": "Rating",
"value": "rating"
}
]
}
}
}
+4 -1
View File
@@ -27,7 +27,10 @@ const generator = function generator(source: LightNovelWPMetadata) {
); );
const pluginScript = ` const pluginScript = `
${LightNovelWPTemplate} ${LightNovelWPTemplate.replace(
'// CustomJS HERE',
source.options?.customJs || '',
)}
const plugin = new LightNovelWPPlugin(${JSON.stringify(source)}); const plugin = new LightNovelWPPlugin(${JSON.stringify(source)});
export default plugin; export default plugin;
`.trim(); `.trim();
+17 -13
View File
@@ -14,7 +14,8 @@
"sourceName": "ملوك الروايات", "sourceName": "ملوك الروايات",
"options": { "options": {
"lang": "Arabic", "lang": "Arabic",
"reverseChapters": true "reverseChapters": true,
"customJs": "let ignore = $('article > style').text().trim().split(',');ignore.push(...(ignore.pop()?.match(/^\\.\\w+/) || []));ignore.map(tag => $(`p${tag}`).remove());"
} }
}, },
{ {
@@ -46,12 +47,12 @@
}, },
{ {
"id": "daotranslate", "id": "daotranslate",
"sourceSite": "https://daotranslate.us/", "sourceSite": "https://daotranslate.net/",
"sourceName": "DaoTranslate", "sourceName": "DaoTranslate",
"options": { "options": {
"lang": "English", "lang": "English",
"reverseChapters": true, "reverseChapters": true,
"versionIncrements": 1 "versionIncrements": 2
} }
}, },
{ {
@@ -97,7 +98,9 @@
"sourceName": "GenesisTls", "sourceName": "GenesisTls",
"options": { "options": {
"lang": "English", "lang": "English",
"reverseChapters": false "reverseChapters": false,
"versionIncrements": 1,
"customJs": "$('.genesistls-watermark').remove();$('.epcontent p').each((i, el) => { if ($(el).html() === ' ') $(el).remove(); });"
} }
}, },
{ {
@@ -136,15 +139,6 @@
"reverseChapters": false "reverseChapters": false
} }
}, },
{
"id": "bacalightnovel",
"sourceSite": "https://bacalightnovel.co/",
"sourceName": "Baca Light Novel",
"options": {
"lang": "Indonesian",
"reverseChapters": true
}
},
{ {
"id": "sektenovel", "id": "sektenovel",
"sourceSite": "https://sektenovel.web.id/", "sourceSite": "https://sektenovel.web.id/",
@@ -162,5 +156,15 @@
"lang": "English", "lang": "English",
"reverseChapters": true "reverseChapters": true
} }
},
{
"id": "moonlightnovel",
"sourceSite": "https://moonlightnovel.com/",
"sourceName": "Moonlight Novels",
"options": {
"lang": "English",
"reverseChapters": true,
"seriesPath": "/novels/"
}
} }
] ]
+14 -7
View File
@@ -9,6 +9,8 @@ interface LightNovelWPOptions {
reverseChapters?: boolean; reverseChapters?: boolean;
lang?: string; lang?: string;
versionIncrements?: number; versionIncrements?: number;
seriesPath?: string;
customJs?: string;
} }
export interface LightNovelWPMetadata { export interface LightNovelWPMetadata {
@@ -35,12 +37,15 @@ class LightNovelWPPlugin implements Plugin.PluginBase {
this.site = metadata.sourceSite; this.site = metadata.sourceSite;
const versionIncrements = metadata.options?.versionIncrements || 0; const versionIncrements = metadata.options?.versionIncrements || 0;
this.version = `1.0.${4 + versionIncrements}`; this.version = `1.0.${4 + versionIncrements}`;
this.options = metadata.options; this.options = metadata.options ?? ({} as LightNovelWPOptions);
this.filters = metadata.filters satisfies Filters; this.filters = metadata.filters satisfies Filters;
} }
getHostname(url: string): string { getHostname(url: string): string {
return url.split('/')[2]; url = url.split('/')[2];
let url_parts = url.split('.');
url_parts.pop(); // remove TLD
return url_parts.join('.');
} }
async getCheerio(url: string, search: boolean): Promise<CheerioAPI> { async getCheerio(url: string, search: boolean): Promise<CheerioAPI> {
@@ -90,7 +95,8 @@ class LightNovelWPPlugin implements Plugin.PluginBase {
showLatestNovels, showLatestNovels,
}: Plugin.PopularNovelsOptions<typeof this.filters>, }: Plugin.PopularNovelsOptions<typeof this.filters>,
): Promise<Plugin.NovelItem[]> { ): Promise<Plugin.NovelItem[]> {
let url = this.site + '/series/?page=' + pageNo; const seriesPath = this.options?.seriesPath ?? '/series/';
let url = this.site + seriesPath + '?page=' + pageNo;
if (!filters) filters = {}; if (!filters) filters = {};
if (showLatestNovels) url += '&order=latest'; if (showLatestNovels) url += '&order=latest';
for (const key in filters) { for (const key in filters) {
@@ -249,10 +255,11 @@ class LightNovelWPPlugin implements Plugin.PluginBase {
async parseChapter(chapterPath: string): Promise<string> { async parseChapter(chapterPath: string): Promise<string> {
const $ = await this.getCheerio(this.site + chapterPath, false); const $ = await this.getCheerio(this.site + chapterPath, false);
if (this.id == 'kolnovel') { try {
let ignore = $('article > style').text().trim().split(','); // CustomJS HERE
ignore.push(...(ignore.pop()?.match(/^\.\w+/) || [])); } catch (error) {
ignore.map(tag => $(`p${tag}`).remove()); console.error('Error executing customJs:', error);
throw error;
} }
return ( return (
$('.epcontent p') $('.epcontent p')