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/
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"
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:
- 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
- options: the options of the source
- 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
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
) (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" \
(./node_modules/.bin/ts-node scripts/multisrc/lightnovelwp/get_filters.ts
### filters
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))
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 cheerio from 'cheerio';
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) {
const $: cheerio.CheerioAPI = cheerio.load(html);
const filters: any = {
function getFilters(name, html) {
const $ = cheerio.load(html);
const filters = {
filters: {
'genre[]': {
type: 'Checkbox',
@@ -36,27 +42,29 @@ function getFilters(name: string, html: string) {
const filtersContainer = $('div.quickfilter').find('ul');
filtersContainer.each((i, el) => {
const filterName = Object.keys(filters.filters)[i];
filters.filters[filterName].label = $(el)
.prev()
.contents()
.first()
.text()
.trim();
$(el)
.find('li')
.each((j, li) => {
filters.filters[filterName].options.push({
label: $(li).text().trim(),
value: decodeURI($(li).find('input').attr('value') || ''),
if (filterName) {
filters.filters[filterName].label = $(el)
.prev()
.contents()
.first()
.text()
.trim();
$(el)
.find('li')
.each((j, li) => {
filters.filters[filterName].options.push({
label: $(li).text().trim(),
value: decodeURI($(li).find('input').attr('value') || ''),
});
});
});
}
});
if (
filters.filters['m_orderby'].options.length == 0 ||
filters.filters['status[]'].options.length == 0 ||
filters.filters['adult'].options.length == 0 ||
filters.filters['genre[]'].options.length == 0
filters.filters['genre[]'].options.length == 0 ||
filters.filters['type[]'].options.length == 0 ||
filters.filters['status'].options.length == 0 ||
filters.filters['order'].options.length == 0
) {
console.error(
`🚨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}✅`);
}
async function getFiltersFromURL(name: string, url: string) {
async function getFiltersFromURL(name, url) {
const response = await fetch(url + '/series/');
if (!response.ok) {
throw new Error(
@@ -82,49 +90,50 @@ async function getFiltersFromURL(name: string, url: string) {
getFilters(name, html);
} catch (e) {
console.error('Error while getting filters from', url);
console.error('(' + e + ')');
}
}
async function askGetFilter() {
const readline = require('readline').createInterface({
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
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): ',
async (name: string) => {
await readline.question(
async name => {
await rl.question(
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): ",
async (method: string) => {
async method => {
if (method.toLowerCase() === 'url') {
const sources = JSON.parse(
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) {
console.log('Getting filters from', source.sourceSite);
try {
await getFiltersFromURL(name, source.sourceSite);
} catch (e: any) {
} catch (e) {
console.error(
'Error while getting filters from',
source.sourceSite,
);
console.log(e.message || e);
}
readline.close();
rl.close();
} else {
await readline.question(
await rl.question(
EREASE_PREV_LINE +
'Enter the URL (same one as in sources.json): ',
async (url: string) => {
readline.close();
async url => {
rl.close();
try {
await getFiltersFromURL(name, url);
} catch (e: any) {
} catch (e) {
console.error('Error while getting filters from', url);
console.log(e.message || e);
}
@@ -135,15 +144,15 @@ async function askGetFilter() {
process.stdout.write(
EREASE_PREV_LINE +
`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 = '';
readline.on('SIGINT', () => {
rl.on('SIGINT', () => {
console.log('Stopeed reading input, creating filters file');
getFilters(name, html);
readline.close();
rl.close();
});
readline.on('line', (line: string) => {
rl.on('line', line => {
html += line + '\n';
});
}
@@ -213,7 +213,18 @@
"sourceSite": "https://arcanetranslations.com/",
"sourceName": "Arcane Translations",
"options": {
"reverseChapters": true,
"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/
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"
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:
- 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)
- 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
exists in the languages (check folder names in "plugins/"))
- 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 \
(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
### 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
) (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" \
(./node_modules/.bin/ts-node scripts/multisrc/madara/get_filters.ts
### filters
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))
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 cheerio from 'cheerio';
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) {
const $: cheerio.CheerioAPI = cheerio.load(html);
const filters: any = {
function getFilters(name, html) {
const $ = cheerio.load(html);
const filters = {
filters: {
'genre[]': {
type: 'Checkbox',
@@ -155,7 +161,7 @@ function getFilters(name: string, html: string) {
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');
if (!response.ok) {
throw new Error(
@@ -171,45 +177,45 @@ async function getFiltersFromURL(name: string, url: string) {
}
async function askGetFilter() {
const readline = require('readline').createInterface({
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
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): ',
async (name: string) => {
await readline.question(
async name => {
await rl.question(
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): ",
async (method: string) => {
async method => {
if (method.toLowerCase() === 'url') {
const sources = JSON.parse(
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) {
console.log('Getting filters from', source.sourceSite);
try {
await getFiltersFromURL(name, source.sourceSite);
} catch (e: any) {
} catch (e) {
console.error(
'Error while getting filters from',
source.sourceSite,
);
console.log(e.message || e);
}
readline.close();
rl.close();
} else {
await readline.question(
await rl.question(
EREASE_PREV_LINE +
'Enter the URL (same one as in sources.json): ',
async (url: string) => {
readline.close();
async url => {
rl.close();
try {
await getFiltersFromURL(name, url);
} catch (e: any) {
} catch (e) {
console.error('Error while getting filters from', url);
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): `,
);
let html = '';
readline.on('SIGINT', () => {
rl.on('SIGINT', () => {
console.log('Stopeed reading input, creating filters file');
getFilters(name, html);
readline.close();
rl.close();
});
readline.on('line', (line: string) => {
rl.on('line', line => {
html += line + '\n';
});
}
+18
View File
@@ -416,5 +416,23 @@
"useNewChapterEndpoint": true,
"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"
}
}
]