Full TS for Plugins (#538)

* remove lang, descrription in plugin script

* remove languages import

* Update README.md

* fix: missing lang

* clean: remove description

* feat(Add Sources) (#15)

* add many sources

* add showToast

* feat(Add Source): (#16)

* add source

* remove descriptions

* Early Novel & Fast Novel (#1)

* some more plugin

* plugin

* try something new

* yes

* try yes

* genres is plural

* fastnovel full fix

* testings

* early check

* earlynovel fixed

* showToast check

* earlynovel done

* fastnovel fixe

* again

* showToasts again

* fix for fastnovel

* done

* for pr

* Update freenovelupdates.js

* MTL Reader and MTL Novel (#2)

* first

* test

* wops

* mtlreaders

* ok

* for PR

* Nitro Scans and Novel Hold (#3)

* start feature

* more feature

* something

* eslint

* yes

* maybe

* wa

* asdasd

* amazing

* change it up

* for pr

* WPmangastream and Novelfull (#4) (#17)

* source generation

* fix json parse error

* update plguins

* delete fetchApi, nobleMTL (.js)

* delete showToast.js

* Typescript Support (#18)

* Initial TS Config

* Initial TS Config

* Fix most errors

* Fix test webserver

* Fix webserver isPlugin not working

* Fix typos

* Add check if plugins have all the fields

* Move exports.protected to the bottom of the plugin

* Change username, reponame and branchname

* Fix no exports error

* Fix type

* Fix typo in tsc_fix

* Remove const from exports to not re-define consts

* Readd const becuause exports may not exist.

* Fix plugins to work in-app

* Fix NobleMTL

* Remove fix_ts.ts

* Change template.ts

* delete cheerio_space

* move api into ./testweb

* remove js dir

* remove js dir (again)

* remove ./js (again)

* init multisrc generator (test)

* remove module.exports in libs

* madara generator

* update template

* rename generator, TS for hako

* fix icon url for madara

* fix icon for madara (again)

* update Readme, nodemon

* export default for all libs

* fix madara novelurl

* update: pluginId, name, filename for madara

* feat: check same id error

* update: precommit, fix: require.default

* Revert "update: precommit, fix: require.default"

This reverts commit c642c5c72241f13eccfe417210c22272c4739ffa.

* Port all plugins to ts (#19)

- fix cheerio
- remove export default
- fix spelling

* update template

* add multisrc noveltl, update generator param, fix web search

* fix undefined id for Snailulitka

* add rulate multisrc, fix max length textarea

* add readwn multisrc

* delete: erolate and rulate are in multisrc

* Change broken extension and show error on commit for those files (#20)

* Change to .broken.ts and show error on commit for those files

* remove novelStatus

* fix: wrong id in github action

* remove mangastream multisrc

* update icon for readwn multisrc

---------

Co-authored-by: K1ngfish3r <trulyihu@gmail.com>
Co-authored-by: Marcin Majewski <skilletssgames@gmail.com>
This commit is contained in:
nyagami
2023-08-17 10:19:45 +07:00
committed by GitHub
parent e444031c25
commit e602df44c8
306 changed files with 58843 additions and 14008 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,213 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.filters = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
const cheerio_1 = require("cheerio");
const dayjs_1 = __importDefault(require("dayjs"));
const fetch_1 = require("@libs/fetch");
// import { parseMadaraDate } from "@libs/parseMadaraDate";
// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
// import { showToast } from "@libs/showToast";
const filterInputs_1 = require("@libs/filterInputs");
const novelStatus_1 = require("@libs/novelStatus");
const defaultCover_1 = require("@libs/defaultCover");
exports.id = "axel.znovel";
exports.name = "Аксел";
exports.icon = "";
exports.version = "1.0.0";
exports.site = "https://axel.znovel.space";
exports.filters = [{ "key": "tags", "label": "Тэги", "values": [{ "label": "Богини", "value": 316 }, { "label": "Везучий главный герой", "value": 411 }, { "label": "Виртуальная реальность", "value": 744 }, { "label": "Высокомерный герой", "value": 56 }, { "label": "Герой-извращенец", "value": 521 }, { "label": "Главная героиня — женщина", "value": 277 }, { "label": "Главный герой — мужчина", "value": 419 }, { "label": "Дворяне", "value": 487 }, { "label": "Девочки-волшебницы", "value": 415 }, { "label": "Демоны", "value": 193 }, { "label": "Дружба", "value": 293 }, { "label": "Есть аниме-адаптация", "value": 10 }, { "label": "Есть видеоигра", "value": 13 }, { "label": "Есть манга-адаптация", "value": 14 }, { "label": "Игра на выживание", "value": 696 }, { "label": "Из грязи в князи", "value": 542 }, { "label": "Королевская особа", "value": 596 }, { "label": "Ленивый главный герой", "value": 389 }, { "label": "Маги", "value": 757 }, { "label": "Магические технологии", "value": 417 }], "inputType": filterInputs_1.FilterInputs.Checkbox }];
exports["protected"] = false;
const baseUrl = exports.site;
const domain = baseUrl.split('//')[1];
const popularNovels = function (page, { filters }) {
var _a, _b, _c, _d, _e;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: ((_b = (_a = filters === null || filters === void 0 ? void 0 : filters.tags) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0 > 0) ? { tags: filters === null || filters === void 0 ? void 0 : filters.tags } : {},
hostname: domain,
limit: 40,
page,
},
}),
});
const json = yield result.json();
const novels = (_e = (_d = (_c = json.data) === null || _c === void 0 ? void 0 : _c.projects) === null || _d === void 0 ? void 0 : _d.content) === null || _e === void 0 ? void 0 : _e.map((novel) => {
var _a;
return ({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
};
exports.popularNovels = popularNovels;
const parseNovelAndChapters = function (novelUrl) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Book',
query: 'query Book($url:String){project(project:{fullUrl:$url}){title translationStatus url covers{url}persons(langs:["ru","en","*"]roles:["author","illustrator","original_story","original_design"]){role name{firstName lastName}}genres{nameRu nameEng}tags{nameRu nameEng}annotation{text}subprojects{content{title volumes{content{url shortName chapters{title publishDate url published}}}}}}}',
variables: {
hostname: domain,
project: novelUrl,
url: novelUrl,
},
}),
});
const json = yield result.json();
const novel = {
url: novelUrl,
name: json.data.project.title,
cover: ((_a = json.data.project.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + json.data.project.covers[0].url
: defaultCover_1.defaultCover,
summary: (0, cheerio_1.load)((_b = json.data.project.annotation) === null || _b === void 0 ? void 0 : _b.text).text(),
author: json.data.project.persons[0].name.firstName +
' ' +
json.data.project.persons[0].name.lastName,
status: json.data.project.translationStatus === 'active'
? novelStatus_1.NovelStatus.Ongoing
: novelStatus_1.NovelStatus.Completed,
};
let genres = []
.concat(json.data.project.tags, json.data.project.genres)
.map((item) => (item === null || item === void 0 ? void 0 : item.nameRu) || (item === null || item === void 0 ? void 0 : item.nameEng))
.filter(item => item);
if (genres.length > 0) {
novel.genres = genres.join(',');
}
let novelChapters = [];
json.data.project.subprojects.content.forEach((work) => work.volumes.content.forEach((volume) => volume.chapters.forEach((chapter) => (chapter === null || chapter === void 0 ? void 0 : chapter.published) &&
novelChapters.push({
name: volume.shortName + ' ' + chapter.title,
url: novelUrl + '/' + volume.url + '/' + chapter.url,
releaseTime: (0, dayjs_1.default)(chapter.publishDate).format('LLL'),
}))));
novel.chapters = novelChapters;
return novel;
});
};
exports.parseNovelAndChapters = parseNovelAndChapters;
const parseChapter = function (chapterUrl) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'EReaderData',
query: 'query EReaderData($url:String!,$chapterSelector:Selector!){project(project:{fullUrl:$url}){title url}chapter(chapter:$chapterSelector){title text{text}}}',
variables: {
chapterSelector: {
fullUrl: chapterUrl,
},
url: chapterUrl,
},
}),
});
const json = yield result.json();
return (0, cheerio_1.load)(json.data.chapter.text.text).html();
});
};
exports.parseChapter = parseChapter;
const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b, _c;
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: {
query: searchTerm,
},
hostname: domain,
limit: 40,
page: 1,
},
}),
});
const json = yield result.json();
const novels = [];
(_c = (_b = (_a = json === null || json === void 0 ? void 0 : json.data) === null || _a === void 0 ? void 0 : _a.projects) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.forEach((novel) => {
var _a;
return novels.push({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
exports.searchNovels = searchNovels;
const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
return yield (0, fetch_1.fetchFile)(url, {});
});
exports.fetchImage = fetchImage;
+209
View File
@@ -0,0 +1,209 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.filters = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
const cheerio_1 = require("cheerio");
const dayjs_1 = __importDefault(require("dayjs"));
const fetch_1 = require("@libs/fetch");
const novelStatus_1 = require("@libs/novelStatus");
const defaultCover_1 = require("@libs/defaultCover");
exports.id = "bel.novel";
exports.name = "Белманга";
exports.icon = "";
exports.version = "1.0.0";
exports.site = "https://bel.novel.tl";
exports.filters = [];
exports["protected"] = false;
const baseUrl = exports.site;
const domain = baseUrl.split('//')[1];
const popularNovels = function (page, { filters }) {
var _a, _b, _c, _d, _e;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: ((_b = (_a = filters === null || filters === void 0 ? void 0 : filters.tags) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0 > 0) ? { tags: filters === null || filters === void 0 ? void 0 : filters.tags } : {},
hostname: domain,
limit: 40,
page,
},
}),
});
const json = yield result.json();
const novels = (_e = (_d = (_c = json.data) === null || _c === void 0 ? void 0 : _c.projects) === null || _d === void 0 ? void 0 : _d.content) === null || _e === void 0 ? void 0 : _e.map((novel) => {
var _a;
return ({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
};
exports.popularNovels = popularNovels;
const parseNovelAndChapters = function (novelUrl) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Book',
query: 'query Book($url:String){project(project:{fullUrl:$url}){title translationStatus url covers{url}persons(langs:["ru","en","*"]roles:["author","illustrator","original_story","original_design"]){role name{firstName lastName}}genres{nameRu nameEng}tags{nameRu nameEng}annotation{text}subprojects{content{title volumes{content{url shortName chapters{title publishDate url published}}}}}}}',
variables: {
hostname: domain,
project: novelUrl,
url: novelUrl,
},
}),
});
const json = yield result.json();
const novel = {
url: novelUrl,
name: json.data.project.title,
cover: ((_a = json.data.project.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + json.data.project.covers[0].url
: defaultCover_1.defaultCover,
summary: (0, cheerio_1.load)((_b = json.data.project.annotation) === null || _b === void 0 ? void 0 : _b.text).text(),
author: json.data.project.persons[0].name.firstName +
' ' +
json.data.project.persons[0].name.lastName,
status: json.data.project.translationStatus === 'active'
? novelStatus_1.NovelStatus.Ongoing
: novelStatus_1.NovelStatus.Completed,
};
let genres = []
.concat(json.data.project.tags, json.data.project.genres)
.map((item) => (item === null || item === void 0 ? void 0 : item.nameRu) || (item === null || item === void 0 ? void 0 : item.nameEng))
.filter(item => item);
if (genres.length > 0) {
novel.genres = genres.join(',');
}
let novelChapters = [];
json.data.project.subprojects.content.forEach((work) => work.volumes.content.forEach((volume) => volume.chapters.forEach((chapter) => (chapter === null || chapter === void 0 ? void 0 : chapter.published) &&
novelChapters.push({
name: volume.shortName + ' ' + chapter.title,
url: novelUrl + '/' + volume.url + '/' + chapter.url,
releaseTime: (0, dayjs_1.default)(chapter.publishDate).format('LLL'),
}))));
novel.chapters = novelChapters;
return novel;
});
};
exports.parseNovelAndChapters = parseNovelAndChapters;
const parseChapter = function (chapterUrl) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'EReaderData',
query: 'query EReaderData($url:String!,$chapterSelector:Selector!){project(project:{fullUrl:$url}){title url}chapter(chapter:$chapterSelector){title text{text}}}',
variables: {
chapterSelector: {
fullUrl: chapterUrl,
},
url: chapterUrl,
},
}),
});
const json = yield result.json();
return (0, cheerio_1.load)(json.data.chapter.text.text).html();
});
};
exports.parseChapter = parseChapter;
const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b, _c;
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: {
query: searchTerm,
},
hostname: domain,
limit: 40,
page: 1,
},
}),
});
const json = yield result.json();
const novels = [];
(_c = (_b = (_a = json === null || json === void 0 ? void 0 : json.data) === null || _a === void 0 ? void 0 : _a.projects) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.forEach((novel) => {
var _a;
return novels.push({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
exports.searchNovels = searchNovels;
const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
return yield (0, fetch_1.fetchFile)(url, {});
});
exports.fetchImage = fetchImage;
+210
View File
@@ -0,0 +1,210 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchImage = exports.filters = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.icon = exports.version = exports.site = exports.name = exports.id = void 0;
const cheerio_1 = require("cheerio");
const fetch_1 = require("@libs/fetch");
const novelStatus_1 = require("@libs/novelStatus");
const filterInputs_1 = require("@libs/filterInputs");
exports.id = "jaomix.ru";
exports.name = "Jaomix";
exports.site = "https://jaomix.ru";
exports.version = "1.0.0";
exports.icon = "src/ru/jaomix/icon.png";
const baseUrl = exports.site;
const popularNovels = function (page, { showLatestNovels, filters }) {
return __awaiter(this, void 0, void 0, function* () {
let url = baseUrl + "/?searchrn&sortby=";
url += showLatestNovels ? "upd" : (filters === null || filters === void 0 ? void 0 : filters.sort) || "count";
if (filters) {
if (Array.isArray(filters.type) && filters.type.length) {
url += filters.type.map((i) => `&lang[]=${i}`).join("");
}
if (Array.isArray(filters.genres) && filters.genres.length) {
url += filters.genres.map((i) => `&genre[]=${i}`).join("");
}
}
url += `&page=${page}`;
const result = yield (0, fetch_1.fetchApi)(url);
let body = yield result.text();
const loadedCheerio = (0, cheerio_1.load)(body);
let novels = [];
loadedCheerio('div[class="block-home"] > div[class="one"]').each(function () {
var _a;
const name = loadedCheerio(this)
.find('div[class="img-home"] > a')
.attr("title");
const cover = (_a = loadedCheerio(this)
.find('div[class="img-home"] > a > img')
.attr("src")) === null || _a === void 0 ? void 0 : _a.replace("-150x150", "");
const url = loadedCheerio(this)
.find('div[class="img-home"] > a')
.attr("href");
if (!name || !url)
return;
novels.push({ name, cover, url });
});
return novels;
});
};
exports.popularNovels = popularNovels;
const parseNovelAndChapters = function (novelUrl) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)(novelUrl);
const body = yield result.text();
const loadedCheerio = (0, cheerio_1.load)(body);
let novel = {
url: novelUrl,
};
novel.name = loadedCheerio('div[class="desc-book"] > h1').text().trim();
novel.cover = loadedCheerio('div[class="img-book"] > img').attr("src");
novel.summary = loadedCheerio('div[id="desc-tab"]').text().trim();
loadedCheerio("#info-book > p").each(function () {
let text = loadedCheerio(this).text().replace(/,/g, "").split(" ");
if (text[0] === "Автор:") {
novel.author = text.splice(1).join(" ");
}
else if (text[0] === "Жанры:") {
novel.genres = text.splice(1).join(",");
}
else if (text[0] === "Статус:") {
novel.status = text.includes("продолжается")
? novelStatus_1.NovelStatus.Ongoing
: novelStatus_1.NovelStatus.Completed;
}
});
const chapters = [];
loadedCheerio(".download-chapter div.title").each(function () {
chapters.push({
name: loadedCheerio(this).find("a").attr("title"),
releaseTime: loadedCheerio(this).find("time").text(),
url: loadedCheerio(this).find("a").attr("href"),
});
});
novel.chapters = chapters.reverse();
return novel;
});
};
exports.parseNovelAndChapters = parseNovelAndChapters;
const parseChapter = function (chapterUrl) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)(chapterUrl);
const body = yield result.text();
const loadedCheerio = (0, cheerio_1.load)(body);
loadedCheerio('div[class="adblock-service"]').remove();
const chapterText = loadedCheerio('div[class="entry-content"]').html();
return chapterText;
});
};
exports.parseChapter = parseChapter;
const searchNovels = function (searchTerm) {
return __awaiter(this, void 0, void 0, function* () {
const url = `${baseUrl}/?searchrn=${searchTerm}&but=Поиск по названию&sortby=upd`;
const result = yield (0, fetch_1.fetchApi)(url);
let body = yield result.text();
const loadedCheerio = (0, cheerio_1.load)(body);
let novels = [];
loadedCheerio('div[class="block-home"] > div[class="one"]').each(function () {
var _a;
const name = loadedCheerio(this)
.find('div[class="img-home"] > a')
.attr("title");
const cover = (_a = loadedCheerio(this)
.find('div[class="img-home"] > a > img')
.attr("src")) === null || _a === void 0 ? void 0 : _a.replace("-150x150", "");
const url = loadedCheerio(this)
.find('div[class="img-home"] > a')
.attr("href");
if (!name || !url)
return;
novels.push({ name, cover, url });
});
return novels;
});
};
exports.searchNovels = searchNovels;
exports.filters = [
{
key: "sort",
label: "Сортировка",
values: [
{ label: "Имя", value: "alphabet" },
{ label: "Просмотры", value: "count" },
{ label: "Дате добавления", value: "new" },
{ label: "Дате обновления", value: "upd" },
],
inputType: filterInputs_1.FilterInputs.Picker,
},
{
key: "type",
label: "Тип",
values: [
{ label: "Английский", value: "Английский" },
{ label: "Китайский", value: "Китайский" },
{ label: "Корейский", value: "Корейский" },
{ label: "Японский", value: "Японский" },
],
inputType: filterInputs_1.FilterInputs.Checkbox,
},
{
key: "genres",
label: "Жанры",
values: [
{ label: "Боевые Искусства", value: "Боевые Искусства" },
{ label: "Виртуальный Мир", value: "Виртуальный Мир" },
{ label: "Гарем", value: "Гарем" },
{ label: "Детектив", value: "Детектив" },
{ label: "Драма", value: "Драма" },
{ label: "Игра", value: "Игра" },
{ label: "Истории из жизни", value: "Истории из жизни" },
{ label: "Исторический", value: "Исторический" },
{ label: "История", value: "История" },
{ label: "Исэкай", value: "Исэкай" },
{ label: "Комедия", value: "Комедия" },
{ label: "Меха", value: "Меха" },
{ label: "Мистика", value: "Мистика" },
{ label: "Научная Фантастика", value: "Научная Фантастика" },
{ label: "Повседневность", value: "Повседневность" },
{ label: "Постапокалипсис", value: "Постапокалипсис" },
{ label: "Приключения", value: "Приключения" },
{ label: "Психология", value: "Психология" },
{ label: "Романтика", value: "Романтика" },
{ label: "Сверхъестественное", value: "Сверхъестественное" },
{ label: "Сёнэн", value: "Сёнэн" },
{ label: "Сёнэн-ай", value: "Сёнэн-ай" },
{ label: "Спорт", value: "Спорт" },
{ label: "Сэйнэн", value: "Сэйнэн" },
{ label: "Сюаньхуа", value: "Сюаньхуа" },
{ label: "Трагедия", value: "Трагедия" },
{ label: "Триллер", value: "Триллер" },
{ label: "Фантастика", value: "Фантастика" },
{ label: "Фэнтези", value: "Фэнтези" },
{ label: "Хоррор", value: "Хоррор" },
{ label: "Школьная жизнь", value: "Школьная жизнь" },
{ label: "Шоунен", value: "Шоунен" },
{ label: "Экшн", value: "Экшн" },
{ label: "Этти", value: "Этти" },
{ label: "Юри", value: "Юри" },
{ label: "Adult", value: "Adult" },
{ label: "Ecchi", value: "Ecchi" },
{ label: "Josei", value: "Josei" },
{ label: "Lolicon", value: "Lolicon" },
{ label: "Mature", value: "Mature" },
{ label: "Shoujo", value: "Shoujo" },
{ label: "Wuxia", value: "Wuxia" },
{ label: "Xianxia", value: "Xianxia" },
{ label: "Xuanhuan", value: "Xuanhuan" },
{ label: "Yaoi", value: "Yaoi" },
],
inputType: filterInputs_1.FilterInputs.Checkbox,
},
];
exports.fetchImage = fetch_1.fetchFile;
+213
View File
@@ -0,0 +1,213 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.filters = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
const cheerio_1 = require("cheerio");
const dayjs_1 = __importDefault(require("dayjs"));
const fetch_1 = require("@libs/fetch");
// import { parseMadaraDate } from "@libs/parseMadaraDate";
// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
// import { showToast } from "@libs/showToast";
const filterInputs_1 = require("@libs/filterInputs");
const novelStatus_1 = require("@libs/novelStatus");
const defaultCover_1 = require("@libs/defaultCover");
exports.id = "japit.novel";
exports.name = "Japit Comics";
exports.icon = "";
exports.version = "1.0.0";
exports.site = "https://japit.novel.tl";
exports.filters = [{ "key": "tags", "label": "Тэги", "values": [{ "label": "Академия", "value": 5 }, { "label": "Андроиды", "value": 37 }, { "label": "Беззаботный герой", "value": 115 }, { "label": "Боги", "value": 318 }, { "label": "Богини", "value": 316 }, { "label": "Вампиры", "value": 742 }, { "label": "Везучий главный герой", "value": 411 }, { "label": "Влияние прошлого", "value": 517 }, { "label": "Внезапное обогащение", "value": 691 }, { "label": "Военные хроники", "value": 749 }, { "label": "Война", "value": 750 }, { "label": "Воспоминания прошлого", "value": 283 }, { "label": "Герои", "value": 341 }, { "label": "Героиня красавица", "value": 81 }, { "label": "Герой влюбляется первым", "value": 561 }, { "label": "Герой красавец", "value": 329 }, { "label": "Герой-бесстыдник", "value": 632 }, { "label": "Герой-извращенец", "value": 521 }, { "label": "Герой-трудяга", "value": 330 }, { "label": "R-15", "value": 570 }], "inputType": filterInputs_1.FilterInputs.Checkbox }];
exports["protected"] = false;
const baseUrl = exports.site;
const domain = baseUrl.split('//')[1];
const popularNovels = function (page, { filters }) {
var _a, _b, _c, _d, _e;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: ((_b = (_a = filters === null || filters === void 0 ? void 0 : filters.tags) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0 > 0) ? { tags: filters === null || filters === void 0 ? void 0 : filters.tags } : {},
hostname: domain,
limit: 40,
page,
},
}),
});
const json = yield result.json();
const novels = (_e = (_d = (_c = json.data) === null || _c === void 0 ? void 0 : _c.projects) === null || _d === void 0 ? void 0 : _d.content) === null || _e === void 0 ? void 0 : _e.map((novel) => {
var _a;
return ({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
};
exports.popularNovels = popularNovels;
const parseNovelAndChapters = function (novelUrl) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Book',
query: 'query Book($url:String){project(project:{fullUrl:$url}){title translationStatus url covers{url}persons(langs:["ru","en","*"]roles:["author","illustrator","original_story","original_design"]){role name{firstName lastName}}genres{nameRu nameEng}tags{nameRu nameEng}annotation{text}subprojects{content{title volumes{content{url shortName chapters{title publishDate url published}}}}}}}',
variables: {
hostname: domain,
project: novelUrl,
url: novelUrl,
},
}),
});
const json = yield result.json();
const novel = {
url: novelUrl,
name: json.data.project.title,
cover: ((_a = json.data.project.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + json.data.project.covers[0].url
: defaultCover_1.defaultCover,
summary: (0, cheerio_1.load)((_b = json.data.project.annotation) === null || _b === void 0 ? void 0 : _b.text).text(),
author: json.data.project.persons[0].name.firstName +
' ' +
json.data.project.persons[0].name.lastName,
status: json.data.project.translationStatus === 'active'
? novelStatus_1.NovelStatus.Ongoing
: novelStatus_1.NovelStatus.Completed,
};
let genres = []
.concat(json.data.project.tags, json.data.project.genres)
.map((item) => (item === null || item === void 0 ? void 0 : item.nameRu) || (item === null || item === void 0 ? void 0 : item.nameEng))
.filter(item => item);
if (genres.length > 0) {
novel.genres = genres.join(',');
}
let novelChapters = [];
json.data.project.subprojects.content.forEach((work) => work.volumes.content.forEach((volume) => volume.chapters.forEach((chapter) => (chapter === null || chapter === void 0 ? void 0 : chapter.published) &&
novelChapters.push({
name: volume.shortName + ' ' + chapter.title,
url: novelUrl + '/' + volume.url + '/' + chapter.url,
releaseTime: (0, dayjs_1.default)(chapter.publishDate).format('LLL'),
}))));
novel.chapters = novelChapters;
return novel;
});
};
exports.parseNovelAndChapters = parseNovelAndChapters;
const parseChapter = function (chapterUrl) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'EReaderData',
query: 'query EReaderData($url:String!,$chapterSelector:Selector!){project(project:{fullUrl:$url}){title url}chapter(chapter:$chapterSelector){title text{text}}}',
variables: {
chapterSelector: {
fullUrl: chapterUrl,
},
url: chapterUrl,
},
}),
});
const json = yield result.json();
return (0, cheerio_1.load)(json.data.chapter.text.text).html();
});
};
exports.parseChapter = parseChapter;
const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b, _c;
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: {
query: searchTerm,
},
hostname: domain,
limit: 40,
page: 1,
},
}),
});
const json = yield result.json();
const novels = [];
(_c = (_b = (_a = json === null || json === void 0 ? void 0 : json.data) === null || _a === void 0 ? void 0 : _a.projects) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.forEach((novel) => {
var _a;
return novels.push({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
exports.searchNovels = searchNovels;
const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
return yield (0, fetch_1.fetchFile)(url, {});
});
exports.fetchImage = fetchImage;
+213
View File
@@ -0,0 +1,213 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.filters = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
const cheerio_1 = require("cheerio");
const dayjs_1 = __importDefault(require("dayjs"));
const fetch_1 = require("@libs/fetch");
// import { parseMadaraDate } from "@libs/parseMadaraDate";
// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
// import { showToast } from "@libs/showToast";
const filterInputs_1 = require("@libs/filterInputs");
const novelStatus_1 = require("@libs/novelStatus");
const defaultCover_1 = require("@libs/defaultCover");
exports.id = "kg.novel";
exports.name = "Карманная галактика";
exports.icon = "";
exports.version = "1.0.0";
exports.site = "https://kg.novel.tl";
exports.filters = [{ "key": "tags", "label": "Тэги", "values": [{ "label": "Алхимия", "value": 27 }, { "label": "Андроиды", "value": 37 }, { "label": "Анти-рост персонажа", "value": 25 }, { "label": "Антигерой", "value": 43 }, { "label": "Апатичный главный герой", "value": 46 }, { "label": "Аристократия", "value": 51 }, { "label": "Асоциальный главный герой", "value": 42 }, { "label": "Ассасины", "value": 61 }, { "label": "Беззаботный герой", "value": 115 }, { "label": "Безработные", "value": 377 }, { "label": "Бессмертные", "value": 359 }, { "label": "Библиотека", "value": 393 }, { "label": "Боги", "value": 318 }, { "label": "Боевая академия", "value": 75 }, { "label": "Бывший герой", "value": 290 }, { "label": "Ведьмы", "value": 756 }, { "label": "Везучий главный герой", "value": 411 }, { "label": "Верные подданные", "value": 410 }, { "label": "Взросление персонажа", "value": 24 }, { "label": "R-15", "value": 570 }], "inputType": filterInputs_1.FilterInputs.Checkbox }];
exports["protected"] = false;
const baseUrl = exports.site;
const domain = baseUrl.split('//')[1];
const popularNovels = function (page, { filters }) {
var _a, _b, _c, _d, _e;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: ((_b = (_a = filters === null || filters === void 0 ? void 0 : filters.tags) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0 > 0) ? { tags: filters === null || filters === void 0 ? void 0 : filters.tags } : {},
hostname: domain,
limit: 40,
page,
},
}),
});
const json = yield result.json();
const novels = (_e = (_d = (_c = json.data) === null || _c === void 0 ? void 0 : _c.projects) === null || _d === void 0 ? void 0 : _d.content) === null || _e === void 0 ? void 0 : _e.map((novel) => {
var _a;
return ({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
};
exports.popularNovels = popularNovels;
const parseNovelAndChapters = function (novelUrl) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Book',
query: 'query Book($url:String){project(project:{fullUrl:$url}){title translationStatus url covers{url}persons(langs:["ru","en","*"]roles:["author","illustrator","original_story","original_design"]){role name{firstName lastName}}genres{nameRu nameEng}tags{nameRu nameEng}annotation{text}subprojects{content{title volumes{content{url shortName chapters{title publishDate url published}}}}}}}',
variables: {
hostname: domain,
project: novelUrl,
url: novelUrl,
},
}),
});
const json = yield result.json();
const novel = {
url: novelUrl,
name: json.data.project.title,
cover: ((_a = json.data.project.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + json.data.project.covers[0].url
: defaultCover_1.defaultCover,
summary: (0, cheerio_1.load)((_b = json.data.project.annotation) === null || _b === void 0 ? void 0 : _b.text).text(),
author: json.data.project.persons[0].name.firstName +
' ' +
json.data.project.persons[0].name.lastName,
status: json.data.project.translationStatus === 'active'
? novelStatus_1.NovelStatus.Ongoing
: novelStatus_1.NovelStatus.Completed,
};
let genres = []
.concat(json.data.project.tags, json.data.project.genres)
.map((item) => (item === null || item === void 0 ? void 0 : item.nameRu) || (item === null || item === void 0 ? void 0 : item.nameEng))
.filter(item => item);
if (genres.length > 0) {
novel.genres = genres.join(',');
}
let novelChapters = [];
json.data.project.subprojects.content.forEach((work) => work.volumes.content.forEach((volume) => volume.chapters.forEach((chapter) => (chapter === null || chapter === void 0 ? void 0 : chapter.published) &&
novelChapters.push({
name: volume.shortName + ' ' + chapter.title,
url: novelUrl + '/' + volume.url + '/' + chapter.url,
releaseTime: (0, dayjs_1.default)(chapter.publishDate).format('LLL'),
}))));
novel.chapters = novelChapters;
return novel;
});
};
exports.parseNovelAndChapters = parseNovelAndChapters;
const parseChapter = function (chapterUrl) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'EReaderData',
query: 'query EReaderData($url:String!,$chapterSelector:Selector!){project(project:{fullUrl:$url}){title url}chapter(chapter:$chapterSelector){title text{text}}}',
variables: {
chapterSelector: {
fullUrl: chapterUrl,
},
url: chapterUrl,
},
}),
});
const json = yield result.json();
return (0, cheerio_1.load)(json.data.chapter.text.text).html();
});
};
exports.parseChapter = parseChapter;
const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b, _c;
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: {
query: searchTerm,
},
hostname: domain,
limit: 40,
page: 1,
},
}),
});
const json = yield result.json();
const novels = [];
(_c = (_b = (_a = json === null || json === void 0 ? void 0 : json.data) === null || _a === void 0 ? void 0 : _a.projects) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.forEach((novel) => {
var _a;
return novels.push({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
exports.searchNovels = searchNovels;
const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
return yield (0, fetch_1.fetchFile)(url, {});
});
exports.fetchImage = fetchImage;
+213
View File
@@ -0,0 +1,213 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.filters = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
const cheerio_1 = require("cheerio");
const dayjs_1 = __importDefault(require("dayjs"));
const fetch_1 = require("@libs/fetch");
// import { parseMadaraDate } from "@libs/parseMadaraDate";
// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
// import { showToast } from "@libs/showToast";
const filterInputs_1 = require("@libs/filterInputs");
const novelStatus_1 = require("@libs/novelStatus");
const defaultCover_1 = require("@libs/defaultCover");
exports.id = "kod.novel";
exports.name = "K.O.D.";
exports.icon = "";
exports.version = "1.0.0";
exports.site = "https://kod.novel.tl";
exports.filters = [{ "key": "tags", "label": "Тэги", "values": [{ "label": "Актёрское искусство", "value": 7 }, { "label": "Забота о детях", "value": 127 }, { "label": "Управление бизнесом", "value": 109 }, { "label": "Шоу-бизнес", "value": 642 }], "inputType": filterInputs_1.FilterInputs.Checkbox }];
exports["protected"] = false;
const baseUrl = exports.site;
const domain = baseUrl.split('//')[1];
const popularNovels = function (page, { filters }) {
var _a, _b, _c, _d, _e;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: ((_b = (_a = filters === null || filters === void 0 ? void 0 : filters.tags) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0 > 0) ? { tags: filters === null || filters === void 0 ? void 0 : filters.tags } : {},
hostname: domain,
limit: 40,
page,
},
}),
});
const json = yield result.json();
const novels = (_e = (_d = (_c = json.data) === null || _c === void 0 ? void 0 : _c.projects) === null || _d === void 0 ? void 0 : _d.content) === null || _e === void 0 ? void 0 : _e.map((novel) => {
var _a;
return ({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
};
exports.popularNovels = popularNovels;
const parseNovelAndChapters = function (novelUrl) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Book',
query: 'query Book($url:String){project(project:{fullUrl:$url}){title translationStatus url covers{url}persons(langs:["ru","en","*"]roles:["author","illustrator","original_story","original_design"]){role name{firstName lastName}}genres{nameRu nameEng}tags{nameRu nameEng}annotation{text}subprojects{content{title volumes{content{url shortName chapters{title publishDate url published}}}}}}}',
variables: {
hostname: domain,
project: novelUrl,
url: novelUrl,
},
}),
});
const json = yield result.json();
const novel = {
url: novelUrl,
name: json.data.project.title,
cover: ((_a = json.data.project.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + json.data.project.covers[0].url
: defaultCover_1.defaultCover,
summary: (0, cheerio_1.load)((_b = json.data.project.annotation) === null || _b === void 0 ? void 0 : _b.text).text(),
author: json.data.project.persons[0].name.firstName +
' ' +
json.data.project.persons[0].name.lastName,
status: json.data.project.translationStatus === 'active'
? novelStatus_1.NovelStatus.Ongoing
: novelStatus_1.NovelStatus.Completed,
};
let genres = []
.concat(json.data.project.tags, json.data.project.genres)
.map((item) => (item === null || item === void 0 ? void 0 : item.nameRu) || (item === null || item === void 0 ? void 0 : item.nameEng))
.filter(item => item);
if (genres.length > 0) {
novel.genres = genres.join(',');
}
let novelChapters = [];
json.data.project.subprojects.content.forEach((work) => work.volumes.content.forEach((volume) => volume.chapters.forEach((chapter) => (chapter === null || chapter === void 0 ? void 0 : chapter.published) &&
novelChapters.push({
name: volume.shortName + ' ' + chapter.title,
url: novelUrl + '/' + volume.url + '/' + chapter.url,
releaseTime: (0, dayjs_1.default)(chapter.publishDate).format('LLL'),
}))));
novel.chapters = novelChapters;
return novel;
});
};
exports.parseNovelAndChapters = parseNovelAndChapters;
const parseChapter = function (chapterUrl) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'EReaderData',
query: 'query EReaderData($url:String!,$chapterSelector:Selector!){project(project:{fullUrl:$url}){title url}chapter(chapter:$chapterSelector){title text{text}}}',
variables: {
chapterSelector: {
fullUrl: chapterUrl,
},
url: chapterUrl,
},
}),
});
const json = yield result.json();
return (0, cheerio_1.load)(json.data.chapter.text.text).html();
});
};
exports.parseChapter = parseChapter;
const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b, _c;
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: {
query: searchTerm,
},
hostname: domain,
limit: 40,
page: 1,
},
}),
});
const json = yield result.json();
const novels = [];
(_c = (_b = (_a = json === null || json === void 0 ? void 0 : json.data) === null || _a === void 0 ? void 0 : _a.projects) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.forEach((novel) => {
var _a;
return novels.push({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
exports.searchNovels = searchNovels;
const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
return yield (0, fetch_1.fetchFile)(url, {});
});
exports.fetchImage = fetchImage;
@@ -0,0 +1,213 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.filters = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
const cheerio_1 = require("cheerio");
const dayjs_1 = __importDefault(require("dayjs"));
const fetch_1 = require("@libs/fetch");
// import { parseMadaraDate } from "@libs/parseMadaraDate";
// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
// import { showToast } from "@libs/showToast";
const filterInputs_1 = require("@libs/filterInputs");
const novelStatus_1 = require("@libs/novelStatus");
const defaultCover_1 = require("@libs/defaultCover");
exports.id = "nightnovel";
exports.name = "Nightnovel";
exports.icon = "";
exports.version = "1.0.0";
exports.site = "https://nightnovel.online";
exports.filters = [{ "key": "tags", "label": "Тэги", "values": [{ "label": "Альтернативная реальность", "value": 30 }, { "label": "Амнезия", "value": 31 }, { "label": "Анал", "value": 33 }, { "label": "Ангелы", "value": 38 }, { "label": "Аристократия", "value": 51 }, { "label": "Артефакты", "value": 58 }, { "label": "Ассасины", "value": 61 }, { "label": "Банды", "value": 302 }, { "label": "БДСМ", "value": 77 }, { "label": "Беременность", "value": 551 }, { "label": "Боги", "value": 318 }, { "label": "Богини", "value": 316 }, { "label": "Боевая академия", "value": 75 }, { "label": "Божественная сила", "value": 317 }, { "label": "Влияние прошлого", "value": 517 }, { "label": "Враги становятся союзниками", "value": 238 }, { "label": "Вынужденные условия проживания", "value": 287 }, { "label": "Герои", "value": 341 }, { "label": "Героиня красавица", "value": 81 }, { "label": "R-18", "value": 571 }], "inputType": filterInputs_1.FilterInputs.Checkbox }];
exports["protected"] = false;
const baseUrl = exports.site;
const domain = baseUrl.split('//')[1];
const popularNovels = function (page, { filters }) {
var _a, _b, _c, _d, _e;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: ((_b = (_a = filters === null || filters === void 0 ? void 0 : filters.tags) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0 > 0) ? { tags: filters === null || filters === void 0 ? void 0 : filters.tags } : {},
hostname: domain,
limit: 40,
page,
},
}),
});
const json = yield result.json();
const novels = (_e = (_d = (_c = json.data) === null || _c === void 0 ? void 0 : _c.projects) === null || _d === void 0 ? void 0 : _d.content) === null || _e === void 0 ? void 0 : _e.map((novel) => {
var _a;
return ({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
};
exports.popularNovels = popularNovels;
const parseNovelAndChapters = function (novelUrl) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Book',
query: 'query Book($url:String){project(project:{fullUrl:$url}){title translationStatus url covers{url}persons(langs:["ru","en","*"]roles:["author","illustrator","original_story","original_design"]){role name{firstName lastName}}genres{nameRu nameEng}tags{nameRu nameEng}annotation{text}subprojects{content{title volumes{content{url shortName chapters{title publishDate url published}}}}}}}',
variables: {
hostname: domain,
project: novelUrl,
url: novelUrl,
},
}),
});
const json = yield result.json();
const novel = {
url: novelUrl,
name: json.data.project.title,
cover: ((_a = json.data.project.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + json.data.project.covers[0].url
: defaultCover_1.defaultCover,
summary: (0, cheerio_1.load)((_b = json.data.project.annotation) === null || _b === void 0 ? void 0 : _b.text).text(),
author: json.data.project.persons[0].name.firstName +
' ' +
json.data.project.persons[0].name.lastName,
status: json.data.project.translationStatus === 'active'
? novelStatus_1.NovelStatus.Ongoing
: novelStatus_1.NovelStatus.Completed,
};
let genres = []
.concat(json.data.project.tags, json.data.project.genres)
.map((item) => (item === null || item === void 0 ? void 0 : item.nameRu) || (item === null || item === void 0 ? void 0 : item.nameEng))
.filter(item => item);
if (genres.length > 0) {
novel.genres = genres.join(',');
}
let novelChapters = [];
json.data.project.subprojects.content.forEach((work) => work.volumes.content.forEach((volume) => volume.chapters.forEach((chapter) => (chapter === null || chapter === void 0 ? void 0 : chapter.published) &&
novelChapters.push({
name: volume.shortName + ' ' + chapter.title,
url: novelUrl + '/' + volume.url + '/' + chapter.url,
releaseTime: (0, dayjs_1.default)(chapter.publishDate).format('LLL'),
}))));
novel.chapters = novelChapters;
return novel;
});
};
exports.parseNovelAndChapters = parseNovelAndChapters;
const parseChapter = function (chapterUrl) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'EReaderData',
query: 'query EReaderData($url:String!,$chapterSelector:Selector!){project(project:{fullUrl:$url}){title url}chapter(chapter:$chapterSelector){title text{text}}}',
variables: {
chapterSelector: {
fullUrl: chapterUrl,
},
url: chapterUrl,
},
}),
});
const json = yield result.json();
return (0, cheerio_1.load)(json.data.chapter.text.text).html();
});
};
exports.parseChapter = parseChapter;
const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b, _c;
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: {
query: searchTerm,
},
hostname: domain,
limit: 40,
page: 1,
},
}),
});
const json = yield result.json();
const novels = [];
(_c = (_b = (_a = json === null || json === void 0 ? void 0 : json.data) === null || _a === void 0 ? void 0 : _a.projects) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.forEach((novel) => {
var _a;
return novels.push({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
exports.searchNovels = searchNovels;
const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
return yield (0, fetch_1.fetchFile)(url, {});
});
exports.fetchImage = fetchImage;
@@ -0,0 +1,213 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.filters = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
const cheerio_1 = require("cheerio");
const dayjs_1 = __importDefault(require("dayjs"));
const fetch_1 = require("@libs/fetch");
// import { parseMadaraDate } from "@libs/parseMadaraDate";
// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
// import { showToast } from "@libs/showToast";
const filterInputs_1 = require("@libs/filterInputs");
const novelStatus_1 = require("@libs/novelStatus");
const defaultCover_1 = require("@libs/defaultCover");
exports.id = "original.novel";
exports.name = "Авторские работы";
exports.icon = "";
exports.version = "1.0.0";
exports.site = "https://original.novel.tl";
exports.filters = [{ "key": "tags", "label": "Тэги", "values": [{ "label": "Агрессивные персонажи", "value": 26 }, { "label": "Академия", "value": 5 }, { "label": "Андроиды", "value": 37 }, { "label": "Антимагия", "value": 41 }, { "label": "Аристократия", "value": 51 }, { "label": "Артефакты", "value": 58 }, { "label": "Брошенные дети", "value": 1 }, { "label": "Вероломные герои/плетение интриг", "value": 424 }, { "label": "Взросление персонажа", "value": 24 }, { "label": "Владелец уникального оружия", "value": 736 }, { "label": "Герой-извращенец", "value": 521 }, { "label": "Главный герой не человек", "value": 488 }, { "label": "Государственные интриги", "value": 212 }, { "label": "Душещипательная история", "value": 335 }, { "label": "Жестокие персонажи", "value": 4 }, { "label": "Зверолюди", "value": 39 }, { "label": "Знания из прошлой жизни", "value": 553 }, { "label": "Искусственный интеллект", "value": 59 }, { "label": "Конфликт в семье", "value": 261 }, { "label": "Королевства", "value": 382 }], "inputType": filterInputs_1.FilterInputs.Checkbox }];
exports["protected"] = false;
const baseUrl = exports.site;
const domain = baseUrl.split('//')[1];
const popularNovels = function (page, { filters }) {
var _a, _b, _c, _d, _e;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: ((_b = (_a = filters === null || filters === void 0 ? void 0 : filters.tags) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0 > 0) ? { tags: filters === null || filters === void 0 ? void 0 : filters.tags } : {},
hostname: domain,
limit: 40,
page,
},
}),
});
const json = yield result.json();
const novels = (_e = (_d = (_c = json.data) === null || _c === void 0 ? void 0 : _c.projects) === null || _d === void 0 ? void 0 : _d.content) === null || _e === void 0 ? void 0 : _e.map((novel) => {
var _a;
return ({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
};
exports.popularNovels = popularNovels;
const parseNovelAndChapters = function (novelUrl) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Book',
query: 'query Book($url:String){project(project:{fullUrl:$url}){title translationStatus url covers{url}persons(langs:["ru","en","*"]roles:["author","illustrator","original_story","original_design"]){role name{firstName lastName}}genres{nameRu nameEng}tags{nameRu nameEng}annotation{text}subprojects{content{title volumes{content{url shortName chapters{title publishDate url published}}}}}}}',
variables: {
hostname: domain,
project: novelUrl,
url: novelUrl,
},
}),
});
const json = yield result.json();
const novel = {
url: novelUrl,
name: json.data.project.title,
cover: ((_a = json.data.project.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + json.data.project.covers[0].url
: defaultCover_1.defaultCover,
summary: (0, cheerio_1.load)((_b = json.data.project.annotation) === null || _b === void 0 ? void 0 : _b.text).text(),
author: json.data.project.persons[0].name.firstName +
' ' +
json.data.project.persons[0].name.lastName,
status: json.data.project.translationStatus === 'active'
? novelStatus_1.NovelStatus.Ongoing
: novelStatus_1.NovelStatus.Completed,
};
let genres = []
.concat(json.data.project.tags, json.data.project.genres)
.map((item) => (item === null || item === void 0 ? void 0 : item.nameRu) || (item === null || item === void 0 ? void 0 : item.nameEng))
.filter(item => item);
if (genres.length > 0) {
novel.genres = genres.join(',');
}
let novelChapters = [];
json.data.project.subprojects.content.forEach((work) => work.volumes.content.forEach((volume) => volume.chapters.forEach((chapter) => (chapter === null || chapter === void 0 ? void 0 : chapter.published) &&
novelChapters.push({
name: volume.shortName + ' ' + chapter.title,
url: novelUrl + '/' + volume.url + '/' + chapter.url,
releaseTime: (0, dayjs_1.default)(chapter.publishDate).format('LLL'),
}))));
novel.chapters = novelChapters;
return novel;
});
};
exports.parseNovelAndChapters = parseNovelAndChapters;
const parseChapter = function (chapterUrl) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'EReaderData',
query: 'query EReaderData($url:String!,$chapterSelector:Selector!){project(project:{fullUrl:$url}){title url}chapter(chapter:$chapterSelector){title text{text}}}',
variables: {
chapterSelector: {
fullUrl: chapterUrl,
},
url: chapterUrl,
},
}),
});
const json = yield result.json();
return (0, cheerio_1.load)(json.data.chapter.text.text).html();
});
};
exports.parseChapter = parseChapter;
const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b, _c;
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: {
query: searchTerm,
},
hostname: domain,
limit: 40,
page: 1,
},
}),
});
const json = yield result.json();
const novels = [];
(_c = (_b = (_a = json === null || json === void 0 ? void 0 : json.data) === null || _a === void 0 ? void 0 : _a.projects) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.forEach((novel) => {
var _a;
return novels.push({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
exports.searchNovels = searchNovels;
const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
return yield (0, fetch_1.fetchFile)(url, {});
});
exports.fetchImage = fetchImage;
+213
View File
@@ -0,0 +1,213 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.filters = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
const cheerio_1 = require("cheerio");
const dayjs_1 = __importDefault(require("dayjs"));
const fetch_1 = require("@libs/fetch");
// import { parseMadaraDate } from "@libs/parseMadaraDate";
// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
// import { showToast } from "@libs/showToast";
const filterInputs_1 = require("@libs/filterInputs");
const novelStatus_1 = require("@libs/novelStatus");
const defaultCover_1 = require("@libs/defaultCover");
exports.id = "red.novel";
exports.name = "Север и Юг";
exports.icon = "";
exports.version = "1.0.0";
exports.site = "https://red.novel.tl";
exports.filters = [{ "key": "tags", "label": "Тэги", "values": [{ "label": "Героиня красавица", "value": 81 }, { "label": "Герой влюбляется первым", "value": 561 }, { "label": "Главный герой — мужчина", "value": 419 }, { "label": "Дружба", "value": 293 }, { "label": "Жизнь в одиночку", "value": 396 }, { "label": "Сложные семейные отношения", "value": 149 }], "inputType": filterInputs_1.FilterInputs.Checkbox }];
exports["protected"] = false;
const baseUrl = exports.site;
const domain = baseUrl.split('//')[1];
const popularNovels = function (page, { filters }) {
var _a, _b, _c, _d, _e;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: ((_b = (_a = filters === null || filters === void 0 ? void 0 : filters.tags) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0 > 0) ? { tags: filters === null || filters === void 0 ? void 0 : filters.tags } : {},
hostname: domain,
limit: 40,
page,
},
}),
});
const json = yield result.json();
const novels = (_e = (_d = (_c = json.data) === null || _c === void 0 ? void 0 : _c.projects) === null || _d === void 0 ? void 0 : _d.content) === null || _e === void 0 ? void 0 : _e.map((novel) => {
var _a;
return ({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
};
exports.popularNovels = popularNovels;
const parseNovelAndChapters = function (novelUrl) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Book',
query: 'query Book($url:String){project(project:{fullUrl:$url}){title translationStatus url covers{url}persons(langs:["ru","en","*"]roles:["author","illustrator","original_story","original_design"]){role name{firstName lastName}}genres{nameRu nameEng}tags{nameRu nameEng}annotation{text}subprojects{content{title volumes{content{url shortName chapters{title publishDate url published}}}}}}}',
variables: {
hostname: domain,
project: novelUrl,
url: novelUrl,
},
}),
});
const json = yield result.json();
const novel = {
url: novelUrl,
name: json.data.project.title,
cover: ((_a = json.data.project.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + json.data.project.covers[0].url
: defaultCover_1.defaultCover,
summary: (0, cheerio_1.load)((_b = json.data.project.annotation) === null || _b === void 0 ? void 0 : _b.text).text(),
author: json.data.project.persons[0].name.firstName +
' ' +
json.data.project.persons[0].name.lastName,
status: json.data.project.translationStatus === 'active'
? novelStatus_1.NovelStatus.Ongoing
: novelStatus_1.NovelStatus.Completed,
};
let genres = []
.concat(json.data.project.tags, json.data.project.genres)
.map((item) => (item === null || item === void 0 ? void 0 : item.nameRu) || (item === null || item === void 0 ? void 0 : item.nameEng))
.filter(item => item);
if (genres.length > 0) {
novel.genres = genres.join(',');
}
let novelChapters = [];
json.data.project.subprojects.content.forEach((work) => work.volumes.content.forEach((volume) => volume.chapters.forEach((chapter) => (chapter === null || chapter === void 0 ? void 0 : chapter.published) &&
novelChapters.push({
name: volume.shortName + ' ' + chapter.title,
url: novelUrl + '/' + volume.url + '/' + chapter.url,
releaseTime: (0, dayjs_1.default)(chapter.publishDate).format('LLL'),
}))));
novel.chapters = novelChapters;
return novel;
});
};
exports.parseNovelAndChapters = parseNovelAndChapters;
const parseChapter = function (chapterUrl) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'EReaderData',
query: 'query EReaderData($url:String!,$chapterSelector:Selector!){project(project:{fullUrl:$url}){title url}chapter(chapter:$chapterSelector){title text{text}}}',
variables: {
chapterSelector: {
fullUrl: chapterUrl,
},
url: chapterUrl,
},
}),
});
const json = yield result.json();
return (0, cheerio_1.load)(json.data.chapter.text.text).html();
});
};
exports.parseChapter = parseChapter;
const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b, _c;
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: {
query: searchTerm,
},
hostname: domain,
limit: 40,
page: 1,
},
}),
});
const json = yield result.json();
const novels = [];
(_c = (_b = (_a = json === null || json === void 0 ? void 0 : json.data) === null || _a === void 0 ? void 0 : _a.projects) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.forEach((novel) => {
var _a;
return novels.push({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
exports.searchNovels = searchNovels;
const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
return yield (0, fetch_1.fetchFile)(url, {});
});
exports.fetchImage = fetchImage;
+213
View File
@@ -0,0 +1,213 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.filters = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
const cheerio_1 = require("cheerio");
const dayjs_1 = __importDefault(require("dayjs"));
const fetch_1 = require("@libs/fetch");
// import { parseMadaraDate } from "@libs/parseMadaraDate";
// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
// import { showToast } from "@libs/showToast";
const filterInputs_1 = require("@libs/filterInputs");
const novelStatus_1 = require("@libs/novelStatus");
const defaultCover_1 = require("@libs/defaultCover");
exports.id = "ruranobe";
exports.name = "РуРанобэ";
exports.icon = "";
exports.version = "1.0.0";
exports.site = "https://ruranobe.ru";
exports.filters = [{ "key": "tags", "label": "Тэги", "values": [{ "label": "Автоматы", "value": 64 }, { "label": "Агрессивные персонажи", "value": 26 }, { "label": "Ад", "value": 338 }, { "label": "Адаптация манги", "value": 8 }, { "label": "Академия", "value": 5 }, { "label": "Алхимия", "value": 27 }, { "label": "Альтернативная реальность", "value": 30 }, { "label": "Амнезия", "value": 31 }, { "label": "Анабиоз", "value": 170 }, { "label": "Ангелы", "value": 38 }, { "label": "Андроиды", "value": 37 }, { "label": "Антигерой", "value": 43 }, { "label": "Антимагия", "value": 41 }, { "label": "Апатичный главный герой", "value": 46 }, { "label": "Апокалипсис", "value": 47 }, { "label": "Аристократия", "value": 51 }, { "label": "Артефакты", "value": 58 }, { "label": "Асоциальный главный герой", "value": 42 }, { "label": "R-15", "value": 570 }, { "label": "R-18", "value": 571 }], "inputType": filterInputs_1.FilterInputs.Checkbox }];
exports["protected"] = false;
const baseUrl = exports.site;
const domain = baseUrl.split('//')[1];
const popularNovels = function (page, { filters }) {
var _a, _b, _c, _d, _e;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: ((_b = (_a = filters === null || filters === void 0 ? void 0 : filters.tags) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0 > 0) ? { tags: filters === null || filters === void 0 ? void 0 : filters.tags } : {},
hostname: domain,
limit: 40,
page,
},
}),
});
const json = yield result.json();
const novels = (_e = (_d = (_c = json.data) === null || _c === void 0 ? void 0 : _c.projects) === null || _d === void 0 ? void 0 : _d.content) === null || _e === void 0 ? void 0 : _e.map((novel) => {
var _a;
return ({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
};
exports.popularNovels = popularNovels;
const parseNovelAndChapters = function (novelUrl) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Book',
query: 'query Book($url:String){project(project:{fullUrl:$url}){title translationStatus url covers{url}persons(langs:["ru","en","*"]roles:["author","illustrator","original_story","original_design"]){role name{firstName lastName}}genres{nameRu nameEng}tags{nameRu nameEng}annotation{text}subprojects{content{title volumes{content{url shortName chapters{title publishDate url published}}}}}}}',
variables: {
hostname: domain,
project: novelUrl,
url: novelUrl,
},
}),
});
const json = yield result.json();
const novel = {
url: novelUrl,
name: json.data.project.title,
cover: ((_a = json.data.project.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + json.data.project.covers[0].url
: defaultCover_1.defaultCover,
summary: (0, cheerio_1.load)((_b = json.data.project.annotation) === null || _b === void 0 ? void 0 : _b.text).text(),
author: json.data.project.persons[0].name.firstName +
' ' +
json.data.project.persons[0].name.lastName,
status: json.data.project.translationStatus === 'active'
? novelStatus_1.NovelStatus.Ongoing
: novelStatus_1.NovelStatus.Completed,
};
let genres = []
.concat(json.data.project.tags, json.data.project.genres)
.map((item) => (item === null || item === void 0 ? void 0 : item.nameRu) || (item === null || item === void 0 ? void 0 : item.nameEng))
.filter(item => item);
if (genres.length > 0) {
novel.genres = genres.join(',');
}
let novelChapters = [];
json.data.project.subprojects.content.forEach((work) => work.volumes.content.forEach((volume) => volume.chapters.forEach((chapter) => (chapter === null || chapter === void 0 ? void 0 : chapter.published) &&
novelChapters.push({
name: volume.shortName + ' ' + chapter.title,
url: novelUrl + '/' + volume.url + '/' + chapter.url,
releaseTime: (0, dayjs_1.default)(chapter.publishDate).format('LLL'),
}))));
novel.chapters = novelChapters;
return novel;
});
};
exports.parseNovelAndChapters = parseNovelAndChapters;
const parseChapter = function (chapterUrl) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'EReaderData',
query: 'query EReaderData($url:String!,$chapterSelector:Selector!){project(project:{fullUrl:$url}){title url}chapter(chapter:$chapterSelector){title text{text}}}',
variables: {
chapterSelector: {
fullUrl: chapterUrl,
},
url: chapterUrl,
},
}),
});
const json = yield result.json();
return (0, cheerio_1.load)(json.data.chapter.text.text).html();
});
};
exports.parseChapter = parseChapter;
const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b, _c;
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: {
query: searchTerm,
},
hostname: domain,
limit: 40,
page: 1,
},
}),
});
const json = yield result.json();
const novels = [];
(_c = (_b = (_a = json === null || json === void 0 ? void 0 : json.data) === null || _a === void 0 ? void 0 : _a.projects) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.forEach((novel) => {
var _a;
return novels.push({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
exports.searchNovels = searchNovels;
const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
return yield (0, fetch_1.fetchFile)(url, {});
});
exports.fetchImage = fetchImage;
@@ -0,0 +1,213 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.filters = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
const cheerio_1 = require("cheerio");
const dayjs_1 = __importDefault(require("dayjs"));
const fetch_1 = require("@libs/fetch");
// import { parseMadaraDate } from "@libs/parseMadaraDate";
// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
// import { showToast } from "@libs/showToast";
const filterInputs_1 = require("@libs/filterInputs");
const novelStatus_1 = require("@libs/novelStatus");
const defaultCover_1 = require("@libs/defaultCover");
exports.id = "sferdrakon.novel";
exports.name = "Уголок дракона";
exports.icon = "";
exports.version = "1.0.0";
exports.site = "https://sferdrakon.novel.tl";
exports.filters = [{ "key": "tags", "label": "Тэги", "values": [{ "label": "Главный герой — мужчина", "value": 419 }, { "label": "Демоны", "value": 193 }, { "label": "Драконы", "value": 218 }, { "label": "Есть аниме-адаптация", "value": 10 }, { "label": "Есть видеоигра", "value": 13 }, { "label": "Есть манга-адаптация", "value": 14 }, { "label": "Звероподобные", "value": 79 }, { "label": "Изнасилование", "value": 574 }, { "label": "Королевская особа", "value": 596 }, { "label": "Магия", "value": 412 }, { "label": "Магия призыва", "value": 694 }, { "label": "Наездники на драконах", "value": 216 }, { "label": "Рыцари", "value": 383 }, { "label": "Цундере", "value": 728 }, { "label": "Эльфы", "value": 235 }], "inputType": filterInputs_1.FilterInputs.Checkbox }];
exports["protected"] = false;
const baseUrl = exports.site;
const domain = baseUrl.split('//')[1];
const popularNovels = function (page, { filters }) {
var _a, _b, _c, _d, _e;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: ((_b = (_a = filters === null || filters === void 0 ? void 0 : filters.tags) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0 > 0) ? { tags: filters === null || filters === void 0 ? void 0 : filters.tags } : {},
hostname: domain,
limit: 40,
page,
},
}),
});
const json = yield result.json();
const novels = (_e = (_d = (_c = json.data) === null || _c === void 0 ? void 0 : _c.projects) === null || _d === void 0 ? void 0 : _d.content) === null || _e === void 0 ? void 0 : _e.map((novel) => {
var _a;
return ({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
};
exports.popularNovels = popularNovels;
const parseNovelAndChapters = function (novelUrl) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Book',
query: 'query Book($url:String){project(project:{fullUrl:$url}){title translationStatus url covers{url}persons(langs:["ru","en","*"]roles:["author","illustrator","original_story","original_design"]){role name{firstName lastName}}genres{nameRu nameEng}tags{nameRu nameEng}annotation{text}subprojects{content{title volumes{content{url shortName chapters{title publishDate url published}}}}}}}',
variables: {
hostname: domain,
project: novelUrl,
url: novelUrl,
},
}),
});
const json = yield result.json();
const novel = {
url: novelUrl,
name: json.data.project.title,
cover: ((_a = json.data.project.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + json.data.project.covers[0].url
: defaultCover_1.defaultCover,
summary: (0, cheerio_1.load)((_b = json.data.project.annotation) === null || _b === void 0 ? void 0 : _b.text).text(),
author: json.data.project.persons[0].name.firstName +
' ' +
json.data.project.persons[0].name.lastName,
status: json.data.project.translationStatus === 'active'
? novelStatus_1.NovelStatus.Ongoing
: novelStatus_1.NovelStatus.Completed,
};
let genres = []
.concat(json.data.project.tags, json.data.project.genres)
.map((item) => (item === null || item === void 0 ? void 0 : item.nameRu) || (item === null || item === void 0 ? void 0 : item.nameEng))
.filter(item => item);
if (genres.length > 0) {
novel.genres = genres.join(',');
}
let novelChapters = [];
json.data.project.subprojects.content.forEach((work) => work.volumes.content.forEach((volume) => volume.chapters.forEach((chapter) => (chapter === null || chapter === void 0 ? void 0 : chapter.published) &&
novelChapters.push({
name: volume.shortName + ' ' + chapter.title,
url: novelUrl + '/' + volume.url + '/' + chapter.url,
releaseTime: (0, dayjs_1.default)(chapter.publishDate).format('LLL'),
}))));
novel.chapters = novelChapters;
return novel;
});
};
exports.parseNovelAndChapters = parseNovelAndChapters;
const parseChapter = function (chapterUrl) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'EReaderData',
query: 'query EReaderData($url:String!,$chapterSelector:Selector!){project(project:{fullUrl:$url}){title url}chapter(chapter:$chapterSelector){title text{text}}}',
variables: {
chapterSelector: {
fullUrl: chapterUrl,
},
url: chapterUrl,
},
}),
});
const json = yield result.json();
return (0, cheerio_1.load)(json.data.chapter.text.text).html();
});
};
exports.parseChapter = parseChapter;
const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b, _c;
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: {
query: searchTerm,
},
hostname: domain,
limit: 40,
page: 1,
},
}),
});
const json = yield result.json();
const novels = [];
(_c = (_b = (_a = json === null || json === void 0 ? void 0 : json.data) === null || _a === void 0 ? void 0 : _a.projects) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.forEach((novel) => {
var _a;
return novels.push({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
exports.searchNovels = searchNovels;
const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
return yield (0, fetch_1.fetchFile)(url, {});
});
exports.fetchImage = fetchImage;
+213
View File
@@ -0,0 +1,213 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.filters = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
const cheerio_1 = require("cheerio");
const dayjs_1 = __importDefault(require("dayjs"));
const fetch_1 = require("@libs/fetch");
// import { parseMadaraDate } from "@libs/parseMadaraDate";
// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
// import { showToast } from "@libs/showToast";
const filterInputs_1 = require("@libs/filterInputs");
const novelStatus_1 = require("@libs/novelStatus");
const defaultCover_1 = require("@libs/defaultCover");
exports.id = "si.novel";
exports.name = "Сказочные истории";
exports.icon = "";
exports.version = "1.0.0";
exports.site = "https://si.novel.tl";
exports.filters = [{ "key": "tags", "label": "Тэги", "values": [{ "label": "Аристократия", "value": 51 }, { "label": "Война", "value": 750 }, { "label": "Главная героиня — женщина", "value": 277 }, { "label": "Драконы", "value": 218 }, { "label": "Древний Китай", "value": 34 }, { "label": "Жестокие персонажи", "value": 4 }, { "label": "Злобные благородные девы", "value": 743 }, { "label": "Комедийный подтекст", "value": 147 }, { "label": "Культивация", "value": 171 }, { "label": "Магия", "value": 412 }, { "label": "Отомэ-игры", "value": 504 }, { "label": "Перерождение в другом мире", "value": 580 }, { "label": "Перерождение в другом мире", "value": 720 }, { "label": "Повелитель демонов", "value": 191 }, { "label": "Попаданец в другой мир", "value": 723 }, { "label": "Смерть", "value": 185 }, { "label": "Средневековье", "value": 436 }, { "label": "Фэнтези", "value": 267 }, { "label": "Харизматичный протагонист", "value": 120 }, { "label": "Хитрый главный герой", "value": 173 }], "inputType": filterInputs_1.FilterInputs.Checkbox }];
exports["protected"] = false;
const baseUrl = exports.site;
const domain = baseUrl.split('//')[1];
const popularNovels = function (page, { filters }) {
var _a, _b, _c, _d, _e;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: ((_b = (_a = filters === null || filters === void 0 ? void 0 : filters.tags) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0 > 0) ? { tags: filters === null || filters === void 0 ? void 0 : filters.tags } : {},
hostname: domain,
limit: 40,
page,
},
}),
});
const json = yield result.json();
const novels = (_e = (_d = (_c = json.data) === null || _c === void 0 ? void 0 : _c.projects) === null || _d === void 0 ? void 0 : _d.content) === null || _e === void 0 ? void 0 : _e.map((novel) => {
var _a;
return ({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
};
exports.popularNovels = popularNovels;
const parseNovelAndChapters = function (novelUrl) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Book',
query: 'query Book($url:String){project(project:{fullUrl:$url}){title translationStatus url covers{url}persons(langs:["ru","en","*"]roles:["author","illustrator","original_story","original_design"]){role name{firstName lastName}}genres{nameRu nameEng}tags{nameRu nameEng}annotation{text}subprojects{content{title volumes{content{url shortName chapters{title publishDate url published}}}}}}}',
variables: {
hostname: domain,
project: novelUrl,
url: novelUrl,
},
}),
});
const json = yield result.json();
const novel = {
url: novelUrl,
name: json.data.project.title,
cover: ((_a = json.data.project.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + json.data.project.covers[0].url
: defaultCover_1.defaultCover,
summary: (0, cheerio_1.load)((_b = json.data.project.annotation) === null || _b === void 0 ? void 0 : _b.text).text(),
author: json.data.project.persons[0].name.firstName +
' ' +
json.data.project.persons[0].name.lastName,
status: json.data.project.translationStatus === 'active'
? novelStatus_1.NovelStatus.Ongoing
: novelStatus_1.NovelStatus.Completed,
};
let genres = []
.concat(json.data.project.tags, json.data.project.genres)
.map((item) => (item === null || item === void 0 ? void 0 : item.nameRu) || (item === null || item === void 0 ? void 0 : item.nameEng))
.filter(item => item);
if (genres.length > 0) {
novel.genres = genres.join(',');
}
let novelChapters = [];
json.data.project.subprojects.content.forEach((work) => work.volumes.content.forEach((volume) => volume.chapters.forEach((chapter) => (chapter === null || chapter === void 0 ? void 0 : chapter.published) &&
novelChapters.push({
name: volume.shortName + ' ' + chapter.title,
url: novelUrl + '/' + volume.url + '/' + chapter.url,
releaseTime: (0, dayjs_1.default)(chapter.publishDate).format('LLL'),
}))));
novel.chapters = novelChapters;
return novel;
});
};
exports.parseNovelAndChapters = parseNovelAndChapters;
const parseChapter = function (chapterUrl) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'EReaderData',
query: 'query EReaderData($url:String!,$chapterSelector:Selector!){project(project:{fullUrl:$url}){title url}chapter(chapter:$chapterSelector){title text{text}}}',
variables: {
chapterSelector: {
fullUrl: chapterUrl,
},
url: chapterUrl,
},
}),
});
const json = yield result.json();
return (0, cheerio_1.load)(json.data.chapter.text.text).html();
});
};
exports.parseChapter = parseChapter;
const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b, _c;
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: {
query: searchTerm,
},
hostname: domain,
limit: 40,
page: 1,
},
}),
});
const json = yield result.json();
const novels = [];
(_c = (_b = (_a = json === null || json === void 0 ? void 0 : json.data) === null || _a === void 0 ? void 0 : _a.projects) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.forEach((novel) => {
var _a;
return novels.push({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
exports.searchNovels = searchNovels;
const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
return yield (0, fetch_1.fetchFile)(url, {});
});
exports.fetchImage = fetchImage;
@@ -0,0 +1,213 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.filters = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
const cheerio_1 = require("cheerio");
const dayjs_1 = __importDefault(require("dayjs"));
const fetch_1 = require("@libs/fetch");
// import { parseMadaraDate } from "@libs/parseMadaraDate";
// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
// import { showToast } from "@libs/showToast";
const filterInputs_1 = require("@libs/filterInputs");
const novelStatus_1 = require("@libs/novelStatus");
const defaultCover_1 = require("@libs/defaultCover");
exports.id = "snailulitka.novel";
exports.name = "Snailulitka";
exports.icon = "";
exports.version = "1.0.0";
exports.site = "https://snailulitka.novel.tl";
exports.filters = [{ "key": "tags", "label": "Тэги", "values": [{ "label": "Алхимия", "value": 27 }, { "label": "Ассасины", "value": 61 }, { "label": "Бедный главный герой", "value": 541 }, { "label": "Богачи", "value": 753 }, { "label": "Виртуальная реальность", "value": 744 }, { "label": "Война", "value": 750 }, { "label": "Геймеры", "value": 301 }, { "label": "Героиня красавица", "value": 81 }, { "label": "Герой красавец", "value": 329 }, { "label": "Гильдии", "value": 324 }, { "label": "Главный герой - гений", "value": 308 }, { "label": "Главный герой — знаменитость", "value": 263 }, { "label": "Главный герой — мужчина", "value": 419 }, { "label": "Дворфы", "value": 224 }, { "label": "Драконы", "value": 218 }, { "label": "Есть маньхуа-адаптация", "value": 15 }, { "label": "Игровая рейтинговая система", "value": 300 }, { "label": "Книги навыков", "value": 654 }, { "label": "Лекари", "value": 334 }, { "label": "Месть", "value": 588 }], "inputType": filterInputs_1.FilterInputs.Checkbox }];
exports["protected"] = false;
const baseUrl = exports.site;
const domain = baseUrl.split('//')[1];
const popularNovels = function (page, { filters }) {
var _a, _b, _c, _d, _e;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: ((_b = (_a = filters === null || filters === void 0 ? void 0 : filters.tags) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0 > 0) ? { tags: filters === null || filters === void 0 ? void 0 : filters.tags } : {},
hostname: domain,
limit: 40,
page,
},
}),
});
const json = yield result.json();
const novels = (_e = (_d = (_c = json.data) === null || _c === void 0 ? void 0 : _c.projects) === null || _d === void 0 ? void 0 : _d.content) === null || _e === void 0 ? void 0 : _e.map((novel) => {
var _a;
return ({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
};
exports.popularNovels = popularNovels;
const parseNovelAndChapters = function (novelUrl) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Book',
query: 'query Book($url:String){project(project:{fullUrl:$url}){title translationStatus url covers{url}persons(langs:["ru","en","*"]roles:["author","illustrator","original_story","original_design"]){role name{firstName lastName}}genres{nameRu nameEng}tags{nameRu nameEng}annotation{text}subprojects{content{title volumes{content{url shortName chapters{title publishDate url published}}}}}}}',
variables: {
hostname: domain,
project: novelUrl,
url: novelUrl,
},
}),
});
const json = yield result.json();
const novel = {
url: novelUrl,
name: json.data.project.title,
cover: ((_a = json.data.project.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + json.data.project.covers[0].url
: defaultCover_1.defaultCover,
summary: (0, cheerio_1.load)((_b = json.data.project.annotation) === null || _b === void 0 ? void 0 : _b.text).text(),
author: json.data.project.persons[0].name.firstName +
' ' +
json.data.project.persons[0].name.lastName,
status: json.data.project.translationStatus === 'active'
? novelStatus_1.NovelStatus.Ongoing
: novelStatus_1.NovelStatus.Completed,
};
let genres = []
.concat(json.data.project.tags, json.data.project.genres)
.map((item) => (item === null || item === void 0 ? void 0 : item.nameRu) || (item === null || item === void 0 ? void 0 : item.nameEng))
.filter(item => item);
if (genres.length > 0) {
novel.genres = genres.join(',');
}
let novelChapters = [];
json.data.project.subprojects.content.forEach((work) => work.volumes.content.forEach((volume) => volume.chapters.forEach((chapter) => (chapter === null || chapter === void 0 ? void 0 : chapter.published) &&
novelChapters.push({
name: volume.shortName + ' ' + chapter.title,
url: novelUrl + '/' + volume.url + '/' + chapter.url,
releaseTime: (0, dayjs_1.default)(chapter.publishDate).format('LLL'),
}))));
novel.chapters = novelChapters;
return novel;
});
};
exports.parseNovelAndChapters = parseNovelAndChapters;
const parseChapter = function (chapterUrl) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'EReaderData',
query: 'query EReaderData($url:String!,$chapterSelector:Selector!){project(project:{fullUrl:$url}){title url}chapter(chapter:$chapterSelector){title text{text}}}',
variables: {
chapterSelector: {
fullUrl: chapterUrl,
},
url: chapterUrl,
},
}),
});
const json = yield result.json();
return (0, cheerio_1.load)(json.data.chapter.text.text).html();
});
};
exports.parseChapter = parseChapter;
const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b, _c;
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: {
query: searchTerm,
},
hostname: domain,
limit: 40,
page: 1,
},
}),
});
const json = yield result.json();
const novels = [];
(_c = (_b = (_a = json === null || json === void 0 ? void 0 : json.data) === null || _a === void 0 ? void 0 : _a.projects) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.forEach((novel) => {
var _a;
return novels.push({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
exports.searchNovels = searchNovels;
const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
return yield (0, fetch_1.fetchFile)(url, {});
});
exports.fetchImage = fetchImage;
@@ -0,0 +1,213 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.filters = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
const cheerio_1 = require("cheerio");
const dayjs_1 = __importDefault(require("dayjs"));
const fetch_1 = require("@libs/fetch");
// import { parseMadaraDate } from "@libs/parseMadaraDate";
// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
// import { showToast } from "@libs/showToast";
const filterInputs_1 = require("@libs/filterInputs");
const novelStatus_1 = require("@libs/novelStatus");
const defaultCover_1 = require("@libs/defaultCover");
exports.id = "tsundoku.novel";
exports.name = "TsundokuTrans";
exports.icon = "";
exports.version = "1.0.0";
exports.site = "https://tsundoku.novel.tl";
exports.filters = [{ "key": "tags", "label": "Тэги", "values": [{ "label": "Боги", "value": 318 }, { "label": "Боевая академия", "value": 75 }, { "label": "Вампиры", "value": 742 }, { "label": "Влияние прошлого", "value": 517 }, { "label": "Война", "value": 750 }, { "label": "Главная героиня — женщина", "value": 277 }, { "label": "Главный герой — мужчина", "value": 419 }, { "label": "Демоны", "value": 193 }, { "label": "Драконы", "value": 218 }, { "label": "Королевская особа", "value": 596 }, { "label": "Коррупция", "value": 157 }, { "label": "Магия", "value": 412 }, { "label": "Мастер подземелий", "value": 222 }, { "label": "Мечи и магия", "value": 697 }, { "label": "Мечники", "value": 698 }, { "label": "Монстры", "value": 454 }, { "label": "Недооцененный главный герой", "value": 734 }, { "label": "От слабого к сильному", "value": 752 }, { "label": "R-15", "value": 570 }, { "label": "R-18", "value": 571 }], "inputType": filterInputs_1.FilterInputs.Checkbox }];
exports["protected"] = false;
const baseUrl = exports.site;
const domain = baseUrl.split('//')[1];
const popularNovels = function (page, { filters }) {
var _a, _b, _c, _d, _e;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: ((_b = (_a = filters === null || filters === void 0 ? void 0 : filters.tags) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0 > 0) ? { tags: filters === null || filters === void 0 ? void 0 : filters.tags } : {},
hostname: domain,
limit: 40,
page,
},
}),
});
const json = yield result.json();
const novels = (_e = (_d = (_c = json.data) === null || _c === void 0 ? void 0 : _c.projects) === null || _d === void 0 ? void 0 : _d.content) === null || _e === void 0 ? void 0 : _e.map((novel) => {
var _a;
return ({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
};
exports.popularNovels = popularNovels;
const parseNovelAndChapters = function (novelUrl) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Book',
query: 'query Book($url:String){project(project:{fullUrl:$url}){title translationStatus url covers{url}persons(langs:["ru","en","*"]roles:["author","illustrator","original_story","original_design"]){role name{firstName lastName}}genres{nameRu nameEng}tags{nameRu nameEng}annotation{text}subprojects{content{title volumes{content{url shortName chapters{title publishDate url published}}}}}}}',
variables: {
hostname: domain,
project: novelUrl,
url: novelUrl,
},
}),
});
const json = yield result.json();
const novel = {
url: novelUrl,
name: json.data.project.title,
cover: ((_a = json.data.project.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + json.data.project.covers[0].url
: defaultCover_1.defaultCover,
summary: (0, cheerio_1.load)((_b = json.data.project.annotation) === null || _b === void 0 ? void 0 : _b.text).text(),
author: json.data.project.persons[0].name.firstName +
' ' +
json.data.project.persons[0].name.lastName,
status: json.data.project.translationStatus === 'active'
? novelStatus_1.NovelStatus.Ongoing
: novelStatus_1.NovelStatus.Completed,
};
let genres = []
.concat(json.data.project.tags, json.data.project.genres)
.map((item) => (item === null || item === void 0 ? void 0 : item.nameRu) || (item === null || item === void 0 ? void 0 : item.nameEng))
.filter(item => item);
if (genres.length > 0) {
novel.genres = genres.join(',');
}
let novelChapters = [];
json.data.project.subprojects.content.forEach((work) => work.volumes.content.forEach((volume) => volume.chapters.forEach((chapter) => (chapter === null || chapter === void 0 ? void 0 : chapter.published) &&
novelChapters.push({
name: volume.shortName + ' ' + chapter.title,
url: novelUrl + '/' + volume.url + '/' + chapter.url,
releaseTime: (0, dayjs_1.default)(chapter.publishDate).format('LLL'),
}))));
novel.chapters = novelChapters;
return novel;
});
};
exports.parseNovelAndChapters = parseNovelAndChapters;
const parseChapter = function (chapterUrl) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'EReaderData',
query: 'query EReaderData($url:String!,$chapterSelector:Selector!){project(project:{fullUrl:$url}){title url}chapter(chapter:$chapterSelector){title text{text}}}',
variables: {
chapterSelector: {
fullUrl: chapterUrl,
},
url: chapterUrl,
},
}),
});
const json = yield result.json();
return (0, cheerio_1.load)(json.data.chapter.text.text).html();
});
};
exports.parseChapter = parseChapter;
const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b, _c;
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: {
query: searchTerm,
},
hostname: domain,
limit: 40,
page: 1,
},
}),
});
const json = yield result.json();
const novels = [];
(_c = (_b = (_a = json === null || json === void 0 ? void 0 : json.data) === null || _a === void 0 ? void 0 : _a.projects) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.forEach((novel) => {
var _a;
return novels.push({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
exports.searchNovels = searchNovels;
const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
return yield (0, fetch_1.fetchFile)(url, {});
});
exports.fetchImage = fetchImage;
+213
View File
@@ -0,0 +1,213 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fetchImage = exports.searchNovels = exports.parseChapter = exports.parseNovelAndChapters = exports.popularNovels = exports.filters = exports.site = exports.version = exports.icon = exports.name = exports.id = void 0;
const cheerio_1 = require("cheerio");
const dayjs_1 = __importDefault(require("dayjs"));
const fetch_1 = require("@libs/fetch");
// import { parseMadaraDate } from "@libs/parseMadaraDate";
// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
// import { showToast } from "@libs/showToast";
const filterInputs_1 = require("@libs/filterInputs");
const novelStatus_1 = require("@libs/novelStatus");
const defaultCover_1 = require("@libs/defaultCover");
exports.id = "ukr.novel";
exports.name = "Переклади українською мовою";
exports.icon = "";
exports.version = "1.0.0";
exports.site = "https://ukr.novel.tl";
exports.filters = [{ "key": "tags", "label": "Тэги", "values": [{ "label": "Альтернативная реальность", "value": 30 }, { "label": "Апатичный главный герой", "value": 46 }, { "label": "Асоциальный главный герой", "value": 42 }, { "label": "Владелец уникального оружия", "value": 736 }, { "label": "Гарем рабов", "value": 656 }, { "label": "Герои", "value": 341 }, { "label": "Героиня красавица", "value": 81 }, { "label": "Герой использует щит", "value": 636 }, { "label": "Герой-трудяга", "value": 330 }, { "label": "Главный герой — мужчина", "value": 419 }, { "label": "Глухой к любви герой", "value": 194 }, { "label": "Демоны", "value": 193 }, { "label": "Друзья детства", "value": 128 }, { "label": "Есть аниме-адаптация", "value": 10 }, { "label": "Есть манга-адаптация", "value": 14 }, { "label": "Есть CD дорама-адаптация", "value": 12 }, { "label": "Зверолюди", "value": 39 }, { "label": "Магия", "value": 412 }, { "label": "Магия призыва", "value": 694 }, { "label": "От слабого к сильному", "value": 752 }], "inputType": filterInputs_1.FilterInputs.Checkbox }];
exports["protected"] = false;
const baseUrl = exports.site;
const domain = baseUrl.split('//')[1];
const popularNovels = function (page, { filters }) {
var _a, _b, _c, _d, _e;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: ((_b = (_a = filters === null || filters === void 0 ? void 0 : filters.tags) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0 > 0) ? { tags: filters === null || filters === void 0 ? void 0 : filters.tags } : {},
hostname: domain,
limit: 40,
page,
},
}),
});
const json = yield result.json();
const novels = (_e = (_d = (_c = json.data) === null || _c === void 0 ? void 0 : _c.projects) === null || _d === void 0 ? void 0 : _d.content) === null || _e === void 0 ? void 0 : _e.map((novel) => {
var _a;
return ({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
};
exports.popularNovels = popularNovels;
const parseNovelAndChapters = function (novelUrl) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Book',
query: 'query Book($url:String){project(project:{fullUrl:$url}){title translationStatus url covers{url}persons(langs:["ru","en","*"]roles:["author","illustrator","original_story","original_design"]){role name{firstName lastName}}genres{nameRu nameEng}tags{nameRu nameEng}annotation{text}subprojects{content{title volumes{content{url shortName chapters{title publishDate url published}}}}}}}',
variables: {
hostname: domain,
project: novelUrl,
url: novelUrl,
},
}),
});
const json = yield result.json();
const novel = {
url: novelUrl,
name: json.data.project.title,
cover: ((_a = json.data.project.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + json.data.project.covers[0].url
: defaultCover_1.defaultCover,
summary: (0, cheerio_1.load)((_b = json.data.project.annotation) === null || _b === void 0 ? void 0 : _b.text).text(),
author: json.data.project.persons[0].name.firstName +
' ' +
json.data.project.persons[0].name.lastName,
status: json.data.project.translationStatus === 'active'
? novelStatus_1.NovelStatus.Ongoing
: novelStatus_1.NovelStatus.Completed,
};
let genres = []
.concat(json.data.project.tags, json.data.project.genres)
.map((item) => (item === null || item === void 0 ? void 0 : item.nameRu) || (item === null || item === void 0 ? void 0 : item.nameEng))
.filter(item => item);
if (genres.length > 0) {
novel.genres = genres.join(',');
}
let novelChapters = [];
json.data.project.subprojects.content.forEach((work) => work.volumes.content.forEach((volume) => volume.chapters.forEach((chapter) => (chapter === null || chapter === void 0 ? void 0 : chapter.published) &&
novelChapters.push({
name: volume.shortName + ' ' + chapter.title,
url: novelUrl + '/' + volume.url + '/' + chapter.url,
releaseTime: (0, dayjs_1.default)(chapter.publishDate).format('LLL'),
}))));
novel.chapters = novelChapters;
return novel;
});
};
exports.parseNovelAndChapters = parseNovelAndChapters;
const parseChapter = function (chapterUrl) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'EReaderData',
query: 'query EReaderData($url:String!,$chapterSelector:Selector!){project(project:{fullUrl:$url}){title url}chapter(chapter:$chapterSelector){title text{text}}}',
variables: {
chapterSelector: {
fullUrl: chapterUrl,
},
url: chapterUrl,
},
}),
});
const json = yield result.json();
return (0, cheerio_1.load)(json.data.chapter.text.text).html();
});
};
exports.parseChapter = parseChapter;
const searchNovels = (searchTerm) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b, _c;
const result = yield (0, fetch_1.fetchApi)('https://api.novel.tl/api/site/v2/graphql', {
method: 'post',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Content-Type': 'application/json',
'Alt-Used': 'api.novel.tl',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
},
referrer: baseUrl,
body: JSON.stringify({
operationName: 'Projects',
query: 'query Projects($hostname:String! $filter:SearchFilter $page:Int $limit:Int){projects(section:{fullUrl:$hostname}filter:$filter page:{pageSize:$limit,pageNumber:$page}){content{title url covers{url}}}}',
variables: {
filter: {
query: searchTerm,
},
hostname: domain,
limit: 40,
page: 1,
},
}),
});
const json = yield result.json();
const novels = [];
(_c = (_b = (_a = json === null || json === void 0 ? void 0 : json.data) === null || _a === void 0 ? void 0 : _a.projects) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.forEach((novel) => {
var _a;
return novels.push({
name: novel.title,
url: baseUrl + '/r/' + novel.url,
cover: ((_a = novel.covers[0]) === null || _a === void 0 ? void 0 : _a.url)
? baseUrl + novel.covers[0].url
: defaultCover_1.defaultCover,
});
});
return novels;
});
exports.searchNovels = searchNovels;
const fetchImage = (url) => __awaiter(void 0, void 0, void 0, function* () {
return yield (0, fetch_1.fetchFile)(url, {});
});
exports.fetchImage = fetchImage;