UNPKG

@waline/vercel

Version:

vercel server for waline comment system

191 lines (152 loc) 3.98 kB
const IP2Region = require('ip2region').default; const parser = require('ua-parser-js'); const preventMessage = 'PREVENT_NEXT_PROCESS'; // Cached IP2Region instance using IIFE closure pattern // Instance is created on first access and reused for all subsequent calls const getIP2RegionInstance = (() => { let instance = null; return () => { if (!instance) { instance = new IP2Region({ ipv4db: process.env.IP2REGION_DB_V4 || process.env.IP2REGION_DB, ipv6db: process.env.IP2REGION_DB_V6, }); } return instance; }; })(); const OS_VERSION_MAP = { Windows: { 'NT 11.0': '11', }, }; module.exports = { prevent() { throw new Error(preventMessage); }, isPrevent(err) { return think.isError(err) && err.message === preventMessage; }, findLastIndex(arr, fn) { for (let i = arr.length - 1; i >= 0; i--) { const ret = fn(arr[i], i, arr); if (!ret) { continue; } return i; } return -1; }, promiseAllQueue(promises, taskNum) { return new Promise((resolve, reject) => { if (promises.length === 0) { resolve(); return; } const ret = []; let index = 0; let count = 0; const runTask = () => { const idx = index; index += 1; if (index > promises.length) { return Promise.resolve(); } return promises[idx].then((data) => { ret[idx] = data; count += 1; if (count === promises.length) { resolve(ret); } return runTask(); }, reject); }; for (let i = 0; i < taskNum; i++) { runTask(); } }); }, async ip2region(ip, { depth = 1 }) { if (!ip) return ''; try { const res = getIP2RegionInstance().search(ip); if (!res) { return ''; } const { province, city, isp } = res; const address = [...new Set([province, city, isp].filter(Boolean))]; return address.slice(0, depth).join(' '); } catch (err) { console.log(err); return ''; } }, uaParser(uaText) { const ua = parser(uaText); if (OS_VERSION_MAP[ua.os.name]?.[ua.os.version]) { ua.os.version = OS_VERSION_MAP[ua.os.name][ua.os.version]; } return ua; }, getLevel(val) { const levels = this.config('levels'); const defaultLevel = 0; if (!val) { return defaultLevel; } const level = think.findLastIndex(levels, (level) => level <= val); return level === -1 ? defaultLevel : level; }, pluginMap(type, callback) { const plugins = think.config('plugins'); const fns = []; if (!think.isArray(plugins)) { return fns; } for (const plugin of plugins) { if (!plugin?.[type]) { continue; } const res = callback(plugin[type]); if (!res) { continue; } fns.push(res); } return fns; }, getPluginMiddlewares() { const middlewares = think.pluginMap('middlewares', (middleware) => { if (think.isFunction(middleware)) { return middleware; } if (think.isArray(middleware)) { return middleware.filter((middleware) => think.isFunction(middleware)); } }); return middlewares.flat(); }, getPluginHook(hookName) { return think .pluginMap('hooks', (hook) => (think.isFunction(hook[hookName]) ? hook[hookName] : null)) .filter(Boolean); }, buildUrl(path, query = {}) { const notEmptyQuery = {}; for (const key in query) { if (!query[key]) { continue; } notEmptyQuery[key] = query[key]; } const notEmptyQueryStr = new URLSearchParams(notEmptyQuery).toString(); let destUrl = path; if (destUrl && notEmptyQueryStr) { destUrl += destUrl.includes('?') ? '&' : '?'; } if (notEmptyQueryStr) { destUrl += notEmptyQueryStr; } return destUrl; }, };