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:
@@ -0,0 +1,2 @@
|
||||
export const defaultCover =
|
||||
"https://github.com/LNReader/lnreader-sources/blob/main/icons/src/coverNotAvailable.jpg?raw=true";
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Plugin } from "@typings/plugin";
|
||||
import { NodeFetchParams, getNodeFetch } from "./nodeFetch";
|
||||
|
||||
const fetch = async (...args: NodeFetchParams) =>
|
||||
(await getNodeFetch())(...args);
|
||||
|
||||
const defaultUserAgentString =
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36";
|
||||
|
||||
export async function fetchApi(
|
||||
url: string,
|
||||
init?: NodeFetchParams[1],
|
||||
pluginId?: string
|
||||
) {
|
||||
const headers = {
|
||||
"User-Agent": defaultUserAgentString,
|
||||
...init?.headers,
|
||||
};
|
||||
if (pluginId) console.log("Enable CloudFlare cookie for", pluginId);
|
||||
return await fetch(url, { ...init, headers });
|
||||
}
|
||||
|
||||
export const fetchFile: Plugin.fetchImage = async function (url, init) {
|
||||
if (!init) init = {};
|
||||
try {
|
||||
const res = await fetch(url, init);
|
||||
if (!res.ok) return undefined;
|
||||
const arrayBuffer = await res.arrayBuffer();
|
||||
return Buffer.from(arrayBuffer).toString("base64");
|
||||
} catch (e) {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
@@ -1,14 +0,0 @@
|
||||
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
|
||||
|
||||
const defaultUserAgentString =
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36';
|
||||
|
||||
async function fetchApi (url, init, pluginId){
|
||||
const headers = {
|
||||
...init?.headers,
|
||||
'User-Agent': defaultUserAgentString,
|
||||
};
|
||||
return await fetch(url, { ...init, headers });
|
||||
}
|
||||
|
||||
module.exports = fetchApi
|
||||
@@ -1,15 +0,0 @@
|
||||
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
|
||||
|
||||
async function fetchFile(url, init){
|
||||
if(!init) init = {};
|
||||
try{
|
||||
const res = await fetch(url, init);
|
||||
if(!res.ok) return undefined;
|
||||
const arrayBuffer = await res.arrayBuffer();
|
||||
return Buffer.from(arrayBuffer).toString('base64');
|
||||
}catch(e){
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = fetchFile;
|
||||
@@ -1,7 +0,0 @@
|
||||
const FilterInputs = {
|
||||
TextInput: 0,
|
||||
Picker: 1,
|
||||
Checkbox: 2,
|
||||
}
|
||||
|
||||
module.exports = FilterInputs
|
||||
@@ -0,0 +1,15 @@
|
||||
export interface FilterValue {
|
||||
label: string;
|
||||
value: string | number;
|
||||
}
|
||||
export enum FilterInputs {
|
||||
TextInput,
|
||||
Picker,
|
||||
Checkbox,
|
||||
}
|
||||
export interface Filter {
|
||||
key: string;
|
||||
label: string;
|
||||
values: FilterValue[];
|
||||
inputType: FilterInputs;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
const isUrlAbsolute = (url) => {
|
||||
if (url) {
|
||||
if (url.indexOf('//') === 0) {
|
||||
return true;
|
||||
} // URL is protocol-relative (= absolute)
|
||||
if (url.indexOf('://') === -1) {
|
||||
return false;
|
||||
} // URL has no protocol (= relative)
|
||||
if (url.indexOf('.') === -1) {
|
||||
return false;
|
||||
} // URL does not contain a dot, i.e. no TLD (= relative, possibly REST)
|
||||
if (url.indexOf('/') === -1) {
|
||||
return false;
|
||||
} // URL does not contain a single slash (= relative)
|
||||
if (url.indexOf(':') > url.indexOf('/')) {
|
||||
return false;
|
||||
} // The first colon comes after the first slash (= relative)
|
||||
if (url.indexOf('://') < url.indexOf('.')) {
|
||||
return true;
|
||||
} // Protocol is defined before first dot (= absolute)
|
||||
}
|
||||
return false; // Anything else must be relative
|
||||
};
|
||||
|
||||
module.exports = isUrlAbsolute;
|
||||
@@ -0,0 +1,23 @@
|
||||
export const isUrlAbsolute = (url: string) => {
|
||||
if (url) {
|
||||
if (url.indexOf("//") === 0) {
|
||||
return true;
|
||||
} // URL is protocol-relative (= absolute)
|
||||
if (url.indexOf("://") === -1) {
|
||||
return false;
|
||||
} // URL has no protocol (= relative)
|
||||
if (url.indexOf(".") === -1) {
|
||||
return false;
|
||||
} // URL does not contain a dot, i.e. no TLD (= relative, possibly REST)
|
||||
if (url.indexOf("/") === -1) {
|
||||
return false;
|
||||
} // URL does not contain a single slash (= relative)
|
||||
if (url.indexOf(":") > url.indexOf("/")) {
|
||||
return false;
|
||||
} // The first colon comes after the first slash (= relative)
|
||||
if (url.indexOf("://") < url.indexOf(".")) {
|
||||
return true;
|
||||
} // Protocol is defined before first dot (= absolute)
|
||||
}
|
||||
return false; // Anything else must be relative
|
||||
};
|
||||
@@ -1,14 +0,0 @@
|
||||
module.exports = {
|
||||
Arabic: 'العربية',
|
||||
Chinese: '中文, 汉语, 漢語',
|
||||
English: 'English',
|
||||
French: 'français, française',
|
||||
Indonesian: 'Bahasa Indonesia',
|
||||
Japanese: '日本語',
|
||||
Korean: '한국어, 조선말',
|
||||
Portuguese: 'Português',
|
||||
Russian: 'русский язык',
|
||||
Spanish: 'español, castellano',
|
||||
Turkish: 'Türkçe',
|
||||
Vietnamese: 'Tiếng Việt',
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
export const languages = {
|
||||
Arabic: "العربية",
|
||||
Chinese: "中文, 汉语, 漢語",
|
||||
English: "English",
|
||||
French: "français, française",
|
||||
Indonesian: "Bahasa Indonesia",
|
||||
Japanese: "日本語",
|
||||
Korean: "한국어, 조선말",
|
||||
Portuguese: "Português",
|
||||
Russian: "русский язык",
|
||||
Spanish: "español, castellano",
|
||||
Turkish: "Türkçe",
|
||||
Vietnamese: "Tiếng Việt",
|
||||
} as const;
|
||||
@@ -0,0 +1,9 @@
|
||||
const nodeFetch = import("node-fetch");
|
||||
|
||||
export type NodeFetchFunction = Awaited<typeof nodeFetch>["default"];
|
||||
|
||||
export type NodeFetchParams = Parameters<NodeFetchFunction>;
|
||||
|
||||
export const getNodeFetch = async (): Promise<NodeFetchFunction> => {
|
||||
return (await nodeFetch).default;
|
||||
};
|
||||
@@ -1,9 +0,0 @@
|
||||
module.exports = {
|
||||
Unknown: 'Unknown',
|
||||
Ongoing: 'Ongoing',
|
||||
Completed: 'Completed',
|
||||
Licensed: 'Licensed',
|
||||
PublishingFinished: 'Publishing Finished',
|
||||
Cancelled: 'Cancelled',
|
||||
OnHiatus: 'On Hiatus',
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
export const NovelStatus = {
|
||||
Unknown: "Unknown",
|
||||
Ongoing: "Ongoing",
|
||||
Completed: "Completed",
|
||||
Licensed: "Licensed",
|
||||
PublishingFinished: "Publishing Finished",
|
||||
Cancelled: "Cancelled",
|
||||
OnHiatus: "On Hiatus",
|
||||
} as const;
|
||||
@@ -1,30 +0,0 @@
|
||||
const dayjs = require('dayjs');
|
||||
|
||||
const parseMadaraDate = date => {
|
||||
let releaseDate = date;
|
||||
|
||||
if (date.includes('ago')) {
|
||||
let timeAgo = date;
|
||||
releaseDate = new Date();
|
||||
|
||||
timeAgo = timeAgo.match(/\d+/)[0];
|
||||
|
||||
if (timeAgo.includes('hours ago') || timeAgo.includes('hour ago')) {
|
||||
releaseDate.setHours(releaseDate.getHours() - timeAgo);
|
||||
}
|
||||
|
||||
if (timeAgo.includes('days ago') || timeAgo.includes('day ago')) {
|
||||
releaseDate.setDate(releaseDate.getDate() - timeAgo);
|
||||
}
|
||||
|
||||
if (timeAgo.includes('months ago') || timeAgo.includes('month ago')) {
|
||||
releaseDate.setMonth(releaseDate.getMonth() - timeAgo);
|
||||
}
|
||||
|
||||
releaseDate = dayjs(releaseDate).format('LL');
|
||||
}
|
||||
|
||||
return releaseDate;
|
||||
};
|
||||
|
||||
module.exports = parseMadaraDate;
|
||||
@@ -0,0 +1,26 @@
|
||||
import dayjs from "dayjs";
|
||||
|
||||
export const parseMadaraDate = (date: string) => {
|
||||
if (date.includes("ago")) {
|
||||
const dayJSDate = dayjs(new Date()); // today
|
||||
const timeAgo = date.match(/\d+/)?.[0] || "";
|
||||
const timeAgoInt = parseInt(timeAgo, 10);
|
||||
|
||||
if (!timeAgo) return date; // there is no number!
|
||||
|
||||
if (date.includes("hours ago") || date.includes("hour ago")) {
|
||||
dayJSDate.subtract(timeAgoInt, "hours"); // go back N hours
|
||||
}
|
||||
|
||||
if (date.includes("days ago") || date.includes("day ago")) {
|
||||
dayJSDate.subtract(timeAgoInt, "days"); // go back N days
|
||||
}
|
||||
|
||||
if (date.includes("months ago") || date.includes("month ago")) {
|
||||
dayJSDate.subtract(timeAgoInt, "months"); // go back N months
|
||||
}
|
||||
|
||||
return dayJSDate.format("LL");
|
||||
}
|
||||
return date; // there is no "ago" so don't mess with the date
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
export function showToast(...message: Parameters<(typeof console)["log"]>) {
|
||||
console.log(...message);
|
||||
}
|
||||
Reference in New Issue
Block a user