mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
Hello airbnb
This commit is contained in:
1 parent
f9468536de
commit
8c195661d7
78 files changed
+2032
-1471
No files matched your search
+24
-21
@@ -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
@@ -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;
|
||||
}
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -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
@@ -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
@@ -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]);
|
||||
};
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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')
|
||||
|
||||
*/
|
||||
*/
|
||||
Reference in new issue
Block a user