feat: add LNORI (#2235)
* feat: add LNORI plugin ("https://lnori.com/")
* chore: update lnori plugin icon to 96x96
* refactor: encapsulate library novel parsing into a private getLibraryNovels method
* refactor: update lnori plugin to improve TOC parsing and support multi-section content loading
This commit is contained in:
@@ -0,0 +1,412 @@
|
||||
import { fetchText } from '@libs/fetch';
|
||||
import { Plugin } from '@/types/plugin';
|
||||
import { Filters, FilterTypes } from '@libs/filterInputs';
|
||||
import { load as parseHTML } from 'cheerio';
|
||||
import { defaultCover } from '@libs/defaultCover';
|
||||
|
||||
class LnorisPlugin implements Plugin.PluginBase {
|
||||
id = 'lnori';
|
||||
name = 'LNORI';
|
||||
icon = 'src/en/lnori/icon.png';
|
||||
site = 'https://lnori.com/';
|
||||
version = '1.0.0';
|
||||
|
||||
private async getLibraryNovels(): Promise<
|
||||
{
|
||||
novel: Plugin.NovelItem;
|
||||
author: string;
|
||||
tags: string[];
|
||||
}[]
|
||||
> {
|
||||
const url = this.site + 'library';
|
||||
const body = await fetchText(url);
|
||||
const $ = parseHTML(body);
|
||||
|
||||
const parsedList: {
|
||||
novel: Plugin.NovelItem;
|
||||
author: string;
|
||||
tags: string[];
|
||||
}[] = [];
|
||||
|
||||
$('article.card').each((i, el) => {
|
||||
const name = $(el).attr('data-t') || '';
|
||||
const author = $(el).attr('data-a') || '';
|
||||
const tagsAttr = $(el).attr('data-tags') || '';
|
||||
const tags = tagsAttr.split(',').map(t => t.trim().toLowerCase());
|
||||
|
||||
const coverImg = $(el).find('.card-cover img').first();
|
||||
let cover = coverImg.attr('src') || '';
|
||||
if (cover && cover.startsWith('/')) {
|
||||
cover = this.site + cover.substring(1);
|
||||
}
|
||||
|
||||
const link = $(el).find('a.stretched-link').first();
|
||||
let path = link.attr('href') || '';
|
||||
if (path.startsWith('/')) {
|
||||
path = path.substring(1);
|
||||
}
|
||||
|
||||
if (path && name) {
|
||||
parsedList.push({
|
||||
novel: {
|
||||
name,
|
||||
path,
|
||||
cover: cover || defaultCover,
|
||||
},
|
||||
author,
|
||||
tags,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return parsedList;
|
||||
}
|
||||
|
||||
async popularNovels(
|
||||
pageNo: number,
|
||||
{ filters }: Plugin.PopularNovelsOptions<typeof this.filters>,
|
||||
): Promise<Plugin.NovelItem[]> {
|
||||
const parsedList = await this.getLibraryNovels();
|
||||
|
||||
let filteredList = parsedList;
|
||||
const selectedGenre = filters?.genre?.value;
|
||||
if (selectedGenre) {
|
||||
filteredList = filteredList.filter(item =>
|
||||
item.tags.includes(selectedGenre.toLowerCase()),
|
||||
);
|
||||
}
|
||||
|
||||
const selectedSort = filters?.sort?.value;
|
||||
if (selectedSort === 'title-az') {
|
||||
filteredList.sort((a, b) => a.novel.name.localeCompare(b.novel.name));
|
||||
} else if (selectedSort === 'title-za') {
|
||||
filteredList.sort((a, b) => b.novel.name.localeCompare(a.novel.name));
|
||||
}
|
||||
|
||||
const pageSize = 36;
|
||||
const offset = (pageNo - 1) * pageSize;
|
||||
return filteredList
|
||||
.slice(offset, offset + pageSize)
|
||||
.map(item => item.novel);
|
||||
}
|
||||
|
||||
async parseNovel(novelPath: string): Promise<Plugin.SourceNovel> {
|
||||
const url = this.site + novelPath;
|
||||
const body = await fetchText(url);
|
||||
const $ = parseHTML(body);
|
||||
|
||||
const novel: Plugin.SourceNovel = {
|
||||
path: novelPath,
|
||||
name: $('.hero-card h1.s-title').text().trim() || 'Untitled',
|
||||
};
|
||||
|
||||
const coverUrl = $('.hero-card .cover-wrap img').attr('src');
|
||||
if (coverUrl) {
|
||||
novel.cover = coverUrl.startsWith('/')
|
||||
? this.site + coverUrl.substring(1)
|
||||
: coverUrl;
|
||||
} else {
|
||||
novel.cover = defaultCover;
|
||||
}
|
||||
|
||||
const dataTagsAttr = $('nav.tags-box.desktop').attr('data-tags');
|
||||
if (dataTagsAttr) {
|
||||
try {
|
||||
const parsedTags = JSON.parse(dataTagsAttr);
|
||||
novel.genres = parsedTags
|
||||
.map((t: { name: string }) => t.name)
|
||||
.join(', ');
|
||||
} catch (e) {
|
||||
// Fallback
|
||||
}
|
||||
}
|
||||
|
||||
if (!novel.genres) {
|
||||
const genres: string[] = [];
|
||||
$('nav.tags-box.desktop a, nav.tags-box a').each((i, el) => {
|
||||
const text = $(el).text().trim();
|
||||
if (text) genres.push(text);
|
||||
});
|
||||
novel.genres = genres.join(', ');
|
||||
}
|
||||
|
||||
const summaryParagraphs: string[] = [];
|
||||
$('section.desc-box p.description').each((i, el) => {
|
||||
const text = $(el).text().trim();
|
||||
if (text) summaryParagraphs.push(text);
|
||||
});
|
||||
novel.summary = summaryParagraphs.join('\n\n');
|
||||
|
||||
novel.author = $('.hero-card p.author').text().trim();
|
||||
|
||||
// Map unique volume URLs
|
||||
const volumeMap: Record<string, string> = {};
|
||||
$('a[href^="/book/"]').each((i, el) => {
|
||||
const href = $(el).attr('href');
|
||||
const text = $(el).text().trim().replace(/\s+/g, ' ');
|
||||
if (href) {
|
||||
if (
|
||||
!volumeMap[href] ||
|
||||
(text && text.length > volumeMap[href].length)
|
||||
) {
|
||||
volumeMap[href] = text;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const getVolumeName = (href: string, text: string) => {
|
||||
let cleanText = text.replace(/Start Reading/gi, '').trim();
|
||||
if (!cleanText) {
|
||||
const parts = href.split('/');
|
||||
const slug = parts[parts.length - 1] || parts[parts.length - 2] || '';
|
||||
cleanText = slug
|
||||
.split('-')
|
||||
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
.join(' ');
|
||||
}
|
||||
return cleanText;
|
||||
};
|
||||
|
||||
const volumeUrls = Object.keys(volumeMap);
|
||||
const volumePromises = volumeUrls.map(async volUrl => {
|
||||
const fullVolUrl = this.site.replace(/\/$/, '') + volUrl;
|
||||
const volHtml = await fetchText(fullVolUrl);
|
||||
const $vol = parseHTML(volHtml);
|
||||
|
||||
const volChapters: Plugin.ChapterItem[] = [];
|
||||
const tocLinks = $vol(
|
||||
'nav.toc-view a[href^="#"], nav#toc-list a[href^="#"]',
|
||||
);
|
||||
|
||||
if (tocLinks.length > 0) {
|
||||
tocLinks.each((i, el) => {
|
||||
const href = $vol(el).attr('href');
|
||||
if (!href) return;
|
||||
const id = href.substring(1);
|
||||
const tocTitle = $vol(el).text().trim().replace(/\s+/g, ' ');
|
||||
|
||||
const section = $vol(`section#${id}`);
|
||||
const h2Title = section
|
||||
.find('h2.chapter-title, h2, h3')
|
||||
.first()
|
||||
.text()
|
||||
.trim();
|
||||
|
||||
const chapterName =
|
||||
tocTitle || h2Title || `Page ${id.replace(/\D/g, '')}`;
|
||||
|
||||
const volTitle = getVolumeName(volUrl, volumeMap[volUrl]);
|
||||
let path = volUrl;
|
||||
if (path.startsWith('/')) {
|
||||
path = path.substring(1);
|
||||
}
|
||||
path = path + '#' + id;
|
||||
|
||||
volChapters.push({
|
||||
name: `${volTitle} - ${chapterName}`,
|
||||
path,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
$vol('section.chapter').each((i, el) => {
|
||||
const id = $vol(el).attr('id');
|
||||
if (id) {
|
||||
const h2Title = $vol(el)
|
||||
.find('h2.chapter-title, h2, h3')
|
||||
.first()
|
||||
.text()
|
||||
.trim();
|
||||
|
||||
if (!h2Title) return;
|
||||
|
||||
const volTitle = getVolumeName(volUrl, volumeMap[volUrl]);
|
||||
let path = volUrl;
|
||||
if (path.startsWith('/')) {
|
||||
path = path.substring(1);
|
||||
}
|
||||
path = path + '#' + id;
|
||||
|
||||
volChapters.push({
|
||||
name: `${volTitle} - ${h2Title}`,
|
||||
path,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
return volChapters;
|
||||
});
|
||||
|
||||
const chapters2D = await Promise.all(volumePromises);
|
||||
const chapters = chapters2D.flat();
|
||||
|
||||
novel.chapters = chapters.map((chap, idx) => ({
|
||||
...chap,
|
||||
chapterNumber: idx + 1,
|
||||
}));
|
||||
|
||||
return novel;
|
||||
}
|
||||
|
||||
async parseChapter(chapterPath: string): Promise<string> {
|
||||
const [pathWithoutAnchor, anchor] = chapterPath.split('#');
|
||||
const url = this.site.replace(/\/$/, '') + '/' + pathWithoutAnchor;
|
||||
|
||||
const body = await fetchText(url);
|
||||
const $ = parseHTML(body);
|
||||
|
||||
const tocAnchors: string[] = [];
|
||||
$('nav.toc-view a[href^="#"], nav#toc-list a[href^="#"]').each((i, el) => {
|
||||
const href = $(el).attr('href');
|
||||
if (href) {
|
||||
tocAnchors.push(href.substring(1));
|
||||
}
|
||||
});
|
||||
|
||||
const chapterSelector = anchor ? `section#${anchor}` : 'section.chapter';
|
||||
const section = $(chapterSelector);
|
||||
|
||||
if (!section.length) {
|
||||
throw new Error(`Chapter section not found: ${chapterPath}`);
|
||||
}
|
||||
|
||||
if (tocAnchors.length > 0 && anchor) {
|
||||
const currentIndex = tocAnchors.indexOf(anchor);
|
||||
const nextAnchor =
|
||||
currentIndex !== -1 && currentIndex + 1 < tocAnchors.length
|
||||
? tocAnchors[currentIndex + 1]
|
||||
: null;
|
||||
|
||||
const pagesContent: string[] = [];
|
||||
let stepSection = section;
|
||||
|
||||
while (stepSection.length) {
|
||||
const mainContent = stepSection.find('.main').length
|
||||
? stepSection.find('.main').clone()
|
||||
: stepSection.clone();
|
||||
|
||||
mainContent.find('h2, h3, .chapter-title').remove();
|
||||
|
||||
mainContent.find('img').each((i, el) => {
|
||||
const src = $(el).attr('src');
|
||||
if (src && src.startsWith('/')) {
|
||||
$(el).attr('src', this.site.replace(/\/$/, '') + src);
|
||||
}
|
||||
});
|
||||
|
||||
mainContent.find('source').each((i, el) => {
|
||||
const srcset = $(el).attr('srcset');
|
||||
if (srcset && srcset.startsWith('/')) {
|
||||
$(el).attr('srcset', this.site.replace(/\/$/, '') + srcset);
|
||||
}
|
||||
});
|
||||
|
||||
const html = mainContent.html();
|
||||
if (html) {
|
||||
pagesContent.push(html);
|
||||
}
|
||||
|
||||
let nextSibling = stepSection.next();
|
||||
while (nextSibling.length && !nextSibling.is('section.chapter')) {
|
||||
nextSibling = nextSibling.next();
|
||||
}
|
||||
stepSection = nextSibling;
|
||||
|
||||
if (nextAnchor && stepSection.attr('id') === nextAnchor) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pagesContent.join('\n');
|
||||
} else {
|
||||
const mainContent = section.find('.main').length
|
||||
? section.find('.main').clone()
|
||||
: section.clone();
|
||||
|
||||
mainContent.find('h2, h3, .chapter-title').remove();
|
||||
|
||||
mainContent.find('img').each((i, el) => {
|
||||
const src = $(el).attr('src');
|
||||
if (src && src.startsWith('/')) {
|
||||
$(el).attr('src', this.site.replace(/\/$/, '') + src);
|
||||
}
|
||||
});
|
||||
|
||||
mainContent.find('source').each((i, el) => {
|
||||
const srcset = $(el).attr('srcset');
|
||||
if (srcset && srcset.startsWith('/')) {
|
||||
$(el).attr('srcset', this.site.replace(/\/$/, '') + srcset);
|
||||
}
|
||||
});
|
||||
|
||||
return mainContent.html() || '';
|
||||
}
|
||||
}
|
||||
|
||||
async searchNovels(
|
||||
searchTerm: string,
|
||||
pageNo: number,
|
||||
): Promise<Plugin.NovelItem[]> {
|
||||
const parsedList = await this.getLibraryNovels();
|
||||
|
||||
const term = searchTerm.toLowerCase();
|
||||
const filteredList = parsedList.filter(item => {
|
||||
return (
|
||||
item.novel.name.toLowerCase().includes(term) ||
|
||||
item.author.toLowerCase().includes(term) ||
|
||||
item.tags.some(t => t.includes(term))
|
||||
);
|
||||
});
|
||||
|
||||
const pageSize = 36;
|
||||
const offset = (pageNo - 1) * pageSize;
|
||||
return filteredList
|
||||
.slice(offset, offset + pageSize)
|
||||
.map(item => item.novel);
|
||||
}
|
||||
|
||||
resolveUrl = (path: string, _isNovel?: boolean) => {
|
||||
return new URL(path, this.site).href;
|
||||
};
|
||||
|
||||
filters = {
|
||||
sort: {
|
||||
label: 'Sort By',
|
||||
value: 'popular',
|
||||
options: [
|
||||
{ label: 'Popular (Default)', value: 'popular' },
|
||||
{ label: 'Title A-Z', value: 'title-az' },
|
||||
{ label: 'Title Z-A', value: 'title-za' },
|
||||
],
|
||||
type: FilterTypes.Picker,
|
||||
},
|
||||
genre: {
|
||||
label: 'Genre',
|
||||
value: '',
|
||||
options: [
|
||||
{ label: 'All', value: '' },
|
||||
{ label: 'Academy', value: 'academy' },
|
||||
{ label: 'Action', value: 'action' },
|
||||
{ label: 'Adventure', value: 'adventure' },
|
||||
{ label: 'Comedy', value: 'comedy' },
|
||||
{ label: 'Drama', value: 'drama' },
|
||||
{ label: 'Fantasy', value: 'fantasy' },
|
||||
{ label: 'Harem', value: 'harem' },
|
||||
{ label: 'Historical', value: 'historical' },
|
||||
{ label: 'Isekai', value: 'isekai' },
|
||||
{ label: 'Magic', value: 'magic' },
|
||||
{ label: 'Mystery', value: 'mystery' },
|
||||
{ label: 'Psychological', value: 'psychological' },
|
||||
{ label: 'Reincarnation', value: 'reincarnation' },
|
||||
{ label: 'Romance', value: 'romance' },
|
||||
{ label: 'Sci-Fi', value: 'sci-fi' },
|
||||
{ label: 'Slice of Life', value: 'slice-of-life' },
|
||||
{ label: 'Tragedy', value: 'tragedy' },
|
||||
{ label: 'Female Protagonist', value: 'female protagonist' },
|
||||
{ label: 'Male Protagonist', value: 'male protagonist' },
|
||||
],
|
||||
type: FilterTypes.Picker,
|
||||
},
|
||||
} satisfies Filters;
|
||||
}
|
||||
|
||||
export default new LnorisPlugin();
|
||||
+118
-116
@@ -131,122 +131,123 @@ import p_128 from '@plugins/english/inoveltranslation';
|
||||
import p_129 from '@plugins/english/leafstudio';
|
||||
import p_130 from '@plugins/english/lightnoveltranslation';
|
||||
import p_131 from '@plugins/english/lnmtl';
|
||||
import p_132 from '@plugins/english/mvlempyr';
|
||||
import p_133 from '@plugins/english/novelbuddy';
|
||||
import p_134 from '@plugins/english/novelfire';
|
||||
import p_135 from '@plugins/english/novelhall';
|
||||
import p_136 from '@plugins/english/novelhi';
|
||||
import p_137 from '@plugins/english/novelight';
|
||||
import p_138 from '@plugins/english/novelrest';
|
||||
import p_139 from '@plugins/english/novelupdates';
|
||||
import p_140 from '@plugins/english/pawread';
|
||||
import p_141 from '@plugins/english/rainofsnow';
|
||||
import p_142 from '@plugins/english/readfrom';
|
||||
import p_143 from '@plugins/english/relibrary';
|
||||
import p_144 from '@plugins/english/royalroad';
|
||||
import p_145 from '@plugins/english/scribblehub';
|
||||
import p_146 from '@plugins/english/vynovel';
|
||||
import p_147 from '@plugins/english/wct';
|
||||
import p_148 from '@plugins/english/webnovel';
|
||||
import p_149 from '@plugins/english/wtrlab';
|
||||
import p_150 from '@plugins/english/wuxiaworld';
|
||||
import p_151 from '@plugins/french/LighNovelFR[lightnovelwp]';
|
||||
import p_152 from '@plugins/french/MTLNovel(FR)[mtlnovel]';
|
||||
import p_153 from '@plugins/french/MassNovel[madara]';
|
||||
import p_154 from '@plugins/french/WorldNovel[madara]';
|
||||
import p_155 from '@plugins/french/chireads';
|
||||
import p_156 from '@plugins/french/harkeneliwood';
|
||||
import p_157 from '@plugins/french/kisswood';
|
||||
import p_158 from '@plugins/french/noveldeglace';
|
||||
import p_159 from '@plugins/french/novelfrance';
|
||||
import p_160 from '@plugins/french/novhell';
|
||||
import p_161 from '@plugins/french/warriorlegendtrad';
|
||||
import p_162 from '@plugins/french/wuxialnscantrad';
|
||||
import p_163 from '@plugins/french/xiaowaz';
|
||||
import p_164 from '@plugins/indonesian/BacaLightNovel[lightnovelwp]';
|
||||
import p_165 from '@plugins/indonesian/MTLNovel(ID)[mtlnovel]';
|
||||
import p_166 from '@plugins/indonesian/MeioNovel[madara]';
|
||||
import p_167 from '@plugins/indonesian/NovelBookID[madara]';
|
||||
import p_168 from '@plugins/indonesian/SekteNovel[lightnovelwp]';
|
||||
import p_169 from '@plugins/indonesian/Vanovel[madara]';
|
||||
import p_170 from '@plugins/indonesian/WBNovel[madara]';
|
||||
import p_171 from '@plugins/indonesian/indowebnovel';
|
||||
import p_172 from '@plugins/indonesian/sakuranovel';
|
||||
import p_173 from '@plugins/japanese/Syosetu';
|
||||
import p_174 from '@plugins/japanese/kakuyomu';
|
||||
import p_175 from '@plugins/korean/Agitoon';
|
||||
import p_176 from '@plugins/korean/FortuneEternal[madara]';
|
||||
import p_177 from '@plugins/multi/komga';
|
||||
import p_178 from '@plugins/polish/novelki';
|
||||
import p_179 from '@plugins/portuguese/BetterNovels[lightnovelwp]';
|
||||
import p_180 from '@plugins/portuguese/CentralNovel[lightnovelwp]';
|
||||
import p_181 from '@plugins/portuguese/Kiniga[madara]';
|
||||
import p_182 from '@plugins/portuguese/LaNovels[hotnovelpub]';
|
||||
import p_183 from '@plugins/portuguese/LightNovelBrasil[lightnovelwp]';
|
||||
import p_184 from '@plugins/portuguese/MTLNovel(PT)[mtlnovel]';
|
||||
import p_185 from '@plugins/portuguese/blogdoamonnovels';
|
||||
import p_186 from '@plugins/portuguese/illusia';
|
||||
import p_187 from '@plugins/portuguese/novelmania';
|
||||
import p_188 from '@plugins/portuguese/tsundoku';
|
||||
import p_189 from '@plugins/russian/Bllate[rulate]';
|
||||
import p_190 from '@plugins/russian/Bookhamster[ifreedom]';
|
||||
import p_191 from '@plugins/russian/Erolate[rulate]';
|
||||
import p_192 from '@plugins/russian/EzNovels[hotnovelpub]';
|
||||
import p_193 from '@plugins/russian/MTLNovel(RU)[mtlnovel]';
|
||||
import p_194 from '@plugins/russian/NovelCool(RU)[novelcool]';
|
||||
import p_195 from '@plugins/russian/Ranobes(RU)[ranobes]';
|
||||
import p_196 from '@plugins/russian/Rulate[rulate]';
|
||||
import p_197 from '@plugins/russian/authortoday';
|
||||
import p_198 from '@plugins/russian/bookriver';
|
||||
import p_199 from '@plugins/russian/ficbook';
|
||||
import p_200 from '@plugins/russian/jaomix';
|
||||
import p_201 from '@plugins/russian/neobook';
|
||||
import p_202 from '@plugins/russian/novelTL';
|
||||
import p_203 from '@plugins/russian/ranobehub';
|
||||
import p_204 from '@plugins/russian/ranobelib';
|
||||
import p_205 from '@plugins/russian/ranoberf';
|
||||
import p_206 from '@plugins/russian/renovels';
|
||||
import p_207 from '@plugins/russian/topliba';
|
||||
import p_208 from '@plugins/russian/zelluloza';
|
||||
import p_209 from '@plugins/russian/СвободныйМирРанобэ[ifreedom]';
|
||||
import p_210 from '@plugins/spanish/AllNovelRead[lightnovelwp]';
|
||||
import p_211 from '@plugins/spanish/AnimesHoy12[madara]';
|
||||
import p_212 from '@plugins/spanish/LightNovelDaily[hotnovelpub]';
|
||||
import p_213 from '@plugins/spanish/MTLNovel(ES)[mtlnovel]';
|
||||
import p_214 from '@plugins/spanish/NOVA';
|
||||
import p_215 from '@plugins/spanish/PanchoTranslations[madara]';
|
||||
import p_216 from '@plugins/spanish/TC&Sega[lightnovelwp]';
|
||||
import p_217 from '@plugins/spanish/TraduccionesAmistosas[madara]';
|
||||
import p_218 from '@plugins/spanish/hasutl';
|
||||
import p_219 from '@plugins/spanish/novelasligera';
|
||||
import p_220 from '@plugins/spanish/novelawuxia';
|
||||
import p_221 from '@plugins/spanish/novelyra';
|
||||
import p_222 from '@plugins/spanish/oasistranslations';
|
||||
import p_223 from '@plugins/spanish/skynovels';
|
||||
import p_224 from '@plugins/spanish/tunovelaligera';
|
||||
import p_225 from '@plugins/spanish/yukitls';
|
||||
import p_226 from '@plugins/thai/NovelLucky[madara]';
|
||||
import p_227 from '@plugins/thai/NovelPDF[madara]';
|
||||
import p_228 from '@plugins/turkish/ArazNovel[madara]';
|
||||
import p_229 from '@plugins/turkish/EKTAPLAR[madara]';
|
||||
import p_230 from '@plugins/turkish/KodeksLibrary[lightnovelwp]';
|
||||
import p_231 from '@plugins/turkish/MangaTR';
|
||||
import p_232 from '@plugins/turkish/NABSCANS[madara]';
|
||||
import p_233 from '@plugins/turkish/Namevt[lightnovelwp]';
|
||||
import p_234 from '@plugins/turkish/NovelTR[lightnovelwp]';
|
||||
import p_235 from '@plugins/turkish/Noveloku[madara]';
|
||||
import p_236 from '@plugins/turkish/RagnarScans[madara]';
|
||||
import p_237 from '@plugins/turkish/ThNovels[hotnovelpub]';
|
||||
import p_238 from '@plugins/turkish/TurkceLightNovels[madara]';
|
||||
import p_239 from '@plugins/turkish/WebNovelOku[madara]';
|
||||
import p_240 from '@plugins/turkish/epiknovel';
|
||||
import p_241 from '@plugins/turkish/kakikata[madara]';
|
||||
import p_242 from '@plugins/ukrainian/bakainua';
|
||||
import p_243 from '@plugins/ukrainian/smakolykytl';
|
||||
import p_244 from '@plugins/vietnamese/LNHako';
|
||||
import p_245 from '@plugins/vietnamese/lightnovelvn';
|
||||
import p_246 from '@plugins/vietnamese/nettruyen';
|
||||
import p_247 from '@plugins/vietnamese/truyenss';
|
||||
import p_132 from '@plugins/english/lnori';
|
||||
import p_133 from '@plugins/english/mvlempyr';
|
||||
import p_134 from '@plugins/english/novelbuddy';
|
||||
import p_135 from '@plugins/english/novelfire';
|
||||
import p_136 from '@plugins/english/novelhall';
|
||||
import p_137 from '@plugins/english/novelhi';
|
||||
import p_138 from '@plugins/english/novelight';
|
||||
import p_139 from '@plugins/english/novelrest';
|
||||
import p_140 from '@plugins/english/novelupdates';
|
||||
import p_141 from '@plugins/english/pawread';
|
||||
import p_142 from '@plugins/english/rainofsnow';
|
||||
import p_143 from '@plugins/english/readfrom';
|
||||
import p_144 from '@plugins/english/relibrary';
|
||||
import p_145 from '@plugins/english/royalroad';
|
||||
import p_146 from '@plugins/english/scribblehub';
|
||||
import p_147 from '@plugins/english/vynovel';
|
||||
import p_148 from '@plugins/english/wct';
|
||||
import p_149 from '@plugins/english/webnovel';
|
||||
import p_150 from '@plugins/english/wtrlab';
|
||||
import p_151 from '@plugins/english/wuxiaworld';
|
||||
import p_152 from '@plugins/french/LighNovelFR[lightnovelwp]';
|
||||
import p_153 from '@plugins/french/MTLNovel(FR)[mtlnovel]';
|
||||
import p_154 from '@plugins/french/MassNovel[madara]';
|
||||
import p_155 from '@plugins/french/WorldNovel[madara]';
|
||||
import p_156 from '@plugins/french/chireads';
|
||||
import p_157 from '@plugins/french/harkeneliwood';
|
||||
import p_158 from '@plugins/french/kisswood';
|
||||
import p_159 from '@plugins/french/noveldeglace';
|
||||
import p_160 from '@plugins/french/novelfrance';
|
||||
import p_161 from '@plugins/french/novhell';
|
||||
import p_162 from '@plugins/french/warriorlegendtrad';
|
||||
import p_163 from '@plugins/french/wuxialnscantrad';
|
||||
import p_164 from '@plugins/french/xiaowaz';
|
||||
import p_165 from '@plugins/indonesian/BacaLightNovel[lightnovelwp]';
|
||||
import p_166 from '@plugins/indonesian/MTLNovel(ID)[mtlnovel]';
|
||||
import p_167 from '@plugins/indonesian/MeioNovel[madara]';
|
||||
import p_168 from '@plugins/indonesian/NovelBookID[madara]';
|
||||
import p_169 from '@plugins/indonesian/SekteNovel[lightnovelwp]';
|
||||
import p_170 from '@plugins/indonesian/Vanovel[madara]';
|
||||
import p_171 from '@plugins/indonesian/WBNovel[madara]';
|
||||
import p_172 from '@plugins/indonesian/indowebnovel';
|
||||
import p_173 from '@plugins/indonesian/sakuranovel';
|
||||
import p_174 from '@plugins/japanese/Syosetu';
|
||||
import p_175 from '@plugins/japanese/kakuyomu';
|
||||
import p_176 from '@plugins/korean/Agitoon';
|
||||
import p_177 from '@plugins/korean/FortuneEternal[madara]';
|
||||
import p_178 from '@plugins/multi/komga';
|
||||
import p_179 from '@plugins/polish/novelki';
|
||||
import p_180 from '@plugins/portuguese/BetterNovels[lightnovelwp]';
|
||||
import p_181 from '@plugins/portuguese/CentralNovel[lightnovelwp]';
|
||||
import p_182 from '@plugins/portuguese/Kiniga[madara]';
|
||||
import p_183 from '@plugins/portuguese/LaNovels[hotnovelpub]';
|
||||
import p_184 from '@plugins/portuguese/LightNovelBrasil[lightnovelwp]';
|
||||
import p_185 from '@plugins/portuguese/MTLNovel(PT)[mtlnovel]';
|
||||
import p_186 from '@plugins/portuguese/blogdoamonnovels';
|
||||
import p_187 from '@plugins/portuguese/illusia';
|
||||
import p_188 from '@plugins/portuguese/novelmania';
|
||||
import p_189 from '@plugins/portuguese/tsundoku';
|
||||
import p_190 from '@plugins/russian/Bllate[rulate]';
|
||||
import p_191 from '@plugins/russian/Bookhamster[ifreedom]';
|
||||
import p_192 from '@plugins/russian/Erolate[rulate]';
|
||||
import p_193 from '@plugins/russian/EzNovels[hotnovelpub]';
|
||||
import p_194 from '@plugins/russian/MTLNovel(RU)[mtlnovel]';
|
||||
import p_195 from '@plugins/russian/NovelCool(RU)[novelcool]';
|
||||
import p_196 from '@plugins/russian/Ranobes(RU)[ranobes]';
|
||||
import p_197 from '@plugins/russian/Rulate[rulate]';
|
||||
import p_198 from '@plugins/russian/authortoday';
|
||||
import p_199 from '@plugins/russian/bookriver';
|
||||
import p_200 from '@plugins/russian/ficbook';
|
||||
import p_201 from '@plugins/russian/jaomix';
|
||||
import p_202 from '@plugins/russian/neobook';
|
||||
import p_203 from '@plugins/russian/novelTL';
|
||||
import p_204 from '@plugins/russian/ranobehub';
|
||||
import p_205 from '@plugins/russian/ranobelib';
|
||||
import p_206 from '@plugins/russian/ranoberf';
|
||||
import p_207 from '@plugins/russian/renovels';
|
||||
import p_208 from '@plugins/russian/topliba';
|
||||
import p_209 from '@plugins/russian/zelluloza';
|
||||
import p_210 from '@plugins/russian/СвободныйМирРанобэ[ifreedom]';
|
||||
import p_211 from '@plugins/spanish/AllNovelRead[lightnovelwp]';
|
||||
import p_212 from '@plugins/spanish/AnimesHoy12[madara]';
|
||||
import p_213 from '@plugins/spanish/LightNovelDaily[hotnovelpub]';
|
||||
import p_214 from '@plugins/spanish/MTLNovel(ES)[mtlnovel]';
|
||||
import p_215 from '@plugins/spanish/NOVA';
|
||||
import p_216 from '@plugins/spanish/PanchoTranslations[madara]';
|
||||
import p_217 from '@plugins/spanish/TC&Sega[lightnovelwp]';
|
||||
import p_218 from '@plugins/spanish/TraduccionesAmistosas[madara]';
|
||||
import p_219 from '@plugins/spanish/hasutl';
|
||||
import p_220 from '@plugins/spanish/novelasligera';
|
||||
import p_221 from '@plugins/spanish/novelawuxia';
|
||||
import p_222 from '@plugins/spanish/novelyra';
|
||||
import p_223 from '@plugins/spanish/oasistranslations';
|
||||
import p_224 from '@plugins/spanish/skynovels';
|
||||
import p_225 from '@plugins/spanish/tunovelaligera';
|
||||
import p_226 from '@plugins/spanish/yukitls';
|
||||
import p_227 from '@plugins/thai/NovelLucky[madara]';
|
||||
import p_228 from '@plugins/thai/NovelPDF[madara]';
|
||||
import p_229 from '@plugins/turkish/ArazNovel[madara]';
|
||||
import p_230 from '@plugins/turkish/EKTAPLAR[madara]';
|
||||
import p_231 from '@plugins/turkish/KodeksLibrary[lightnovelwp]';
|
||||
import p_232 from '@plugins/turkish/MangaTR';
|
||||
import p_233 from '@plugins/turkish/NABSCANS[madara]';
|
||||
import p_234 from '@plugins/turkish/Namevt[lightnovelwp]';
|
||||
import p_235 from '@plugins/turkish/NovelTR[lightnovelwp]';
|
||||
import p_236 from '@plugins/turkish/Noveloku[madara]';
|
||||
import p_237 from '@plugins/turkish/RagnarScans[madara]';
|
||||
import p_238 from '@plugins/turkish/ThNovels[hotnovelpub]';
|
||||
import p_239 from '@plugins/turkish/TurkceLightNovels[madara]';
|
||||
import p_240 from '@plugins/turkish/WebNovelOku[madara]';
|
||||
import p_241 from '@plugins/turkish/epiknovel';
|
||||
import p_242 from '@plugins/turkish/kakikata[madara]';
|
||||
import p_243 from '@plugins/ukrainian/bakainua';
|
||||
import p_244 from '@plugins/ukrainian/smakolykytl';
|
||||
import p_245 from '@plugins/vietnamese/LNHako';
|
||||
import p_246 from '@plugins/vietnamese/lightnovelvn';
|
||||
import p_247 from '@plugins/vietnamese/nettruyen';
|
||||
import p_248 from '@plugins/vietnamese/truyenss';
|
||||
|
||||
const PLUGINS: Plugin.PluginBase[] = [
|
||||
p_0,
|
||||
@@ -497,5 +498,6 @@ const PLUGINS: Plugin.PluginBase[] = [
|
||||
p_245,
|
||||
p_246,
|
||||
p_247,
|
||||
p_248,
|
||||
];
|
||||
export default PLUGINS;
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
Reference in New Issue
Block a user