|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 726 B After Width: | Height: | Size: 726 B |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.8 KiB |
@@ -8,14 +8,14 @@ class novelOvh implements Plugin.PluginBase {
|
|||||||
id = 'novelovh';
|
id = 'novelovh';
|
||||||
name = 'НовелОВХ';
|
name = 'НовелОВХ';
|
||||||
site = 'https://novel.ovh';
|
site = 'https://novel.ovh';
|
||||||
version = '1.0.1';
|
version = '1.0.2';
|
||||||
icon = 'src/ru/novelovh/icon.png';
|
icon = 'src/ru/novelovh/icon.png';
|
||||||
|
|
||||||
async popularNovels(
|
async popularNovels(
|
||||||
pageNo: number,
|
pageNo: number,
|
||||||
{ showLatestNovels, filters }: Plugin.PopularNovelsOptions,
|
{ showLatestNovels, filters }: Plugin.PopularNovelsOptions,
|
||||||
): Promise<Plugin.NovelItem[]> {
|
): Promise<Plugin.NovelItem[]> {
|
||||||
let url = this.site + '/novel?page=' + (pageNo - 1);
|
let url = this.site + '/content?page=' + (pageNo - 1);
|
||||||
url +=
|
url +=
|
||||||
'&sort=' +
|
'&sort=' +
|
||||||
(showLatestNovels
|
(showLatestNovels
|
||||||
@@ -41,7 +41,9 @@ class novelOvh implements Plugin.PluginBase {
|
|||||||
|
|
||||||
async parseNovel(novelPath: string): Promise<Plugin.SourceNovel> {
|
async parseNovel(novelPath: string): Promise<Plugin.SourceNovel> {
|
||||||
const { book, chapters }: responseNovel = await fetchApi(
|
const { book, chapters }: responseNovel = await fetchApi(
|
||||||
this.resolveUrl(novelPath, true) +
|
this.site +
|
||||||
|
'/content/' +
|
||||||
|
novelPath +
|
||||||
'?_data=routes/reader/book/$slug/index',
|
'?_data=routes/reader/book/$slug/index',
|
||||||
).then(res => res.json());
|
).then(res => res.json());
|
||||||
|
|
||||||
@@ -98,14 +100,9 @@ class novelOvh implements Plugin.PluginBase {
|
|||||||
return chapterText;
|
return chapterText;
|
||||||
}
|
}
|
||||||
|
|
||||||
async searchNovels(
|
async searchNovels(searchTerm: string): Promise<Plugin.NovelItem[]> {
|
||||||
searchTerm: string,
|
const url = `https://api.novel.ovh/v2/books?type=NOVEL&search=${searchTerm}`;
|
||||||
page: number | undefined = 1,
|
const books: BooksEntity[] = await fetchApi(url).then(res => res.json());
|
||||||
): Promise<Plugin.NovelItem[]> {
|
|
||||||
const url = `${this.site}/novel?search=${searchTerm}&page=${page - 1}`;
|
|
||||||
const { books }: { books: BooksEntity[] } = await fetchApi(
|
|
||||||
url + '&_data=routes/reader/book/index',
|
|
||||||
).then(res => res.json());
|
|
||||||
|
|
||||||
const novels: Plugin.NovelItem[] = [];
|
const novels: Plugin.NovelItem[] = [];
|
||||||
books.forEach(novel =>
|
books.forEach(novel =>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class Zelluloza implements Plugin.PluginBase {
|
|||||||
id = 'zelluloza';
|
id = 'zelluloza';
|
||||||
name = 'Целлюлоза';
|
name = 'Целлюлоза';
|
||||||
site = 'https://zelluloza.ru';
|
site = 'https://zelluloza.ru';
|
||||||
version = '1.0.0';
|
version = '1.0.1';
|
||||||
icon = 'src/ru/zelluloza/icon.png';
|
icon = 'src/ru/zelluloza/icon.png';
|
||||||
|
|
||||||
async popularNovels(
|
async popularNovels(
|
||||||
@@ -40,15 +40,14 @@ class Zelluloza implements Plugin.PluginBase {
|
|||||||
const loadedCheerio = parseHTML(body);
|
const loadedCheerio = parseHTML(body);
|
||||||
const novels: Plugin.NovelItem[] = [];
|
const novels: Plugin.NovelItem[] = [];
|
||||||
|
|
||||||
loadedCheerio('div[style="display: flex"]').each((index, element) => {
|
loadedCheerio('div[style="display: flex;"]').each((index, element) => {
|
||||||
novels.push({
|
novels.push({
|
||||||
name: loadedCheerio(element).find('span[itemprop="name"]').text() || '',
|
name: loadedCheerio(element).find('span[itemprop="name"]').text() || '',
|
||||||
cover:
|
cover:
|
||||||
this.site +
|
this.site +
|
||||||
loadedCheerio(element).find('img[class="shadow"]').attr('src'),
|
loadedCheerio(element).find('img[class="shadow"]').attr('src'),
|
||||||
path: (
|
path: (
|
||||||
loadedCheerio(element).find('img[class="shadow"]').attr('onclick') ||
|
loadedCheerio(element).find('a[class="txt"]').attr('href') || ''
|
||||||
''
|
|
||||||
).replace(/\D/g, ''),
|
).replace(/\D/g, ''),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -64,7 +63,7 @@ class Zelluloza implements Plugin.PluginBase {
|
|||||||
|
|
||||||
const novel: Plugin.SourceNovel = {
|
const novel: Plugin.SourceNovel = {
|
||||||
path: novelPath,
|
path: novelPath,
|
||||||
name: loadedCheerio('span[itemprop="name"]').text(),
|
name: loadedCheerio('h2[class="bookname"]').text().trim(),
|
||||||
cover: this.site + loadedCheerio('img[class="shadow"]').attr('src'),
|
cover: this.site + loadedCheerio('img[class="shadow"]').attr('src'),
|
||||||
genres: loadedCheerio('.gnres').text()?.split?.(': ')?.[1],
|
genres: loadedCheerio('.gnres').text()?.split?.(': ')?.[1],
|
||||||
summary:
|
summary:
|
||||||
@@ -163,15 +162,14 @@ class Zelluloza implements Plugin.PluginBase {
|
|||||||
const loadedCheerio = parseHTML(body);
|
const loadedCheerio = parseHTML(body);
|
||||||
const novels: Plugin.NovelItem[] = [];
|
const novels: Plugin.NovelItem[] = [];
|
||||||
|
|
||||||
loadedCheerio('div[style="display: flex"]').each((index, element) => {
|
loadedCheerio('div[style="display: flex;"]').each((index, element) => {
|
||||||
novels.push({
|
novels.push({
|
||||||
name: loadedCheerio(element).find('span[itemprop="name"]').text() || '',
|
name: loadedCheerio(element).find('span[itemprop="name"]').text() || '',
|
||||||
cover:
|
cover:
|
||||||
this.site +
|
this.site +
|
||||||
loadedCheerio(element).find('img[class="shadow"]').attr('src'),
|
loadedCheerio(element).find('img[class="shadow"]').attr('src'),
|
||||||
path: (
|
path: (
|
||||||
loadedCheerio(element).find('img[class="shadow"]').attr('onclick') ||
|
loadedCheerio(element).find('a[class="txt"]').attr('href') || ''
|
||||||
''
|
|
||||||
).replace(/\D/g, ''),
|
).replace(/\D/g, ''),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
require('module-alias/register');
|
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import { Plugin } from '@typings/plugin';
|
import { Plugin } from '@typings/plugin';
|
||||||
import { languages } from '@libs/languages';
|
import { languages } from '@libs/languages';
|
||||||
@@ -9,44 +8,38 @@ const size = 96;
|
|||||||
|
|
||||||
const skip: string[] = [
|
const skip: string[] = [
|
||||||
//custom icons
|
//custom icons
|
||||||
'ReN',
|
|
||||||
'sektenovel',
|
|
||||||
'FWK.US',
|
'FWK.US',
|
||||||
|
'ReN',
|
||||||
'daonovel',
|
'daonovel',
|
||||||
'dragontea',
|
'dragontea',
|
||||||
'foxaholic',
|
'foxaholic',
|
||||||
'kiniga',
|
'kiniga',
|
||||||
'sonicmtl',
|
'lightnovelpubvip',
|
||||||
'translatinotaku',
|
|
||||||
'wuxiaworld.site',
|
|
||||||
'moonlightnovel',
|
'moonlightnovel',
|
||||||
'mtl-novel',
|
'mtl-novel',
|
||||||
'mysticalmerries',
|
'mysticalmerries',
|
||||||
'lightnovelpubvip',
|
|
||||||
'novelTL',
|
'novelTL',
|
||||||
|
'novelsparadise',
|
||||||
|
'sektenovel',
|
||||||
|
'sonicmtl',
|
||||||
|
'translatinotaku',
|
||||||
|
'wuxiaworld.site',
|
||||||
|
|
||||||
//low quality
|
//low quality
|
||||||
'BLN',
|
'BLN',
|
||||||
'novelhall',
|
|
||||||
'NO.net',
|
'NO.net',
|
||||||
'novelbookid',
|
'novelbookid',
|
||||||
|
'novelhall',
|
||||||
'olaoe',
|
'olaoe',
|
||||||
|
|
||||||
//broken icons
|
|
||||||
'guavaread',
|
|
||||||
'LightNovelUpdates',
|
|
||||||
'turkcelightnovels',
|
|
||||||
'novelki.pl',
|
|
||||||
'lunarletters',
|
|
||||||
'novelsparadise',
|
|
||||||
'earlynovel',
|
|
||||||
'wbnovel',
|
|
||||||
'novhell',
|
|
||||||
'RLIB',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const used = new Set();
|
const used = new Set();
|
||||||
used.add(path.join(root, 'icons', 'coverNotAvailable.webp'));
|
used.add(path.join(root, 'icons', 'coverNotAvailable.webp'));
|
||||||
|
used.add(path.join(root, 'icons', 'siteNotAvailable.png'));
|
||||||
|
|
||||||
|
const notAvailableImage = fs.readFileSync(
|
||||||
|
path.join(root, 'icons', 'siteNotAvailable.png'),
|
||||||
|
);
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
console.log('Loading plugins.json ⌛');
|
console.log('Loading plugins.json ⌛');
|
||||||
@@ -56,6 +49,7 @@ used.add(path.join(root, 'icons', 'coverNotAvailable.webp'));
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const plugins = JSON.parse(fs.readFileSync(plugin_path, 'utf-8'));
|
const plugins = JSON.parse(fs.readFileSync(plugin_path, 'utf-8'));
|
||||||
|
|
||||||
console.log('\nDownloading icons ⌛');
|
console.log('\nDownloading icons ⌛');
|
||||||
let language;
|
let language;
|
||||||
for (let plugin in plugins) {
|
for (let plugin in plugins) {
|
||||||
@@ -80,10 +74,6 @@ used.add(path.join(root, 'icons', 'coverNotAvailable.webp'));
|
|||||||
.then(res => res.arrayBuffer())
|
.then(res => res.arrayBuffer())
|
||||||
.then(res => Buffer.from(res));
|
.then(res => Buffer.from(res));
|
||||||
|
|
||||||
const notAvailableImage = fs.readFileSync(
|
|
||||||
path.join(root, 'scripts', 'notavailable.png'),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (Buffer.compare(image, notAvailableImage) === 0) {
|
if (Buffer.compare(image, notAvailableImage) === 0) {
|
||||||
console.log(
|
console.log(
|
||||||
' ',
|
' ',
|
||||||
@@ -114,14 +104,6 @@ used.add(path.join(root, 'icons', 'coverNotAvailable.webp'));
|
|||||||
}
|
}
|
||||||
console.log('\nDeleting unused icons ⌛');
|
console.log('\nDeleting unused icons ⌛');
|
||||||
|
|
||||||
function fileList(dir: string): string[] {
|
|
||||||
return fs.readdirSync(dir).reduce((list: string[], file: string) => {
|
|
||||||
const name = path.join(dir, file);
|
|
||||||
const isDir = fs.statSync(name).isDirectory();
|
|
||||||
return list.concat(isDir ? fileList(name) : [name]);
|
|
||||||
}, []);
|
|
||||||
}
|
|
||||||
|
|
||||||
fileList(path.join(root, 'icons')).forEach(path => {
|
fileList(path.join(root, 'icons')).forEach(path => {
|
||||||
if (!used.has(path)) {
|
if (!used.has(path)) {
|
||||||
console.log('🗑️', path);
|
console.log('🗑️', path);
|
||||||
@@ -130,3 +112,11 @@ used.add(path.join(root, 'icons', 'coverNotAvailable.webp'));
|
|||||||
});
|
});
|
||||||
console.log('\nDone ✅');
|
console.log('\nDone ✅');
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
function fileList(dir: string): string[] {
|
||||||
|
return fs.readdirSync(dir).reduce((list: string[], file: string) => {
|
||||||
|
const name = path.join(dir, file);
|
||||||
|
const isDir = fs.statSync(name).isDirectory();
|
||||||
|
return list.concat(isDir ? fileList(name) : [name]);
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ for (let language in languages) {
|
|||||||
lang: languages[language as keyof typeof languages],
|
lang: languages[language as keyof typeof languages],
|
||||||
version,
|
version,
|
||||||
url: `${PLUGIN_LINK}/${language.toLowerCase()}/${plugin}`,
|
url: `${PLUGIN_LINK}/${language.toLowerCase()}/${plugin}`,
|
||||||
iconUrl: `${ICON_LINK}/${icon}`,
|
iconUrl: `${ICON_LINK}/${icon || 'siteNotAvailable.png'}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (pluginSet.has(id)) {
|
if (pluginSet.has(id)) {
|
||||||
|
|||||||