Add Clash and Subscription producer

This commit is contained in:
Peng-YM 2020-09-29 17:09:29 +08:00
parent 8b626ffad3
commit 33ae67ab60
2 changed files with 3158 additions and 3124 deletions

View File

@ -20,6 +20,7 @@ $.http = HTTP({
const SETTINGS_KEY = "settings"; const SETTINGS_KEY = "settings";
const SUBS_KEY = "subs"; const SUBS_KEY = "subs";
const COLLECTIONS_KEY = "collections"; const COLLECTIONS_KEY = "collections";
const AVAILABLE_FILTERS = { const AVAILABLE_FILTERS = {
"Keyword Filter": KeywordFilter, "Keyword Filter": KeywordFilter,
"Useless Filter": UselessFilter, "Useless Filter": UselessFilter,
@ -41,13 +42,17 @@ const AVAILABLE_OPERATORS = {
"Script Operator": ScriptOperator, "Script Operator": ScriptOperator,
}; };
const AVAILABLE_PRODUCERS = [
Raw_Producer, URI_Producer,
Surge_Producer, Loon_Producer, QX_Producer, Clash_Producer, Sub_Producer
];
// SOME INITIALIZATIONS // SOME INITIALIZATIONS
if (!$.read(SUBS_KEY)) $.write({}, SUBS_KEY); if (!$.read(SUBS_KEY)) $.write({}, SUBS_KEY);
if (!$.read(COLLECTIONS_KEY)) $.write({}, COLLECTIONS_KEY); if (!$.read(COLLECTIONS_KEY)) $.write({}, COLLECTIONS_KEY);
if (!$.read(SETTINGS_KEY)) $.write({}, SETTINGS_KEY); if (!$.read(SETTINGS_KEY)) $.write({}, SETTINGS_KEY);
// BACKEND API // BACKEND API
$.info("Initializing Express...");
// download // download
$app.get("/download/collection/:name", downloadCollection); $app.get("/download/collection/:name", downloadCollection);
@ -88,7 +93,6 @@ $app.all("/", async (req, res) => {
res.send("Hello from Sub-Store! Made with ❤️ by Peng-YM."); res.send("Hello from Sub-Store! Made with ❤️ by Peng-YM.");
}); });
$.info("Express initialized");
$app.start(); $app.start();
async function IP_API(req, res) { async function IP_API(req, res) {
@ -115,7 +119,7 @@ async function downloadResource(url) {
async function gistBackup(req, res) { async function gistBackup(req, res) {
const {action} = req.query; const {action} = req.query;
// read token // read token
const { gistToken } = $.read(SETTINGS_KEY); const {gistToken} = $.read(SETTINGS_KEY);
if (!gistToken) { if (!gistToken) {
res.status(500).json({ res.status(500).json({
status: "failed", status: "failed",
@ -123,7 +127,7 @@ async function gistBackup(req, res) {
}); });
} else { } else {
const gist = new Gist("Auto Generated Sub-Store Backup", gistToken); const gist = new Gist("Auto Generated Sub-Store Backup", gistToken);
try{ try {
let content; let content;
switch (action) { switch (action) {
case "upload": case "upload":
@ -134,7 +138,7 @@ async function gistBackup(req, res) {
case "download": case "download":
content = await gist.download(); content = await gist.download();
// restore settings // restore settings
$.write(content,"#sub-store"); $.write(content, "#sub-store");
$.info(`还原备份中...`); $.info(`还原备份中...`);
break; break;
} }
@ -175,7 +179,7 @@ async function updateSettings(req, res) {
// refresh resource // refresh resource
async function refreshResource(req, res) { async function refreshResource(req, res) {
const Base64 = new Base64Code(); const Base64 = new Base64Code();
const { url } = req.body; const {url} = req.body;
const raw = await downloadResource(url); const raw = await downloadResource(url);
$.write(raw, `#${Base64.safeEncode(url)}`); $.write(raw, `#${Base64.safeEncode(url)}`);
res.json({ res.json({
@ -185,7 +189,7 @@ async function refreshResource(req, res) {
// download subscription, for APP only // download subscription, for APP only
async function downloadSub(req, res) { async function downloadSub(req, res) {
const { name } = req.params; const {name} = req.params;
const platform = req.query.target || getPlatformFromHeaders(req.headers); const platform = req.query.target || getPlatformFromHeaders(req.headers);
const allSubs = $.read(SUBS_KEY); const allSubs = $.read(SUBS_KEY);
if (allSubs[name]) { if (allSubs[name]) {
@ -268,7 +272,7 @@ async function parseSub(sub, platform) {
let script; let script;
// process script // process script
if (item.type.indexOf("Script") !== -1) { if (item.type.indexOf("Script") !== -1) {
const { mode, content } = item.args; const {mode, content} = item.args;
if (mode === "link") { if (mode === "link") {
// if this is remote script, download it // if this is remote script, download it
script = await $.http script = await $.http
@ -324,13 +328,7 @@ async function parseSub(sub, platform) {
} }
// Producers // Producers
$parser.addProducers([ $parser.addProducers(AVAILABLE_PRODUCERS);
QX_Producer,
Loon_Producer,
Surge_Producer,
Raw_Producer,
URI_Producer,
]);
return $parser.produce(proxies); return $parser.produce(proxies);
} }
@ -375,7 +373,7 @@ function getFlowHeaders(headers, proxies) {
// Subscriptions // Subscriptions
async function getSub(req, res) { async function getSub(req, res) {
const { name } = req.params; const {name} = req.params;
const sub = $.read(SUBS_KEY)[name]; const sub = $.read(SUBS_KEY)[name];
if (sub) { if (sub) {
res.json({ res.json({
@ -416,7 +414,7 @@ async function newSub(req, res) {
} }
async function updateSub(req, res) { async function updateSub(req, res) {
const { name } = req.params; const {name} = req.params;
$.info(`Updating subscription: ${name}`); $.info(`Updating subscription: ${name}`);
let sub = req.body; let sub = req.body;
const allSubs = $.read(SUBS_KEY); const allSubs = $.read(SUBS_KEY);
@ -455,7 +453,7 @@ async function updateSub(req, res) {
} }
async function deleteSub(req, res) { async function deleteSub(req, res) {
const { name } = req.params; const {name} = req.params;
// delete from subscriptions // delete from subscriptions
let allSubs = $.read(SUBS_KEY); let allSubs = $.read(SUBS_KEY);
delete allSubs[name]; delete allSubs[name];
@ -490,7 +488,7 @@ async function deleteAllSubs(req, res) {
// Collections // Collections
async function downloadCollection(req, res) { async function downloadCollection(req, res) {
const { name } = req.params; const {name} = req.params;
const collection = $.read(COLLECTIONS_KEY)[name]; const collection = $.read(COLLECTIONS_KEY)[name];
const platform = getPlatformFromHeaders(req.headers); const platform = getPlatformFromHeaders(req.headers);
if (collection) { if (collection) {
@ -517,7 +515,7 @@ async function downloadCollection(req, res) {
} }
async function getCollection(req, res) { async function getCollection(req, res) {
const { name } = req.params; const {name} = req.params;
const collection = $.read(COLLECTIONS_KEY)[name]; const collection = $.read(COLLECTIONS_KEY)[name];
if (collection) { if (collection) {
res.json({ res.json({
@ -558,7 +556,7 @@ async function newCollection(req, res) {
} }
async function updateCollection(req, res) { async function updateCollection(req, res) {
const { name } = req.params; const {name} = req.params;
let collection = req.body; let collection = req.body;
const allCol = $.read(COLLECTIONS_KEY); const allCol = $.read(COLLECTIONS_KEY);
if (allCol[name]) { if (allCol[name]) {
@ -583,7 +581,7 @@ async function updateCollection(req, res) {
} }
async function deleteCollection(req, res) { async function deleteCollection(req, res) {
const { name } = req.params; const {name} = req.params;
let allCol = $.read(COLLECTIONS_KEY); let allCol = $.read(COLLECTIONS_KEY);
delete allCol[name]; delete allCol[name];
$.write(allCol, COLLECTIONS_KEY); $.write(allCol, COLLECTIONS_KEY);
@ -633,7 +631,7 @@ function ProxyParser(targetPlatform) {
if (line.startsWith("#")) continue; // skip comments if (line.startsWith("#")) continue; // skip comments
let matched = false; let matched = false;
for (const p of parsers) { for (const p of parsers) {
const { patternTest, func } = p; const {patternTest, func} = p;
// some lines with weird format may produce errors! // some lines with weird format may produce errors!
let patternMatched; let patternMatched;
@ -676,6 +674,7 @@ function ProxyParser(targetPlatform) {
function produce(proxies) { function produce(proxies) {
for (const p of producers) { for (const p of producers) {
if (p.targetPlatform === targetPlatform) { if (p.targetPlatform === targetPlatform) {
if (typeof p.type === 'undefined' || p.type === "SINGLE") {
return proxies return proxies
.map((proxy) => { .map((proxy) => {
try { try {
@ -691,6 +690,10 @@ function ProxyParser(targetPlatform) {
}) })
.filter((v) => v.length > 0) // discard empty lines .filter((v) => v.length > 0) // discard empty lines
.join("\n"); .join("\n");
} else if (p.type === 'ALL') {
return p.output(proxies);
}
} }
} }
throw new Error( throw new Error(
@ -884,7 +887,7 @@ function URI_SS() {
} }
return proxy; return proxy;
}; };
return { patternTest, func }; return {patternTest, func};
} }
// Parse URI SSR format, such as ssr://xxx // Parse URI SSR format, such as ssr://xxx
@ -946,7 +949,7 @@ function URI_SSR() {
return proxy; return proxy;
}; };
return { patternTest, func }; return {patternTest, func};
} }
// V2rayN URI VMess format // V2rayN URI VMess format
@ -1043,7 +1046,7 @@ function URI_VMess() {
return proxy; return proxy;
} }
}; };
return { patternTest, func }; return {patternTest, func};
} }
// Trojan URI format // Trojan URI format
@ -1075,7 +1078,7 @@ function URI_Trojan() {
supported, supported,
}; };
}; };
return { patternTest, func }; return {patternTest, func};
} }
/**************************** Clash ***************************************/ /**************************** Clash ***************************************/
@ -1084,7 +1087,7 @@ function Clash_All() {
return line.indexOf("{") !== -1; return line.indexOf("{") !== -1;
}; };
const func = (line) => JSON.parse(line); const func = (line) => JSON.parse(line);
return { patternTest, func }; return {patternTest, func};
} }
/**************************** Quantumult X ***************************************/ /**************************** Quantumult X ***************************************/
@ -1142,7 +1145,7 @@ function QX_SS() {
} }
return proxy; return proxy;
}; };
return { patternTest, func }; return {patternTest, func};
} }
function QX_SSR() { function QX_SSR() {
@ -1181,7 +1184,7 @@ function QX_SSR() {
} }
return proxy; return proxy;
}; };
return { patternTest, func }; return {patternTest, func};
} }
function QX_VMess() { function QX_VMess() {
@ -1217,7 +1220,7 @@ function QX_VMess() {
return proxy; return proxy;
}; };
return { patternTest, func }; return {patternTest, func};
} }
function QX_Trojan() { function QX_Trojan() {
@ -1239,7 +1242,7 @@ function QX_Trojan() {
proxy.scert = !JSON.parse(params["tls-verification"] || "true"); proxy.scert = !JSON.parse(params["tls-verification"] || "true");
return proxy; return proxy;
}; };
return { patternTest, func }; return {patternTest, func};
} }
function QX_Http() { function QX_Http() {
@ -1266,7 +1269,7 @@ function QX_Http() {
return proxy; return proxy;
}; };
return { patternTest, func }; return {patternTest, func};
} }
function getQXParams(line) { function getQXParams(line) {
@ -1316,7 +1319,7 @@ function Loon_SS() {
} }
return proxy; return proxy;
}; };
return { patternTest, func }; return {patternTest, func};
} }
function Loon_SSR() { function Loon_SSR() {
@ -1347,7 +1350,7 @@ function Loon_SSR() {
"obfs-param": params[8].match(/{(.*)}/)[1], "obfs-param": params[8].match(/{(.*)}/)[1],
}; };
}; };
return { patternTest, func }; return {patternTest, func};
} }
function Loon_VMess() { function Loon_VMess() {
@ -1395,7 +1398,7 @@ function Loon_VMess() {
} }
return proxy; return proxy;
}; };
return { patternTest, func }; return {patternTest, func};
} }
function Loon_Trojan() { function Loon_Trojan() {
@ -1426,7 +1429,7 @@ function Loon_Trojan() {
return proxy; return proxy;
}; };
return { patternTest, func }; return {patternTest, func};
} }
function Loon_Http() { function Loon_Http() {
@ -1457,7 +1460,7 @@ function Loon_Http() {
return proxy; return proxy;
}; };
return { patternTest, func }; return {patternTest, func};
} }
/**************************** Surge ***************************************/ /**************************** Surge ***************************************/
@ -1487,7 +1490,7 @@ function Surge_SS() {
} }
return proxy; return proxy;
}; };
return { patternTest, func }; return {patternTest, func};
} }
function Surge_VMess() { function Surge_VMess() {
@ -1523,7 +1526,7 @@ function Surge_VMess() {
} }
return proxy; return proxy;
}; };
return { patternTest, func }; return {patternTest, func};
} }
function Surge_Trojan() { function Surge_Trojan() {
@ -1546,7 +1549,7 @@ function Surge_Trojan() {
}; };
}; };
return { patternTest, func }; return {patternTest, func};
} }
function Surge_Http() { function Surge_Http() {
@ -1573,7 +1576,7 @@ function Surge_Http() {
if (params.password !== "none") proxy.password = params.password; if (params.password !== "none") proxy.password = params.password;
return proxy; return proxy;
}; };
return { patternTest, func }; return {patternTest, func};
} }
function getSurgeParams(line) { function getSurgeParams(line) {
@ -1605,7 +1608,7 @@ function QX_Producer() {
obfs_opts = `,obfs=${proxy["plugin-opts"].mode},obfs-host=${proxy["plugin-opts"].host}`; obfs_opts = `,obfs=${proxy["plugin-opts"].mode},obfs-host=${proxy["plugin-opts"].host}`;
} }
if (proxy.plugin === "v2ray-plugin") { if (proxy.plugin === "v2ray-plugin") {
const { tls, host, path } = proxy["plugin-opts"]; const {tls, host, path} = proxy["plugin-opts"];
obfs_opts = `,obfs=${tls ? "wss" : "ws"},obfs-host=${host}${ obfs_opts = `,obfs=${tls ? "wss" : "ws"},obfs-host=${host}${
path ? ",obfs-uri=" + path : "" path ? ",obfs-uri=" + path : ""
}`; }`;
@ -1684,7 +1687,7 @@ function QX_Producer() {
`Platform ${targetPlatform} does not support proxy type: ${proxy.type}` `Platform ${targetPlatform} does not support proxy type: ${proxy.type}`
); );
}; };
return { targetPlatform, output }; return {targetPlatform, output};
} }
function Loon_Producer() { function Loon_Producer() {
@ -1696,7 +1699,7 @@ function Loon_Producer() {
obfs_opts = ",,"; obfs_opts = ",,";
if (proxy.plugin) { if (proxy.plugin) {
if (proxy.plugin === "obfs") { if (proxy.plugin === "obfs") {
const { mode, host } = proxy["plugin-opts"]; const {mode, host} = proxy["plugin-opts"];
obfs_opts = `,${mode},${host}`; obfs_opts = `,${mode},${host}`;
} else { } else {
throw new Error( throw new Error(
@ -1745,7 +1748,7 @@ function Loon_Producer() {
`Platform ${targetPlatform} does not support proxy type: ${proxy.type}` `Platform ${targetPlatform} does not support proxy type: ${proxy.type}`
); );
}; };
return { targetPlatform, output }; return {targetPlatform, output};
} }
function Surge_Producer() { function Surge_Producer() {
@ -1813,7 +1816,7 @@ function Surge_Producer() {
`Platform ${targetPlatform} does not support proxy type: ${proxy.type}` `Platform ${targetPlatform} does not support proxy type: ${proxy.type}`
); );
}; };
return { targetPlatform, output }; return {targetPlatform, output};
} }
function Raw_Producer() { function Raw_Producer() {
@ -1821,7 +1824,7 @@ function Raw_Producer() {
const output = (proxy) => { const output = (proxy) => {
return JSON.stringify(proxy); return JSON.stringify(proxy);
}; };
return { targetPlatform, output }; return {targetPlatform, output};
} }
function URI_Producer() { function URI_Producer() {
@ -1860,7 +1863,7 @@ function URI_Producer() {
result += `#${encodeURIComponent(proxy.name)}`; result += `#${encodeURIComponent(proxy.name)}`;
break; break;
case "ssr": case "ssr":
result = `${proxy.server}:${proxy.port}:${proxy.protocol}:${ result = `ssr://${proxy.server}:${proxy.port}:${proxy.protocol}:${
proxy.cipher proxy.cipher
}:${proxy.obfs}:${Base64.safeEncode(proxy.password)}/`; }:${proxy.obfs}:${Base64.safeEncode(proxy.password)}/`;
result += `?remarks=${proxy.name}${ result += `?remarks=${proxy.name}${
@ -1872,7 +1875,6 @@ function URI_Producer() {
? "&protocolparam=" + Base64.safeEncode(proxy["protocol-param"]) ? "&protocolparam=" + Base64.safeEncode(proxy["protocol-param"])
: "" : ""
}`; }`;
result = "vmess://" + Base64.safeEncode(result);
break; break;
case "vmess": case "vmess":
// V2RayN URI format // V2RayN URI format
@ -1891,7 +1893,7 @@ function URI_Producer() {
result.path = proxy["ws-path"] || "/"; result.path = proxy["ws-path"] || "/";
result.host = proxy["ws-headers"].Host || proxy.server; result.host = proxy["ws-headers"].Host || proxy.server;
} }
result = Base64.safeEncode(JSON.stringify(result)); result = "vmess://" + Base64.safeEncode(JSON.stringify(result));
break; break;
case "trojan": case "trojan":
result = `trojan://${proxy.password}@${proxy.server}:${proxy.port}#${proxy.name}`; result = `trojan://${proxy.password}@${proxy.server}:${proxy.port}#${proxy.name}`;
@ -1901,12 +1903,41 @@ function URI_Producer() {
} }
return result; return result;
}; };
return { targetPlatform, output }; return {targetPlatform, output};
}
function Clash_Producer() {
const targetPlatform = "Clash";
const type = "ALL";
const output = (proxies) => {
return "proxies:\n" + proxies.map(proxy => {
delete proxy.supported;
return " - " + JSON.stringify(proxy) + "\n";
}).join("");
};
return {targetPlatform, type, output};
}
function Sub_Producer() {
const targetPlatform = "Sub";
const type = "ALL";
const output = (proxies) => {
const urls = proxies.map(proxy => {
try {
return URI_Producer().output(proxy) + "\n";
} catch (e) {
return "";
}
}).join("");
const Base64 = new Base64Code();
return Base64.encode(urls);
};
return {targetPlatform, type, output};
} }
/**************************** Operators ***************************************/ /**************************** Operators ***************************************/
// force to set some properties (e.g., scert, udp, tfo, etc.) // force to set some properties (e.g., scert, udp, tfo, etc.)
function SetPropertyOperator({ key, value }) { function SetPropertyOperator({key, value}) {
return { return {
name: "Set Property Operator", name: "Set Property Operator",
func: (proxies) => { func: (proxies) => {
@ -1998,7 +2029,7 @@ function KeywordRenameOperator(keywords) {
name: "Keyword Rename Operator", name: "Keyword Rename Operator",
func: (proxies) => { func: (proxies) => {
return proxies.map((proxy) => { return proxies.map((proxy) => {
for (const { old, now } of keywords) { for (const {old, now} of keywords) {
proxy.name = proxy.name.replaceAll(old, now).trim(); proxy.name = proxy.name.replaceAll(old, now).trim();
} }
return proxy; return proxy;
@ -2014,7 +2045,7 @@ function RegexRenameOperator(regex) {
name: "Regex Rename Operator", name: "Regex Rename Operator",
func: (proxies) => { func: (proxies) => {
return proxies.map((proxy) => { return proxies.map((proxy) => {
for (const { expr, now } of regex) { for (const {expr, now} of regex) {
proxy.name = proxy.name.replace(new RegExp(expr, "g"), now).trim(); proxy.name = proxy.name.replace(new RegExp(expr, "g"), now).trim();
} }
return proxy; return proxy;
@ -2092,7 +2123,7 @@ function ScriptOperator(script) {
/**************************** Filters ***************************************/ /**************************** Filters ***************************************/
// filter by keywords // filter by keywords
function KeywordFilter({ keywords = [], keep = true }) { function KeywordFilter({keywords = [], keep = true}) {
return { return {
name: "Keyword Filter", name: "Keyword Filter",
func: (proxies) => { func: (proxies) => {
@ -2147,7 +2178,7 @@ function RegionFilter(regions) {
} }
// filter by regex // filter by regex
function RegexFilter({ regex = [], keep = true }) { function RegexFilter({regex = [], keep = true}) {
return { return {
name: "Regex Filter", name: "Regex Filter",
func: (proxies) => { func: (proxies) => {
@ -2476,21 +2507,23 @@ function ENV() {
} }
function HTTP(defaultOptions = {}) { function HTTP(defaultOptions = {}) {
const { isQX, isLoon, isSurge } = ENV(); const {isQX, isLoon, isSurge} = ENV();
const methods = ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"]; const methods = ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"];
function send(method, options) { function send(method, options) {
options = options.hasOwnProperty("url") ? options : { url: options }; options = options.hasOwnProperty("url") ? options : {url: options};
options.url = defaultOptions.baseURL options.url = defaultOptions.baseURL
? defaultOptions.baseURL + options.url ? defaultOptions.baseURL + options.url
: options.url; : options.url;
options = { ...defaultOptions, ...options }; options = {...defaultOptions, ...options};
const timeout = options.timeout; const timeout = options.timeout;
const events = { const events = {
...{ ...{
onRequest: () => {}, onRequest: () => {
},
onResponse: (resp) => resp, onResponse: (resp) => resp,
onTimeout: () => {}, onTimeout: () => {
},
}, },
...options.events, ...options.events,
}; };
@ -2499,7 +2532,7 @@ function HTTP(defaultOptions = {}) {
let worker; let worker;
if (isQX) { if (isQX) {
worker = $task.fetch({ method, ...options }); worker = $task.fetch({method, ...options});
} else { } else {
worker = new Promise((resolve, reject) => { worker = new Promise((resolve, reject) => {
const request = isSurge || isLoon ? $httpClient : require("request"); const request = isSurge || isLoon ? $httpClient : require("request");
@ -2545,7 +2578,7 @@ function HTTP(defaultOptions = {}) {
} }
function API(name = "untitled", debug = false) { function API(name = "untitled", debug = false) {
const { isQX, isLoon, isSurge, isNode, isJSBox, isScriptable } = ENV(); const {isQX, isLoon, isSurge, isNode, isJSBox, isScriptable} = ENV();
return new (class { return new (class {
constructor(name, debug) { constructor(name, debug) {
this.name = name; this.name = name;
@ -2593,7 +2626,7 @@ function API(name = "untitled", debug = false) {
this.node.fs.writeFileSync( this.node.fs.writeFileSync(
fpath, fpath,
JSON.stringify({}), JSON.stringify({}),
{ flag: "wx" }, {flag: "wx"},
(err) => console.log(err) (err) => console.log(err)
); );
} }
@ -2605,7 +2638,7 @@ function API(name = "untitled", debug = false) {
this.node.fs.writeFileSync( this.node.fs.writeFileSync(
fpath, fpath,
JSON.stringify({}), JSON.stringify({}),
{ flag: "wx" }, {flag: "wx"},
(err) => console.log(err) (err) => console.log(err)
); );
this.cache = {}; this.cache = {};
@ -2626,13 +2659,13 @@ function API(name = "untitled", debug = false) {
this.node.fs.writeFileSync( this.node.fs.writeFileSync(
`${this.name}.json`, `${this.name}.json`,
data, data,
{ flag: "w" }, {flag: "w"},
(err) => console.log(err) (err) => console.log(err)
); );
this.node.fs.writeFileSync( this.node.fs.writeFileSync(
"root.json", "root.json",
JSON.stringify(this.root), JSON.stringify(this.root),
{ flag: "w" }, {flag: "w"},
(err) => console.log(err) (err) => console.log(err)
); );
} }
@ -2766,7 +2799,7 @@ function API(name = "untitled", debug = false) {
/*********************************** Mini Express *************************************/ /*********************************** Mini Express *************************************/
function express(port = 3000) { function express(port = 3000) {
const { isNode } = ENV(); const {isNode} = ENV();
const DEFAULT_HEADERS = { const DEFAULT_HEADERS = {
"Content-Type": "text/plain;charset=UTF-8", "Content-Type": "text/plain;charset=UTF-8",
"Access-Control-Allow-Origin": "*", "Access-Control-Allow-Origin": "*",
@ -2780,9 +2813,9 @@ function express(port = 3000) {
const express_ = require("express"); const express_ = require("express");
const bodyParser = require("body-parser"); const bodyParser = require("body-parser");
const app = express_(); const app = express_();
app.use(bodyParser.json({ verify: rawBodySaver })); app.use(bodyParser.json({verify: rawBodySaver}));
app.use(bodyParser.urlencoded({ verify: rawBodySaver, extended: true })); app.use(bodyParser.urlencoded({verify: rawBodySaver, extended: true}));
app.use(bodyParser.raw({ verify: rawBodySaver, type: "*/*" })); app.use(bodyParser.raw({verify: rawBodySaver, type: "*/*"}));
app.use((req, res, next) => { app.use((req, res, next) => {
res.set(DEFAULT_HEADERS); res.set(DEFAULT_HEADERS);
next(); next();
@ -2814,19 +2847,19 @@ function express(port = 3000) {
// dispatch url to route // dispatch url to route
const dispatch = (request, start = 0) => { const dispatch = (request, start = 0) => {
let { method, url, headers, body } = request; let {method, url, headers, body} = request;
if (/json/i.test(headers["Content-Type"])) { if (/json/i.test(headers["Content-Type"])) {
body = JSON.parse(body); body = JSON.parse(body);
} }
method = method.toUpperCase(); method = method.toUpperCase();
const { path, query } = extractURL(url); const {path, query} = extractURL(url);
let handler = null; let handler = null;
let i; let i;
for (i = start; i < handlers.length; i++) { for (i = start; i < handlers.length; i++) {
if (handlers[i].method === "ALL" || method === handlers[i].method) { if (handlers[i].method === "ALL" || method === handlers[i].method) {
const { pattern } = handlers[i]; const {pattern} = handlers[i];
if (patternMatched(pattern, path)) { if (patternMatched(pattern, path)) {
handler = handlers[i]; handler = handlers[i];
break; break;
@ -2870,7 +2903,7 @@ function express(port = 3000) {
METHODS_NAMES.forEach((method) => { METHODS_NAMES.forEach((method) => {
app[method.toLowerCase()] = (pattern, callback) => { app[method.toLowerCase()] = (pattern, callback) => {
// add handler // add handler
handlers.push({ method, pattern, callback }); handlers.push({method, pattern, callback});
}; };
}); });
@ -2880,7 +2913,7 @@ function express(port = 3000) {
METHODS_NAMES.forEach((method) => { METHODS_NAMES.forEach((method) => {
chainApp[method.toLowerCase()] = (callback) => { chainApp[method.toLowerCase()] = (callback) => {
// add handler // add handler
handlers.push({ method, pattern, callback }); handlers.push({method, pattern, callback});
return chainApp; return chainApp;
}; };
}); });
@ -2905,7 +2938,7 @@ function express(port = 3000) {
function Response() { function Response() {
let statusCode = 200; let statusCode = 200;
const { isQX, isLoon, isSurge } = ENV(); const {isQX, isLoon, isSurge} = ENV();
const headers = DEFAULT_HEADERS; const headers = DEFAULT_HEADERS;
const STATUS_CODE_MAP = { const STATUS_CODE_MAP = {
200: "HTTP/1.1 200 OK", 200: "HTTP/1.1 200 OK",
@ -3060,10 +3093,10 @@ function Gist(backupKey, token) {
}); });
} }
this.upload = async function(content) { this.upload = async function (content) {
const id = await locate(); const id = await locate();
const files = { const files = {
[FILE_NAME]: { content } [FILE_NAME]: {content}
}; };
if (id === -1) { if (id === -1) {
@ -3080,18 +3113,18 @@ function Gist(backupKey, token) {
// update an existing gist // update an existing gist
return http.patch({ return http.patch({
url: `/gists/${id}`, url: `/gists/${id}`,
body: JSON.stringify({ files }) body: JSON.stringify({files})
}); });
} }
}; };
this.download = async function() { this.download = async function () {
const id = await locate(); const id = await locate();
if (id === -1) { if (id === -1) {
return Promise.reject("未找到Gist备份"); return Promise.reject("未找到Gist备份");
} else { } else {
try { try {
const { files } = await http const {files} = await http
.get(`/gists/${id}`) .get(`/gists/${id}`)
.then(resp => JSON.parse(resp.body)); .then(resp => JSON.parse(resp.body));
const url = files[FILE_NAME].raw_url; const url = files[FILE_NAME].raw_url;
@ -3102,6 +3135,7 @@ function Gist(backupKey, token) {
} }
}; };
} }
/******************************** Base 64 *********************************************/ /******************************** Base 64 *********************************************/
// Base64 Coding Library // Base64 Coding Library
// https://github.com/dankogai/js-base64#readme // https://github.com/dankogai/js-base64#readme

File diff suppressed because one or more lines are too long