import fs from 'fs'; import cluster from 'cluster'; import path from 'path'; import * as superagent from 'superagent'; import proxyAgent from 'proxy-agent'; import serialize from 'serialize-javascript'; import Lru from 'lru-cache'; declare global { interface StringConstructor { random: (digit?: number) => string; } interface ArrayConstructor { isDiff: (a: any[], b: any[]) => boolean; } interface Date { format: (fmt?: string) => string; } interface Math { sum: (...args: Array) => number; } interface SetConstructor { isSuperset: (set: Set, subset: Set) => boolean; intersection: (setA: Set, setB: Set) => Set; union: (setA: Set, setB: Set) => Set; } } const lru = new Lru(1000); export function lrucache(target: any, funcName: string, obj: any) { const originalMethod = obj.value; obj.value = function func(...args: any[]) { const key = serialize({ funcName, args }); let val = lru.get(key); if (val) return val; val = originalMethod.call(this, ...args); lru.set(key, val); return val; }; return obj; } namespace Proxy { function getUrl() { return this._url; } function setUrl(v: string) { this._url = v; // eslint-disable-next-line no-use-before-define proxy.call(this, this._proxyUri); } function setupUrl(req: superagent.Request) { const desc = Object.getOwnPropertyDescriptor(req, 'url'); if (desc.get === getUrl && desc.set === setUrl) return; // @ts-ignore req._url = req.url; desc.get = getUrl; desc.set = setUrl; delete desc.value; delete desc.writable; Object.defineProperty(req, 'url', desc); } function proxy(uri: string) { if (!uri) return this; setupUrl(this); const agent = proxyAgent(uri); if (agent) this.agent(agent); this._proxyUri = uri; return this; } export function setup(agent, uri = '') { const Request = agent.Request; if (Request) { Request.prototype.proxy = proxy; return agent; } return proxy.call(agent, uri); } } declare module 'superagent' { interface Request { proxy(url: string): this; } } Proxy.setup(superagent); if (!cluster.worker) { // @ts-ignore cluster.worker = { id: 0 }; } const dict = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'; String.random = function random(digit = 32) { let str = ''; for (let i = 1; i <= digit; i++) str += dict[Math.floor(Math.random() * 62)]; return str; }; Array.isDiff = function isDiff(a, b) { if (a.length !== b.length) return true; a.sort(); b.sort(); for (const i in a) { if (a[i] !== b[i]) return true; } return false; }; Date.prototype.format = function formatDate(fmt = '%Y-%m-%d %H:%M:%S') { let m = this.getMonth() + 1; if (m < 10) m = `0${m}`; let d = this.getDate(); if (d < 10) d = `0${d}`; let H = this.getHours(); if (H < 10) H = `0${H}`; let M = this.getMinutes(); if (M < 10) M = `0${M}`; let S = this.getSeconds(); if (S < 10) S = `0${S}`; return fmt .replace('%Y', this.getFullYear()) .replace('%m', m) .replace('%d', d) .replace('%H', H) .replace('%M', M) .replace('%S', S); }; Math.sum = function sum(...args) { let s = 0; for (const i of args) { if (i instanceof Array) { for (const j of i) { s += j; } } else s += i; } return s; }; Set.isSuperset = function isSuperset(set, subset) { for (const elem of subset) { if (!set.has(elem)) return false; } return true; }; Set.union = function Union(setA: Set, setB: Set) { const union = new Set(setA); for (const elem of setB) union.add(elem); return union; }; Set.intersection = function Intersection(setA: Set, setB: Set): Set { const intersection = new Set(); for (const elem of setB) { if (setA.has(elem)) intersection.add(elem); } // @ts-ignore return intersection; }; export function folderSize(folderPath: string) { let size = 0; const _next = function a(p: string) { if (p) { const stats = fs.statSync(p); if (!stats.isDirectory() || stats.isSymbolicLink()) { if (!stats.isSymbolicLink()) size += stats.size; } else { size += stats.size; const files = fs.readdirSync(p); if (Array.isArray(files)) { files.forEach((file) => { _next(path.join(p, file)); }); } } } }; _next(folderPath); return size; } const TIME_RE = /^([0-9]+(?:\.[0-9]*)?)([mu]?)s?$/i; const TIME_UNITS = { '': 1000, m: 1, u: 0.001 }; const MEMORY_RE = /^([0-9]+(?:\.[0-9]*)?)([kmg])b?$/i; const MEMORY_UNITS = { k: 0.1, m: 1, g: 1024 }; export function parseTimeMS(str: string) { const match = TIME_RE.exec(str); if (!match) throw new Error(`${str} error parsing time`); return Math.floor(parseFloat(match[1]) * TIME_UNITS[match[2]]); } export function parseMemoryMB(str: string) { const match = MEMORY_RE.exec(str); if (!match) throw new Error(`${str} error parsing memory`); return Math.floor(parseFloat(match[1]) * MEMORY_UNITS[match[2]]); } export function isClass(obj: any, strict = false) { if (typeof obj !== 'function') return false; const str = obj.toString(); if (obj.prototype === undefined) return false; if (obj.prototype.constructor !== obj) return false; if (str.slice(0, 5) === 'class') return true; if (Object.getOwnPropertyNames(obj.prototype).length >= 2) return true; if (/^function\s+\(|^function\s+anonymous\(/.test(str)) return false; if (strict && /^function\s+[A-Z]/.test(str)) return true; if (/\b\(this\b|\bthis[.[]\b/.test(str)) { if (!strict || /classCallCheck\(this/.test(str)) return true; return /^function\sdefault_\d+\s*\(/.test(str); } return false; }