Hello airbnb

This commit is contained in:
masnn committed 2020-04-15 15:08:05 +08:00
1 parent f9468536de
commit 8c195661d7
78 files changed
+2032 -1471

No files matched your search

+24 -21
View File
@@ -1,37 +1,40 @@
const
fs = require('fs'),
yaml = require('js-yaml');
const fs = require('fs');
const yaml = require('js-yaml');
let locales = {};
const locales = {};
String.prototype.format = function (args) {
var result = this;
if (arguments.length > 0) {
if (arguments.length == 1 && typeof (args) == 'object') {
for (var key in args)
if (args[key] != undefined) {
let reg = new RegExp('(\\{' + key + '\\})', 'g');
String.prototype.format = function formatStr(...args) {
let result = this;
if (args.length > 0) {
if (args.length === 1 && typeof (args[0]) === 'object') {
for (const key in args) {
if (args[key] !== undefined) {
const reg = new RegExp(`(\\{${key}\\})`, 'g');
result = result.replace(reg, args[key]);
}
} else for (var i = 0; i < arguments.length; i++)
if (arguments[i] != undefined) {
let reg = new RegExp('(\\{)' + i + '(\\})', 'g');
result = result.replace(reg, arguments[i]);
}
} else {
for (let i = 0; i < args.length; i++) {
if (args[i] !== undefined) {
const reg = new RegExp(`(\\{)${i}(\\})`, 'g');
result = result.replace(reg, args[i]);
}
}
}
}
return result;
};
String.prototype.rawformat = function (object) {
let res = this.split('{@}');
String.prototype.rawformat = function rawFormat(object) {
const res = this.split('{@}');
return [res[0], object, res[1]];
};
String.prototype.translate = function (language = 'zh_CN') {
String.prototype.translate = function translate(language = 'zh_CN') {
if (locales[language]) return locales[language][this] || this;
else return this;
return this;
};
module.exports = function load(file, language) {
if (!locales[language]) locales[language] = {};
let content = fs.readFileSync(file).toString();
const content = fs.readFileSync(file).toString();
Object.assign(locales[language], yaml.safeLoad(content));
};
};
+13 -11
View File
@@ -1,7 +1,6 @@
const
nodemailer = require('nodemailer'),
options = require('../options'),
{ SendMailError } = require('../error');
const nodemailer = require('nodemailer');
const options = require('../options');
const { SendMailError } = require('../error');
let transporter = null;
try {
@@ -11,8 +10,8 @@ try {
secure: options.VJ_SMTP_SECURE,
auth: {
user: options.VJ_SMTP_USER,
pass: options.VJ_SMTP_PASSWORD
}
pass: options.VJ_SMTP_PASSWORD,
},
});
} catch (e) {
console.error(e);
@@ -20,8 +19,8 @@ try {
module.exports = {
/**
* @param {string} to
* @param {string} subject
* @param {string} to
* @param {string} subject
* @param {string} text
* @param {string} html
*/
@@ -31,7 +30,10 @@ module.exports = {
t = await new Promise((resolve, reject) => {
transporter.sendMail({
from: options.VJ_SMTP_FROM,
to, subject, text, html
to,
subject,
text,
html,
}, (err, info) => {
if (err) reject(err);
else resolve(info);
@@ -41,5 +43,5 @@ module.exports = {
throw new SendMailError(to);
}
return t;
}
};
},
};
+7 -7
View File
@@ -1,19 +1,19 @@
const
hljs = require('highlight.js'),
MarkdownIt = require('markdown-it'),
katex = require('markdown-it-katex');
const hljs = require('highlight.js');
const MarkdownIt = require('markdown-it');
const katex = require('markdown-it-katex');
class Markdown extends MarkdownIt {
constructor() {
super({
linkify: true,
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang))
highlight(str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return hljs.highlight(lang, str).value;
} catch (__) { } // eslint-disable-line no-empty
}
return '';
}
},
});
this.linkify.tlds('.py', false);
this.use(katex);
+27 -31
View File
@@ -1,8 +1,7 @@
'use strict';
/* eslint-disable no-bitwise */
function safeAdd(x, y) {
var lsw = (x & 0xffff) + (y & 0xffff);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
const lsw = (x & 0xffff) + (y & 0xffff);
const msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xffff);
}
const bitRotateLeft = (num, cnt) => (num << cnt) | (num >>> (32 - cnt));
@@ -14,15 +13,15 @@ const md5ii = (a, b, c, d, x, s, t) => md5cmn(c ^ (b | ~d), a, b, x, s, t);
function binlMD5(x, len) {
x[len >> 5] |= 0x80 << len % 32;
x[(((len + 64) >>> 9) << 4) + 14] = len;
var i;
var olda;
var oldb;
var oldc;
var oldd;
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
let i;
let olda;
let oldb;
let oldc;
let oldd;
let a = 1732584193;
let b = -271733879;
let c = -1732584194;
let d = 271733878;
for (i = 0; i < x.length; i += 16) {
olda = a;
oldb = b;
@@ -100,34 +99,31 @@ function binlMD5(x, len) {
return [a, b, c, d];
}
function binl2rstr(input) {
var i;
var output = '';
var length32 = input.length * 32;
for (i = 0; i < length32; i += 8)
output += String.fromCharCode((input[i >> 5] >>> i % 32) & 0xff);
let i;
let output = '';
const length32 = input.length * 32;
for (i = 0; i < length32; i += 8) { output += String.fromCharCode((input[i >> 5] >>> i % 32) & 0xff); }
return output;
}
function rstr2binl(input) {
var i;
var output = [];
let i;
const output = [];
output[(input.length >> 2) - 1] = undefined;
for (i = 0; i < output.length; i += 1)
output[i] = 0;
var length8 = input.length * 8;
for (i = 0; i < length8; i += 8)
output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << i % 32;
for (i = 0; i < output.length; i += 1) { output[i] = 0; }
const length8 = input.length * 8;
for (i = 0; i < length8; i += 8) output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << i % 32;
return output;
}
const rstrMD5 = s => binl2rstr(binlMD5(rstr2binl(s), s.length * 8));
const rstrMD5 = (s) => binl2rstr(binlMD5(rstr2binl(s), s.length * 8));
function rstr2hex(input) {
var hexTab = '0123456789abcdef';
var output = '';
var x;
var i;
const hexTab = '0123456789abcdef';
let output = '';
let x;
let i;
for (i = 0; i < input.length; i += 1) {
x = input.charCodeAt(i);
output += hexTab.charAt((x >>> 4) & 0x0f) + hexTab.charAt(x & 0x0f);
}
return output;
}
module.exports = s => rstr2hex(rstrMD5(unescape(encodeURIComponent(s))));
module.exports = (s) => rstr2hex(rstrMD5(unescape(encodeURIComponent(s))));
+23 -20
View File
@@ -1,41 +1,44 @@
const md5 = require('./md5');
exports.gravatar_url = function (email, size) {
exports.gravatar_url = function gravatarUrl(email, size) {
return `//gravatar.loli.net/avatar/${md5((email || '').toString().trim().toLowerCase())}?d=mm&s=${size}`;
};
exports.datetime_span = function (dt, relative = true, format = '%Y-%m-%d %H:%M:%S') {
exports.datetime_span = function datetimeSpan(dt, relative = true, format = '%Y-%m-%d %H:%M:%S') {
if (dt.generationTime) dt = new Date(dt.generationTime * 1000);
else if (typeof dt == 'number' || typeof dt == 'string') dt = new Date(dt);
else if (typeof dt === 'number' || typeof dt === 'string') dt = new Date(dt);
return '<span class="time{0}" data-timestamp="{1}">{2}</span>'.format(
relative ? ' relative' : '',
dt.getTime() / 1000,
dt.format(format)
dt.format(format),
);
};
exports.paginate = function* (page, num_pages) {
let radius = 2, first, last;
exports.paginate = function* paginate(page, numPages) {
const radius = 2; let first; let
last;
if (page > 1) {
yield ['first', 1];
yield ['previous', page - 1];
}
if (page <= radius) [first, last] = [1, Math.min(1 + radius * 2, num_pages)];
else if (page >= num_pages - radius) [first, last] = [Math.max(1, num_pages - radius * 2), num_pages];
else[first, last] = [page - radius, page + radius];
if (page <= radius) [first, last] = [1, Math.min(1 + radius * 2, numPages)];
else if (page >= numPages - radius) {
[first, last] = [Math.max(1, numPages - radius * 2), numPages];
} else [first, last] = [page - radius, page + radius];
if (first > 1) yield ['ellipsis', 0];
for (let page0 = first; page0 < last + 1; page0++) {
if (page0 != page) yield ['page', page0];
if (page0 !== page) yield ['page', page0];
else yield ['current', page];
}
if (last < num_pages) yield ['ellipsis', 0];
if (page < num_pages) yield ['next', page + 1];
yield ['last', num_pages];
if (last < numPages) yield ['ellipsis', 0];
if (page < numPages) yield ['next', page + 1];
yield ['last', numPages];
};
exports.format_size = function (size, base = 1) {
exports.format_size = function formatSize(size, base = 1) {
size *= base;
let unit = 1024;
let unit_names = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
for (let unit_name of unit_names) {
if (size < unit) return '{0} {1}'.format(Math.round(size), unit_name);
const unit = 1024;
const unitNames = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
for (const unitName of unitNames) {
if (size < unit) return '{0} {1}'.format(Math.round(size), unitName);
size /= unit;
}
return '{0} {1}'.format(Math.round(size * unit), unit_names[unit_names.length - 1]);
};
return '{0} {1}'.format(Math.round(size * unit), unitNames[unitNames.length - 1]);
};
+6 -5
View File
@@ -1,10 +1,11 @@
const { ValidationError } = require('../error');
module.exports = async function paginate(cursor, page, page_size) {
module.exports = async function paginate(cursor, page, pageSize) {
if (page <= 0) throw new ValidationError('page');
let [count, page_docs] = await Promise.all([
const [count, pageDocs] = await Promise.all([
cursor.count(),
cursor.skip((page - 1) * page_size).limit(page_size).toArray()
cursor.skip((page - 1) * pageSize).limit(pageSize).toArray(),
]);
let num_pages = Math.floor((count + page_size - 1) / page_size);
return [page_docs, num_pages, count];
const numPages = Math.floor((count + pageSize - 1) / pageSize);
return [pageDocs, numPages, count];
};
+9 -8
View File
@@ -1,26 +1,27 @@
const crypto = require('crypto');
module.exports = {
_b64encode: str => new Buffer(str).toString('base64'),
_b64decode: str => new Buffer(str, 'base64').toString(),
_md5: str => crypto.createHash('md5').update(str).digest('hex'),
_sha1: str => crypto.createHash('sha1').update(str).digest('hex'),
_b64encode: (str) => Buffer.from(str).toString('base64'),
_b64decode: (str) => Buffer.from(str, 'base64').toString(),
_md5: (str) => crypto.createHash('md5').update(str).digest('hex'),
_sha1: (str) => crypto.createHash('sha1').update(str).digest('hex'),
/**
* @param {string} password
* @param {string} salt
* @param {string} hash
*/
check(password, salt, hash) {
return hash == this.hash(password, salt);
return hash === this.hash(password, salt);
},
/**
* @param {string} password
* @param {string} salt
*/
hash(password, salt) {
let res = crypto.pbkdf2Sync(password, salt, 100000, 64, 'sha256');
const res = crypto.pbkdf2Sync(password, salt, 100000, 64, 'sha256');
return res.toString('Hex');
},
salt() {
return String.random();
}
};
},
};
+7 -7
View File
@@ -1,11 +1,11 @@
module.exports = function* ranked(diter, equ = (a, b) => a == b) {
let last_doc = null;
let r = 0, count = 0;
for (let doc of diter) {
module.exports = function* ranked(diter, equ = (a, b) => a === b) {
let last = null;
let r = 0;
let count = 0;
for (const doc of diter) {
count++;
if (count == 1 || !equ(last_doc, doc))
r = count;
last_doc = doc;
if (count === 1 || !equ(last, doc)) r = count;
last = doc;
yield [r, doc];
}
};
+17 -24
View File
@@ -1,34 +1,27 @@
const
path = require('path'),
nunjucks = require('nunjucks'),
markdown = require('./markdown'),
options = require('../options'),
perm = require('../permission'),
builtin = require('../model/builtin'),
model = require('../model'),
misc = require('../lib/misc');
const path = require('path');
const nunjucks = require('nunjucks');
const markdown = require('./markdown');
const options = require('../options');
const perm = require('../permission');
const builtin = require('../model/builtin');
const model = require('../model');
const misc = require('./misc');
class Nunjucks extends nunjucks.Environment {
constructor() {
super(
new nunjucks.FileSystemLoader(path.resolve(options.template.path)),
{ autoescape: true, trimBlocks: true }
{ autoescape: true, trimBlocks: true },
);
this.addFilter('json', function (self) {
return JSON.stringify(self);
}, false);
this.addFilter('assign', function (self, data) {
return Object.assign(self, data);
});
this.addFilter('markdown', function (self) {
return markdown.render(self);
});
this.addFilter('json', (self) => JSON.stringify(self), false);
this.addFilter('assign', (self, data) => Object.assign(self, data));
this.addFilter('markdown', (self) => markdown.render(self));
this.addFilter('gravatar_url', misc.gravatar_url);
this.addFilter('format_size', misc.format_size);
this.addGlobal('typeof', o => typeof o);
this.addGlobal('typeof', (o) => typeof o);
this.addGlobal('console', console);
this.addGlobal('static_url', str => `/${str}`);
this.addGlobal('reverse_url', str => str);
this.addGlobal('static_url', (str) => `/${str}`);
this.addGlobal('reverse_url', (str) => str);
this.addGlobal('datetime_span', misc.datetime_span);
this.addGlobal('paginate', misc.paginate);
this.addGlobal('perm', perm);
@@ -36,6 +29,6 @@ class Nunjucks extends nunjucks.Environment {
this.addGlobal('model', model);
}
}
let env = new Nunjucks();
const env = new Nunjucks();
module.exports = env;
module.exports = env;
+39 -32
View File
@@ -1,37 +1,44 @@
const
{ ValidationError } = require('../error'),
RE_UID = /^-?\d+$/i,
RE_PID = /^([a-zA-Z]+[a-zA-Z0-9]*)|$/i,
RE_UNAME = /[^\s\u3000](.{,254}[^\s\u3000])?$/i,
RE_MAIL = /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)+$/i;
const { ValidationError } = require('../error');
const
isTitle = s => s && s.length < 64,
checkTitle = s => { if (!isTitle(s)) throw new ValidationError('title'); else return s; },
isUid = s => RE_UID.test(s),
checkUid = s => { if (!isUid(s)) throw new ValidationError('uid'); else return s; },
isUname = s => RE_UNAME.test(s),
checkUname = s => { if (!isUname(s)) throw new ValidationError('uname'); else return s; },
isPassword = s => s.length >= 5,
checkPassword = s => { if (!isPassword(s)) throw new ValidationError('password'); else return s; },
isEmail = s => RE_MAIL.test(s),
checkEmail = s => { if (!isEmail(s)) throw new ValidationError('mail'); else return s; },
isContent = s => s && s.length < 65536,
checkContent = s => { if (!isContent(s)) throw new ValidationError('content'); else return s; },
isName = s => s && s.length < 256,
checkName = s => { if (!isName(s)) throw new ValidationError('name'); else return s; },
isPid = s => RE_PID.test(s.toString()),
checkPid = s => { if (!RE_PID.test(s)) throw new ValidationError('pid'); else return s; };
const RE_UID = /^-?\d+$/i;
const RE_PID = /^([a-zA-Z]+[a-zA-Z0-9]*)|$/i;
const RE_UNAME = /[^\s\u3000](.{,254}[^\s\u3000])?$/i;
const RE_MAIL = /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)+$/i;
const isTitle = (s) => s && s.length < 64;
const checkTitle = (s) => { if (!isTitle(s)) throw new ValidationError('title'); else return s; };
const isUid = (s) => RE_UID.test(s);
const checkUid = (s) => { if (!isUid(s)) throw new ValidationError('uid'); else return s; };
const isUname = (s) => RE_UNAME.test(s);
const checkUname = (s) => { if (!isUname(s)) throw new ValidationError('uname'); else return s; };
const isPassword = (s) => s.length >= 5;
const checkPassword = (s) => { if (!isPassword(s)) throw new ValidationError('password'); else return s; };
const isEmail = (s) => RE_MAIL.test(s);
const checkEmail = (s) => { if (!isEmail(s)) throw new ValidationError('mail'); else return s; };
const isContent = (s) => s && s.length < 65536;
const checkContent = (s) => { if (!isContent(s)) throw new ValidationError('content'); else return s; };
const isName = (s) => s && s.length < 256;
const checkName = (s) => { if (!isName(s)) throw new ValidationError('name'); else return s; };
const isPid = (s) => RE_PID.test(s.toString());
const checkPid = (s) => { if (!RE_PID.test(s)) throw new ValidationError('pid'); else return s; };
module.exports = {
isTitle, checkTitle,
isUid, checkUid,
isUname, checkUname,
isPassword, checkPassword,
isEmail, checkEmail,
isContent, checkContent,
isName, checkName,
isPid, checkPid
isTitle,
checkTitle,
isUid,
checkUid,
isUname,
checkUname,
isPassword,
checkPassword,
isEmail,
checkEmail,
isContent,
checkContent,
isName,
checkName,
isPid,
checkPid,
};
/*
ID_RE = re.compile(r'[^\\/\s\u3000]([^\\/\n\r]*[^\\/\s\u3000])?')
@@ -104,4 +111,4 @@ def check_domain_invitation_code(s):
if not is_domain_invitation_code(s):
raise error.ValidationError('invitation_code')
*/
*/