multisrc update (#1238)

* Madara:
- added sources filters
- new sources (Coral Boutique EN, Pastel Tales EN)
- get filters in js
- update README.md

* LighnovelWP:
- added sources filters
- new source (Namevt TR)
- get filters in js
- update README.md
This commit is contained in:
Justin COLLON
2024-10-24 03:43:50 +02:00
committed by GitHub
parent 363846a4f1
commit f9db96d74e
19 changed files with 1509 additions and 70 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 555 B

+18 -7
View File
@@ -1,4 +1,7 @@
# Compatiblity # Madara multisrc generator
## Compatiblity
### This generator is for most sites that uses the LightNovel WordPress Theme: https://themesia.com/lightnovel-wordpress-theme/ ### This generator is for most sites that uses the LightNovel WordPress Theme: https://themesia.com/lightnovel-wordpress-theme/
it should work for all sites that uses this theme (highest version tested: 1.1.5) it should work for all sites that uses this theme (highest version tested: 1.1.5)
@@ -8,12 +11,14 @@ to know the name and version of the theme you can enter the url in : [WP Theme D
or you can check the version by adding "/wp-content/themes/lightnovel/style.css" or you can check the version by adding "/wp-content/themes/lightnovel/style.css"
to the site url and check the version in the file to the site url and check the version in the file
## Add a new source
### sources.json
## ADD A NEW SOURCE
To add a new source you need to add it to sources.json: To add a new source you need to add it to sources.json:
- id: the id of the source (something unique) - id: the id of the source (something unique)
- sourceName: the name of the source (the name that will be displayed in the app) - sourceName: the name of the source (you can use the value of "name" in "https://site.com/wp-json/" if it exists)
- sourceSite: the site url - sourceSite: the site url
- options: the options of the source - options: the options of the source
- lang: the language of the source (default: "English") (check that the language - lang: the language of the source (default: "English") (check that the language
@@ -27,12 +32,18 @@ To add a new source you need to add it to sources.json:
- customJS: custom javascript that will be excuted when getting the text (if - 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 $)) 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 \ ### icon
To add an icon to the source you can just run `npm run icons` to generate all icons (make sure `npm run generate` works on your machine)
Or you can manualy 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
) (don't forget to convert it to png) ) (don't forget to convert it to png)
and add it to the folder "icons/multisrc/lightnovelwp" named as the id of the source and add it to the folder "public/static/multisrc/madara/{sourceID}/icon.png"
To add filters to a source you need to run the script "get_filters.ts" \ ### filters
(./node_modules/.bin/ts-node scripts/multisrc/lightnovelwp/get_filters.ts
To add filters to a source you need to run the script "get_filters.js" \
(`npx node scripts/multisrc/madara/get_filters.js`
(if you are at the root of the project) (and you have ran "npm install" before)) (if you are at the root of the project) (and you have ran "npm install" before))
and follow the instructions (url is easier and faster but sometimes it doesn't work) and follow the instructions (url is easier and faster but sometimes it doesn't work)
@@ -0,0 +1,232 @@
{
"filters": {
"genre[]": {
"type": "Checkbox",
"label": "Genre",
"value": [],
"options": [
{
"label": "Academy",
"value": "academy"
},
{
"label": "Action",
"value": "action"
},
{
"label": "Adult",
"value": "adult"
},
{
"label": "Adventure",
"value": "adventure"
},
{
"label": "Apocalypse",
"value": "apocalypse"
},
{
"label": "Comedy",
"value": "comedy"
},
{
"label": "Cyberpunk",
"value": "cyberpunk"
},
{
"label": "Drama",
"value": "drama"
},
{
"label": "Ecchi",
"value": "ecchi"
},
{
"label": "Fantasy",
"value": "fantasy"
},
{
"label": "Fusion",
"value": "fusion"
},
{
"label": "Game World",
"value": "game-world"
},
{
"label": "Harem",
"value": "harem"
},
{
"label": "Martial Arts",
"value": "martial-arts"
},
{
"label": "Mature",
"value": "mature"
},
{
"label": "Medieval",
"value": "medieval"
},
{
"label": "Misunderstandings",
"value": "misunderstandings"
},
{
"label": "Modern",
"value": "modern"
},
{
"label": "Mystery",
"value": "mystery"
},
{
"label": "Obsession",
"value": "obsession"
},
{
"label": "Possession",
"value": "possession"
},
{
"label": "Psychological",
"value": "psychological"
},
{
"label": "Regression",
"value": "regression"
},
{
"label": "Regret",
"value": "regret"
},
{
"label": "Reincarnation",
"value": "reincarnation"
},
{
"label": "Romance",
"value": "romance"
},
{
"label": "School Life",
"value": "school-life"
},
{
"label": "Sci-Fi",
"value": "sci-fi"
},
{
"label": "Seinen",
"value": "seinen"
},
{
"label": "Shounen",
"value": "shounen"
},
{
"label": "Slice of Life",
"value": "slice-of-life"
},
{
"label": "Supernatural",
"value": "supernatural"
},
{
"label": "Tragedy",
"value": "tragedy"
},
{
"label": "Transmigration",
"value": "transmigration"
},
{
"label": "Wuxia",
"value": "wuxia"
}
]
},
"type[]": {
"type": "Checkbox",
"label": "Type",
"value": [],
"options": [
{
"label": "Chinese Novel",
"value": "chinese-novel"
},
{
"label": "Japanese Novel",
"value": "japanese-novel"
},
{
"label": "Korean Novel",
"value": "korean-novel"
},
{
"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"
}
]
}
}
}
@@ -0,0 +1,160 @@
{
"filters": {
"genre[]": {
"type": "Checkbox",
"label": "Türler",
"value": [],
"options": [
{
"label": "Aksiyon",
"value": "aksiyon"
},
{
"label": "Bilimkurgu",
"value": "bilimkurgu"
},
{
"label": "Doğaüstü",
"value": "dogaustu"
},
{
"label": "Dram",
"value": "dram"
},
{
"label": "Ecchi",
"value": "ecchi"
},
{
"label": "Fantastik",
"value": "fantastik"
},
{
"label": "Fantezi",
"value": "fantezi"
},
{
"label": "Gizem",
"value": "gizem"
},
{
"label": "Harem",
"value": "harem"
},
{
"label": "Komedi",
"value": "komedi"
},
{
"label": "Macera",
"value": "macera"
},
{
"label": "Mecha",
"value": "mecha"
},
{
"label": "Okul hayatı",
"value": "okul-hayati"
},
{
"label": "Romantik",
"value": "romantik"
},
{
"label": "Seinen",
"value": "seinen"
},
{
"label": "Shoujo",
"value": "shoujo"
},
{
"label": "Shounen",
"value": "shounen"
},
{
"label": "Trajedi",
"value": "trajedi"
},
{
"label": "Yetişkin",
"value": "yetiskin"
}
]
},
"type[]": {
"type": "Checkbox",
"label": "Yazım Şekli",
"value": [],
"options": [
{
"label": "Light Novel (JP)",
"value": "light-novel-jp"
},
{
"label": "Web Novel",
"value": "web-novel"
}
]
},
"status": {
"type": "Picker",
"label": "Durum",
"value": "",
"options": [
{
"label": "Tümü",
"value": ""
},
{
"label": "Devam Ediyor",
"value": "ongoing"
},
{
"label": "Ara Verildi",
"value": "hiatus"
},
{
"label": "Tamamlandı",
"value": "completed"
}
]
},
"order": {
"type": "Picker",
"label": "Sıralama",
"value": "",
"options": [
{
"label": "Varsayılan",
"value": ""
},
{
"label": "A-Z",
"value": "title"
},
{
"label": "Z-A",
"value": "titlereverse"
},
{
"label": "Son Güncellemeler",
"value": "update"
},
{
"label": "Son Eklenenler",
"value": "latest"
},
{
"label": "Popüler",
"value": "popular"
},
{
"label": "Puanlama",
"value": "rating"
}
]
}
}
}
@@ -1,10 +1,16 @@
import * as fs from 'fs'; import * as fs from 'fs';
import * as cheerio from 'cheerio'; import * as cheerio from 'cheerio';
import * as path from 'path'; import * as path from 'path';
import * as readline from 'readline';
import process from 'process';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
function getFilters(name: string, html: string) { function getFilters(name, html) {
const $: cheerio.CheerioAPI = cheerio.load(html); const $ = cheerio.load(html);
const filters: any = { const filters = {
filters: { filters: {
'genre[]': { 'genre[]': {
type: 'Checkbox', type: 'Checkbox',
@@ -36,27 +42,29 @@ function getFilters(name: string, html: string) {
const filtersContainer = $('div.quickfilter').find('ul'); const filtersContainer = $('div.quickfilter').find('ul');
filtersContainer.each((i, el) => { filtersContainer.each((i, el) => {
const filterName = Object.keys(filters.filters)[i]; const filterName = Object.keys(filters.filters)[i];
filters.filters[filterName].label = $(el) if (filterName) {
.prev() filters.filters[filterName].label = $(el)
.contents() .prev()
.first() .contents()
.text() .first()
.trim(); .text()
$(el) .trim();
.find('li') $(el)
.each((j, li) => { .find('li')
filters.filters[filterName].options.push({ .each((j, li) => {
label: $(li).text().trim(), filters.filters[filterName].options.push({
value: decodeURI($(li).find('input').attr('value') || ''), label: $(li).text().trim(),
value: decodeURI($(li).find('input').attr('value') || ''),
});
}); });
}); }
}); });
if ( if (
filters.filters['m_orderby'].options.length == 0 || filters.filters['genre[]'].options.length == 0 ||
filters.filters['status[]'].options.length == 0 || filters.filters['type[]'].options.length == 0 ||
filters.filters['adult'].options.length == 0 || filters.filters['status'].options.length == 0 ||
filters.filters['genre[]'].options.length == 0 filters.filters['order'].options.length == 0
) { ) {
console.error( console.error(
`🚨Error in filters for ${name} please fix manually (${path.join(__dirname, 'filters', name + '.json')})🚨`, `🚨Error in filters for ${name} please fix manually (${path.join(__dirname, 'filters', name + '.json')})🚨`,
@@ -70,7 +78,7 @@ function getFilters(name: string, html: string) {
console.log(`✅Filters created successfully for ${name}✅`); console.log(`✅Filters created successfully for ${name}✅`);
} }
async function getFiltersFromURL(name: string, url: string) { async function getFiltersFromURL(name, url) {
const response = await fetch(url + '/series/'); const response = await fetch(url + '/series/');
if (!response.ok) { if (!response.ok) {
throw new Error( throw new Error(
@@ -82,49 +90,50 @@ async function getFiltersFromURL(name: string, url: string) {
getFilters(name, html); getFilters(name, html);
} catch (e) { } catch (e) {
console.error('Error while getting filters from', url); console.error('Error while getting filters from', url);
console.error('(' + e + ')');
} }
} }
async function askGetFilter() { async function askGetFilter() {
const readline = require('readline').createInterface({ const rl = readline.createInterface({
input: process.stdin, input: process.stdin,
output: process.stdout, output: process.stdout,
}); });
const EREASE_PREV_LINE = '\x1b[1A\r\x1b[2K'; const EREASE_PREV_LINE = '\x1b[1A\r\x1b[2K';
await readline.question( await rl.question(
'Enter the id of the site (same one as in sources.json): ', 'Enter the id of the site (same one as in sources.json): ',
async (name: string) => { async name => {
await readline.question( await rl.question(
EREASE_PREV_LINE + EREASE_PREV_LINE +
"Do you want to get the filters from a URL or the html text? (if url dosen't work try html) (url/html): ", "Do you want to get the filters from a URL or the html text? (if url dosen't work try html) (url/html): ",
async (method: string) => { async method => {
if (method.toLowerCase() === 'url') { if (method.toLowerCase() === 'url') {
const sources = JSON.parse( const sources = JSON.parse(
fs.readFileSync(path.join(__dirname, 'sources.json'), 'utf-8'), fs.readFileSync(path.join(__dirname, 'sources.json'), 'utf-8'),
); );
const source = sources.find((s: any) => s.id === name); const source = sources.find(s => s.id === name);
if (source && source.sourceSite) { if (source && source.sourceSite) {
console.log('Getting filters from', source.sourceSite); console.log('Getting filters from', source.sourceSite);
try { try {
await getFiltersFromURL(name, source.sourceSite); await getFiltersFromURL(name, source.sourceSite);
} catch (e: any) { } catch (e) {
console.error( console.error(
'Error while getting filters from', 'Error while getting filters from',
source.sourceSite, source.sourceSite,
); );
console.log(e.message || e); console.log(e.message || e);
} }
readline.close(); rl.close();
} else { } else {
await readline.question( await rl.question(
EREASE_PREV_LINE + EREASE_PREV_LINE +
'Enter the URL (same one as in sources.json): ', 'Enter the URL (same one as in sources.json): ',
async (url: string) => { async url => {
readline.close(); rl.close();
try { try {
await getFiltersFromURL(name, url); await getFiltersFromURL(name, url);
} catch (e: any) { } catch (e) {
console.error('Error while getting filters from', url); console.error('Error while getting filters from', url);
console.log(e.message || e); console.log(e.message || e);
} }
@@ -135,15 +144,15 @@ async function askGetFilter() {
process.stdout.write( process.stdout.write(
EREASE_PREV_LINE + EREASE_PREV_LINE +
`Enter the html text from the page at {sourceSite}/series (at the end press ENTER then press CTRL+C) `Enter the html text from the page at {sourceSite}/series (at the end press ENTER then press CTRL+C)
(to make it faster you can run \`$(\"div.quickfilter\").parent().html()\` in the console to get only the important html part): `, (to make it faster you can run \`$("div.quickfilter").parent().html()\` in the console to get only the important html part): `,
); );
let html = ''; let html = '';
readline.on('SIGINT', () => { rl.on('SIGINT', () => {
console.log('Stopeed reading input, creating filters file'); console.log('Stopeed reading input, creating filters file');
getFilters(name, html); getFilters(name, html);
readline.close(); rl.close();
}); });
readline.on('line', (line: string) => { rl.on('line', line => {
html += line + '\n'; html += line + '\n';
}); });
} }
@@ -213,7 +213,18 @@
"sourceSite": "https://arcanetranslations.com/", "sourceSite": "https://arcanetranslations.com/",
"sourceName": "Arcane Translations", "sourceName": "Arcane Translations",
"options": { "options": {
"reverseChapters": true,
"lang": "English" "lang": "English"
} }
},
{
"id": "namevt",
"sourceSite": "https://namevt.com/",
"sourceName": "Namevt",
"options": {
"reverseChapters": true,
"seriesPath": "/seri/",
"lang": "Turkish"
}
} }
] ]
+19 -7
View File
@@ -1,4 +1,7 @@
# Compatiblity # Madara multisrc generator
## Compatiblity
### This generator is for most sites that uses the Madara WordPress Theme: https://mangabooth.com/ ### This generator is for most sites that uses the Madara WordPress Theme: https://mangabooth.com/
it should work for all sites that uses this theme it should work for all sites that uses this theme
@@ -7,10 +10,12 @@ to know the name and version of the theme you can enter the url in : [WP Theme D
or you can check the version by adding "/wp-content/themes/madara/style.css" or you can check the version by adding "/wp-content/themes/madara/style.css"
to the site url and check the version in the file to the site url and check the version in the file
## Add a new source
### sources.json
## ADD A NEW SOURCE
To add a new source you need to add it to sources.json: To add a new source you need to add it to sources.json:
- id: the id of the source (something unique) - id: the id of the source (something unique)
- sourceName: the name of the source (you can use the value of "name" in "https://site.com/wp-json/" if it exists) - sourceName: the name of the source (you can use the value of "name" in "https://site.com/wp-json/" if it exists)
- sourceSite: the site url - sourceSite: the site url
@@ -18,13 +23,20 @@ To add a new source you need to add it to sources.json:
- lang: the language of the source (default: "English") (check that the language - lang: the language of the source (default: "English") (check that the language
exists in the languages (check folder names in "plugins/")) exists in the languages (check folder names in "plugins/"))
- useNewChapterEndpoint: if the source uses the new chapter endpoint - useNewChapterEndpoint: if the source uses the new chapter endpoint
- versionIncrements: needs to be updated everytime the site url is updated
To add an icon to the source you need to find the icon of the site \ ### icon
(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
To add an icon to the source you can just run `npm run icons` to generate all icons (make sure `npm run generate` works on your machine)
Or you can manualy 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
) (don't forget to convert it to png) ) (don't forget to convert it to png)
and add it to the folder "icons/multisrc/madara" named as the id of the source and add it to the folder "public/static/multisrc/madara/{sourceID}/icon.png"
To add filters to a source you need to run the script "get_filters.ts" \ ### filters
(./node_modules/.bin/ts-node scripts/multisrc/madara/get_filters.ts
To add filters to a source you need to run the script "get_filters.js" \
(`npx node scripts/multisrc/madara/get_filters.js`
(if you are at the root of the project) (and you have ran "npm install" before)) (if you are at the root of the project) (and you have ran "npm install" before))
and follow the instructions (url is easier and faster but sometimes it doesn't work) and follow the instructions (url is easier and faster but sometimes it doesn't work)
@@ -0,0 +1,196 @@
{
"filters": {
"genre[]": {
"type": "Checkbox",
"label": "Genre",
"value": [],
"options": [
{
"label": "Action",
"value": "action"
},
{
"label": "Adventure",
"value": "adventure"
},
{
"label": "Comedy",
"value": "comedy"
},
{
"label": "Dark",
"value": "dark"
},
{
"label": "Drama",
"value": "drama"
},
{
"label": "Fantasy",
"value": "fantasy"
},
{
"label": "Harem",
"value": "harem"
},
{
"label": "Horror",
"value": "horror"
},
{
"label": "Isekai",
"value": "isekai"
},
{
"label": "Josei",
"value": "josei"
},
{
"label": "Mature",
"value": "mature"
},
{
"label": "Mystery",
"value": "mystery"
},
{
"label": "Psychological",
"value": "psychological"
},
{
"label": "R-15",
"value": "r-15"
},
{
"label": "R-19",
"value": "r-19"
},
{
"label": "Regression",
"value": "regression"
},
{
"label": "Romance",
"value": "romance"
},
{
"label": "Shoujo",
"value": "shoujo"
},
{
"label": "Supernatural",
"value": "supernatural"
},
{
"label": "Tragedy",
"value": "tragedy"
},
{
"label": "Transmigration",
"value": "transmigration"
}
]
},
"op": {
"type": "Switch",
"label": "having all selected genres",
"value": false
},
"author": {
"type": "Text",
"label": "Author",
"value": ""
},
"artist": {
"type": "Text",
"label": "Artist",
"value": ""
},
"release": {
"type": "Text",
"label": "Year of Released",
"value": ""
},
"adult": {
"type": "Picker",
"label": "Adult content",
"value": "",
"options": [
{
"label": "All",
"value": ""
},
{
"label": "None adult content",
"value": "0"
},
{
"label": "Only adult content",
"value": "1"
}
]
},
"status[]": {
"type": "Checkbox",
"label": "Status",
"value": [],
"options": [
{
"label": "OnGoing",
"value": "on-going"
},
{
"label": "Completed",
"value": "end"
},
{
"label": "Canceled",
"value": "canceled"
},
{
"label": "On Hold",
"value": "on-hold"
},
{
"label": "Upcoming",
"value": "upcoming"
}
]
},
"m_orderby": {
"type": "Picker",
"label": "Order by",
"value": "",
"options": [
{
"label": "Relevance",
"value": ""
},
{
"label": "Latest",
"value": "latest"
},
{
"label": "A-Z",
"value": "alphabet"
},
{
"label": "Rating",
"value": "rating"
},
{
"label": "Trending",
"value": "trending"
},
{
"label": "Most Views",
"value": "views"
},
{
"label": "New",
"value": "new-manga"
}
]
}
}
}
@@ -0,0 +1,168 @@
{
"filters": {
"genre[]": {
"type": "Checkbox",
"label": "Genre",
"value": [],
"options": [
{
"label": "Action",
"value": "action"
},
{
"label": "Adult",
"value": "adult"
},
{
"label": "Adventure",
"value": "adventure"
},
{
"label": "BL",
"value": "bl"
},
{
"label": "Comedy",
"value": "comedy"
},
{
"label": "Drama",
"value": "drama"
},
{
"label": "Fantasy",
"value": "fantasy"
},
{
"label": "GL",
"value": "gl"
},
{
"label": "Mystery",
"value": "mystery"
},
{
"label": "Romance",
"value": "romance"
},
{
"label": "School Life",
"value": "school-life"
},
{
"label": "Slice of Life",
"value": "slice-of-life"
},
{
"label": "Supernatural",
"value": "supernatural"
},
{
"label": "Tragedy",
"value": "tragedy"
}
]
},
"op": {
"type": "Switch",
"label": "having all selected genres",
"value": false
},
"author": {
"type": "Text",
"label": "Author",
"value": ""
},
"artist": {
"type": "Text",
"label": "Artist",
"value": ""
},
"release": {
"type": "Text",
"label": "Year of Released",
"value": ""
},
"adult": {
"type": "Picker",
"label": "Adult content",
"value": "",
"options": [
{
"label": "All",
"value": ""
},
{
"label": "None adult content",
"value": "0"
},
{
"label": "Only adult content",
"value": "1"
}
]
},
"status[]": {
"type": "Checkbox",
"label": "Status",
"value": [],
"options": [
{
"label": "OnGoing",
"value": "on-going"
},
{
"label": "Completed",
"value": "end"
},
{
"label": "Canceled",
"value": "canceled"
},
{
"label": "On Hold",
"value": "on-hold"
},
{
"label": "Upcoming",
"value": "upcoming"
}
]
},
"m_orderby": {
"type": "Picker",
"label": "Order by",
"value": "",
"options": [
{
"label": "Relevance",
"value": ""
},
{
"label": "Latest",
"value": "latest"
},
{
"label": "A-Z",
"value": "alphabet"
},
{
"label": "Rating",
"value": "rating"
},
{
"label": "Trending",
"value": "trending"
},
{
"label": "Most Views",
"value": "views"
},
{
"label": "New",
"value": "new-manga"
}
]
}
}
}
@@ -0,0 +1,192 @@
{
"filters": {
"genre[]": {
"type": "Checkbox",
"label": "Genre",
"value": [],
"options": [
{
"label": "Action",
"value": "action"
},
{
"label": "Adult",
"value": "adult"
},
{
"label": "Adventure",
"value": "adventure"
},
{
"label": "Comedy",
"value": "comedy"
},
{
"label": "Drama",
"value": "drama"
},
{
"label": "Fantasy",
"value": "fantasy"
},
{
"label": "Gender Bender",
"value": "gender-bender"
},
{
"label": "Harem",
"value": "harem"
},
{
"label": "Historical",
"value": "historical"
},
{
"label": "Horror",
"value": "horror"
},
{
"label": "Mature",
"value": "mature"
},
{
"label": "Mystery",
"value": "mystery"
},
{
"label": "Psychological",
"value": "psychological"
},
{
"label": "Romance",
"value": "romance"
},
{
"label": "School Life",
"value": "school-life"
},
{
"label": "Sci-fi",
"value": "sci-fi"
},
{
"label": "Slice of Life",
"value": "slice-of-life"
},
{
"label": "Smut",
"value": "smut"
},
{
"label": "Supernatural",
"value": "supernatural"
},
{
"label": "Tragedy",
"value": "tragedy"
}
]
},
"op": {
"type": "Switch",
"label": "having all selected genres",
"value": false
},
"author": {
"type": "Text",
"label": "Author",
"value": ""
},
"artist": {
"type": "Text",
"label": "Artist",
"value": ""
},
"release": {
"type": "Text",
"label": "Year of Released",
"value": ""
},
"adult": {
"type": "Picker",
"label": "Adult content",
"value": "",
"options": [
{
"label": "All",
"value": ""
},
{
"label": "None adult content",
"value": "0"
},
{
"label": "Only adult content",
"value": "1"
}
]
},
"status[]": {
"type": "Checkbox",
"label": "Status",
"value": [],
"options": [
{
"label": "OnGoing",
"value": "on-going"
},
{
"label": "Completed",
"value": "end"
},
{
"label": "Canceled",
"value": "canceled"
},
{
"label": "On Hold",
"value": "on-hold"
},
{
"label": "Upcoming",
"value": "upcoming"
}
]
},
"m_orderby": {
"type": "Picker",
"label": "Order by",
"value": "",
"options": [
{
"label": "Relevance",
"value": ""
},
{
"label": "Latest",
"value": "latest"
},
{
"label": "A-Z",
"value": "alphabet"
},
{
"label": "Rating",
"value": "rating"
},
{
"label": "Trending",
"value": "trending"
},
{
"label": "Most Views",
"value": "views"
},
{
"label": "New",
"value": "new-manga"
}
]
}
}
}
+300
View File
@@ -0,0 +1,300 @@
{
"filters": {
"genre[]": {
"type": "Checkbox",
"label": "Genre",
"value": [],
"options": [
{
"label": "Action",
"value": "action"
},
{
"label": "Adult",
"value": "adult"
},
{
"label": "Adventure",
"value": "adventure"
},
{
"label": "Anime",
"value": "anime"
},
{
"label": "Cartoon",
"value": "cartoon"
},
{
"label": "Comedy",
"value": "comedy"
},
{
"label": "Comic",
"value": "comic"
},
{
"label": "Cooking",
"value": "cooking"
},
{
"label": "Detective",
"value": "detective"
},
{
"label": "Doujinshi",
"value": "doujinshi"
},
{
"label": "Drama",
"value": "drama"
},
{
"label": "Ecchi",
"value": "ecchi"
},
{
"label": "Fantasy",
"value": "fantasy"
},
{
"label": "Gender Bender",
"value": "gender-bender"
},
{
"label": "Harem",
"value": "harem"
},
{
"label": "Historical",
"value": "historical"
},
{
"label": "Horror",
"value": "horror"
},
{
"label": "Josei",
"value": "josei"
},
{
"label": "Live action",
"value": "live-action"
},
{
"label": "Manga",
"value": "manga"
},
{
"label": "Manhua",
"value": "manhua"
},
{
"label": "Manhwa",
"value": "manhwa"
},
{
"label": "Martial Arts",
"value": "martial-arts"
},
{
"label": "Mature",
"value": "mature"
},
{
"label": "Mecha",
"value": "mecha"
},
{
"label": "Mystery",
"value": "mystery"
},
{
"label": "One shot",
"value": "one-shot"
},
{
"label": "Psychological",
"value": "psychological"
},
{
"label": "Romance",
"value": "romance"
},
{
"label": "School Life",
"value": "school-life"
},
{
"label": "Sci-fi",
"value": "sci-fi"
},
{
"label": "Seinen",
"value": "seinen"
},
{
"label": "Shoujo",
"value": "shoujo"
},
{
"label": "Shoujo Ai",
"value": "shoujo-ai"
},
{
"label": "Shounen",
"value": "shounen"
},
{
"label": "Shounen Ai",
"value": "shounen-ai"
},
{
"label": "Slice of Life",
"value": "slice-of-life"
},
{
"label": "Smut",
"value": "smut"
},
{
"label": "Soft Yaoi",
"value": "soft-yaoi"
},
{
"label": "Soft Yuri",
"value": "soft-yuri"
},
{
"label": "Sports",
"value": "sports"
},
{
"label": "Supernatural",
"value": "supernatural"
},
{
"label": "Tragedy",
"value": "tragedy"
},
{
"label": "Webtoon",
"value": "webtoon"
},
{
"label": "Wuxia",
"value": "wuxia"
},
{
"label": "Yaoi",
"value": "yaoi"
},
{
"label": "Yuri",
"value": "yuri"
}
]
},
"op": {
"type": "Switch",
"label": "having all selected genres",
"value": false
},
"author": {
"type": "Text",
"label": "Author",
"value": ""
},
"artist": {
"type": "Text",
"label": "Artist",
"value": ""
},
"release": {
"type": "Text",
"label": "Year of Released",
"value": ""
},
"adult": {
"type": "Picker",
"label": "Adult content",
"value": "",
"options": [
{
"label": "All",
"value": ""
},
{
"label": "None adult content",
"value": "0"
},
{
"label": "Only adult content",
"value": "1"
}
]
},
"status[]": {
"type": "Checkbox",
"label": "Status",
"value": [],
"options": [
{
"label": "OnGoing",
"value": "on-going"
},
{
"label": "Completed",
"value": "end"
},
{
"label": "Canceled",
"value": "canceled"
},
{
"label": "On Hold",
"value": "on-hold"
},
{
"label": "Upcoming",
"value": "upcoming"
}
]
},
"m_orderby": {
"type": "Picker",
"label": "Order by",
"value": "",
"options": [
{
"label": "Relevance",
"value": ""
},
{
"label": "Latest",
"value": "latest"
},
{
"label": "A-Z",
"value": "alphabet"
},
{
"label": "Rating",
"value": "rating"
},
{
"label": "Trending",
"value": "trending"
},
{
"label": "Most Views",
"value": "views"
},
{
"label": "New",
"value": "new-manga"
}
]
}
}
}
@@ -0,0 +1,124 @@
{
"filters": {
"genre[]": {
"type": "Checkbox",
"label": "Genre",
"value": [],
"options": [
{
"label": "G",
"value": "g"
},
{
"label": "R15",
"value": "r15"
},
{
"label": "R19",
"value": "r19"
}
]
},
"op": {
"type": "Switch",
"label": "having all selected genres",
"value": false
},
"author": {
"type": "Text",
"label": "Author",
"value": ""
},
"artist": {
"type": "Text",
"label": "Artist",
"value": ""
},
"release": {
"type": "Text",
"label": "Year of Released",
"value": ""
},
"adult": {
"type": "Picker",
"label": "Adult content",
"value": "",
"options": [
{
"label": "All",
"value": ""
},
{
"label": "None adult content",
"value": "0"
},
{
"label": "Only adult content",
"value": "1"
}
]
},
"status[]": {
"type": "Checkbox",
"label": "Status",
"value": [],
"options": [
{
"label": "OnGoing",
"value": "on-going"
},
{
"label": "Completed",
"value": "end"
},
{
"label": "Canceled",
"value": "canceled"
},
{
"label": "On Hold",
"value": "on-hold"
},
{
"label": "Upcoming",
"value": "upcoming"
}
]
},
"m_orderby": {
"type": "Picker",
"label": "Order by",
"value": "",
"options": [
{
"label": "Relevance",
"value": ""
},
{
"label": "Latest",
"value": "latest"
},
{
"label": "A-Z",
"value": "alphabet"
},
{
"label": "Rating",
"value": "rating"
},
{
"label": "Trending",
"value": "trending"
},
{
"label": "Most Views",
"value": "views"
},
{
"label": "New",
"value": "new-manga"
}
]
}
}
}
@@ -1,10 +1,16 @@
import * as fs from 'fs'; import * as fs from 'fs';
import * as cheerio from 'cheerio'; import * as cheerio from 'cheerio';
import * as path from 'path'; import * as path from 'path';
import * as readline from 'readline';
import process from 'process';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
function getFilters(name: string, html: string) { function getFilters(name, html) {
const $: cheerio.CheerioAPI = cheerio.load(html); const $ = cheerio.load(html);
const filters: any = { const filters = {
filters: { filters: {
'genre[]': { 'genre[]': {
type: 'Checkbox', type: 'Checkbox',
@@ -155,7 +161,7 @@ function getFilters(name: string, html: string) {
console.log(`✅Filters created successfully for ${name}✅`); console.log(`✅Filters created successfully for ${name}✅`);
} }
async function getFiltersFromURL(name: string, url: string) { async function getFiltersFromURL(name, url) {
const response = await fetch(url + '/?s=&post_type=wp-manga'); const response = await fetch(url + '/?s=&post_type=wp-manga');
if (!response.ok) { if (!response.ok) {
throw new Error( throw new Error(
@@ -171,45 +177,45 @@ async function getFiltersFromURL(name: string, url: string) {
} }
async function askGetFilter() { async function askGetFilter() {
const readline = require('readline').createInterface({ const rl = readline.createInterface({
input: process.stdin, input: process.stdin,
output: process.stdout, output: process.stdout,
}); });
const EREASE_PREV_LINE = '\x1b[1A\r\x1b[2K'; const EREASE_PREV_LINE = '\x1b[1A\r\x1b[2K';
await readline.question( await rl.question(
'Enter the id of the site (same one as in sources.json): ', 'Enter the id of the site (same one as in sources.json): ',
async (name: string) => { async name => {
await readline.question( await rl.question(
EREASE_PREV_LINE + EREASE_PREV_LINE +
"Do you want to get the filters from a URL or the html text? (if url dosen't work try html) (url/html): ", "Do you want to get the filters from a URL or the html text? (if url dosen't work try html) (url/html): ",
async (method: string) => { async method => {
if (method.toLowerCase() === 'url') { if (method.toLowerCase() === 'url') {
const sources = JSON.parse( const sources = JSON.parse(
fs.readFileSync(path.join(__dirname, 'sources.json'), 'utf-8'), fs.readFileSync(path.join(__dirname, 'sources.json'), 'utf-8'),
); );
const source = sources.find((s: any) => s.id === name); const source = sources.find(s => s.id === name);
if (source && source.sourceSite) { if (source && source.sourceSite) {
console.log('Getting filters from', source.sourceSite); console.log('Getting filters from', source.sourceSite);
try { try {
await getFiltersFromURL(name, source.sourceSite); await getFiltersFromURL(name, source.sourceSite);
} catch (e: any) { } catch (e) {
console.error( console.error(
'Error while getting filters from', 'Error while getting filters from',
source.sourceSite, source.sourceSite,
); );
console.log(e.message || e); console.log(e.message || e);
} }
readline.close(); rl.close();
} else { } else {
await readline.question( await rl.question(
EREASE_PREV_LINE + EREASE_PREV_LINE +
'Enter the URL (same one as in sources.json): ', 'Enter the URL (same one as in sources.json): ',
async (url: string) => { async url => {
readline.close(); rl.close();
try { try {
await getFiltersFromURL(name, url); await getFiltersFromURL(name, url);
} catch (e: any) { } catch (e) {
console.error('Error while getting filters from', url); console.error('Error while getting filters from', url);
console.log(e.message || e); console.log(e.message || e);
} }
@@ -222,12 +228,12 @@ async function askGetFilter() {
`Enter the html text from the page at {sourceSite}/?s=&post_type=wp-manga (at the end press ENTER then press CTRL+C): `, `Enter the html text from the page at {sourceSite}/?s=&post_type=wp-manga (at the end press ENTER then press CTRL+C): `,
); );
let html = ''; let html = '';
readline.on('SIGINT', () => { rl.on('SIGINT', () => {
console.log('Stopeed reading input, creating filters file'); console.log('Stopeed reading input, creating filters file');
getFilters(name, html); getFilters(name, html);
readline.close(); rl.close();
}); });
readline.on('line', (line: string) => { rl.on('line', line => {
html += line + '\n'; html += line + '\n';
}); });
} }
+18
View File
@@ -416,5 +416,23 @@
"useNewChapterEndpoint": true, "useNewChapterEndpoint": true,
"lang": "Spanish" "lang": "Spanish"
} }
},
{
"id": "coralboutique",
"sourceSite": "https://coralboutique.xyz/",
"sourceName": "Coral Boutique",
"options": {
"useNewChapterEndpoint": true,
"lang": "English"
}
},
{
"id": "pasteltales",
"sourceSite": "https://pasteltales.com/",
"sourceName": "Pastel Tales",
"options": {
"useNewChapterEndpoint": true,
"lang": "English"
}
} }
] ]