mirror of https://github.com/calzoneman/sync.git
289 lines
7.9 KiB
JavaScript
289 lines
7.9 KiB
JavaScript
(function () {
|
|
const root = module.exports;
|
|
const net = require("net");
|
|
const crypto = require("crypto");
|
|
|
|
root.isValidChannelName = function (name) {
|
|
return name.match(/^[\w-]{1,30}$/);
|
|
},
|
|
|
|
root.isValidUserName = function (name) {
|
|
return name.match(/^[\w-]{1,20}$/);
|
|
},
|
|
|
|
root.isValidEmail = function (email) {
|
|
if (typeof email !== "string") {
|
|
return false;
|
|
}
|
|
|
|
if (email.length > 255) {
|
|
return false;
|
|
}
|
|
|
|
if (!email.match(/^[^@]+?@[^@]+$/)) {
|
|
return false;
|
|
}
|
|
|
|
if (email.match(/^[^@]+?@(localhost|127\.0\.0\.1)$/)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
},
|
|
|
|
root.randomSalt = function (length) {
|
|
var chars = "abcdefgihjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
+ "0123456789!@#$%^&*_+=~";
|
|
var salt = [];
|
|
for(var i = 0; i < length; i++) {
|
|
salt.push(chars[parseInt(Math.random()*chars.length)]);
|
|
}
|
|
return salt.join('');
|
|
},
|
|
|
|
root.getIPRange = function (ip) {
|
|
if (net.isIPv6(ip)) {
|
|
return root.expandIPv6(ip)
|
|
.replace(/((?:[0-9a-f]{4}:){3}[0-9a-f]{4}):(?:[0-9a-f]{4}:){3}[0-9a-f]{4}/, "$1");
|
|
} else {
|
|
return ip.replace(/((?:[0-9]+\.){2}[0-9]+)\.[0-9]+/, "$1");
|
|
}
|
|
},
|
|
|
|
root.getWideIPRange = function (ip) {
|
|
if (net.isIPv6(ip)) {
|
|
return root.expandIPv6(ip)
|
|
.replace(/((?:[0-9a-f]{4}:){2}[0-9a-f]{4}):(?:[0-9a-f]{4}:){4}[0-9a-f]{4}/, "$1");
|
|
} else {
|
|
return ip.replace(/([0-9]+\.[0-9]+)\.[0-9]+\.[0-9]+/, "$1");
|
|
}
|
|
},
|
|
|
|
root.expandIPv6 = function (ip) {
|
|
var result = "0000:0000:0000:0000:0000:0000:0000:0000".split(":");
|
|
var parts = ip.split("::");
|
|
var left = parts[0].split(":");
|
|
var i = 0;
|
|
left.forEach(function (block) {
|
|
while (block.length < 4) {
|
|
block = "0" + block;
|
|
}
|
|
result[i++] = block;
|
|
});
|
|
|
|
if (parts.length > 1) {
|
|
var right = parts[1].split(":");
|
|
i = 7;
|
|
right.forEach(function (block) {
|
|
while (block.length < 4) {
|
|
block = "0" + block;
|
|
}
|
|
result[i--] = block;
|
|
});
|
|
}
|
|
|
|
return result.join(":");
|
|
},
|
|
|
|
root.formatTime = function (sec) {
|
|
if(sec === "--:--")
|
|
return sec;
|
|
|
|
sec = Math.floor(+sec);
|
|
var h = "", m = "", s = "";
|
|
|
|
if(sec >= 3600) {
|
|
h = "" + Math.floor(sec / 3600);
|
|
if(h.length < 2)
|
|
h = "0" + h;
|
|
sec %= 3600;
|
|
}
|
|
|
|
m = "" + Math.floor(sec / 60);
|
|
if(m.length < 2)
|
|
m = "0" + m;
|
|
|
|
s = "" + (sec % 60);
|
|
if(s.length < 2)
|
|
s = "0" + s;
|
|
|
|
if(h === "")
|
|
return [m, s].join(":");
|
|
|
|
return [h, m, s].join(":");
|
|
},
|
|
|
|
root.parseTime = function (time) {
|
|
var parts = time.split(":").reverse();
|
|
var seconds = 0;
|
|
// TODO: consider refactoring to remove this suppression
|
|
/* eslint no-fallthrough: off */
|
|
switch (parts.length) {
|
|
case 3:
|
|
seconds += parseInt(parts[2]) * 3600;
|
|
case 2:
|
|
seconds += parseInt(parts[1]) * 60;
|
|
case 1:
|
|
seconds += parseInt(parts[0]);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return seconds;
|
|
},
|
|
|
|
root.newRateLimiter = function () {
|
|
return {
|
|
count: 0,
|
|
lastTime: 0,
|
|
throttle: function (opts) {
|
|
if (typeof opts === "undefined")
|
|
opts = {};
|
|
|
|
var burst = +opts.burst,
|
|
sustained = +opts.sustained,
|
|
cooldown = +opts.cooldown;
|
|
|
|
if (isNaN(burst))
|
|
burst = 10;
|
|
|
|
if (isNaN(sustained))
|
|
sustained = 2;
|
|
|
|
if (isNaN(cooldown))
|
|
cooldown = burst / sustained;
|
|
|
|
// Cooled down, allow and clear buffer
|
|
if (this.lastTime < Date.now() - cooldown*1000) {
|
|
this.count = 1;
|
|
this.lastTime = Date.now();
|
|
return false;
|
|
}
|
|
|
|
// Haven't reached burst cap yet, allow
|
|
if (this.count < burst) {
|
|
this.count++;
|
|
this.lastTime = Date.now();
|
|
return false;
|
|
}
|
|
|
|
var diff = Date.now() - this.lastTime;
|
|
if (diff < 1000/sustained)
|
|
return true;
|
|
|
|
this.lastTime = Date.now();
|
|
return false;
|
|
}
|
|
};
|
|
},
|
|
|
|
root.formatLink = function (id, type) {
|
|
switch (type) {
|
|
case "yt":
|
|
return "https://youtu.be/" + id;
|
|
case "vi":
|
|
return "https://vimeo.com/" + id;
|
|
case "dm":
|
|
return "https://dailymotion.com/video/" + id;
|
|
case "sc":
|
|
return id;
|
|
case "li":
|
|
return "https://livestream.com/" + id;
|
|
case "tw":
|
|
return "https://twitch.tv/" + id;
|
|
case "rt":
|
|
return id;
|
|
case "im":
|
|
return "https://imgur.com/a/" + id;
|
|
case "us":
|
|
return "https://ustream.tv/channel/" + id;
|
|
case "gd":
|
|
return "https://docs.google.com/file/d/" + id;
|
|
case "fi":
|
|
return id;
|
|
case "hb":
|
|
return "https://www.smashcast.tv/" + id;
|
|
case "hl":
|
|
return id;
|
|
case "sb":
|
|
return "https://streamable.com/" + id;
|
|
case "tc":
|
|
return "https://clips.twitch.tv/" + id;
|
|
case "cm":
|
|
return id;
|
|
default:
|
|
return "";
|
|
}
|
|
},
|
|
|
|
root.isLive = function (type) {
|
|
switch (type) {
|
|
case "li":
|
|
case "tw":
|
|
case "us":
|
|
case "rt":
|
|
case "cu":
|
|
case "im":
|
|
case "hb":
|
|
case "hl":
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
},
|
|
|
|
root.sha1 = function (data) {
|
|
if (!crypto) {
|
|
return "";
|
|
}
|
|
var shasum = crypto.createHash("sha1");
|
|
shasum.update(data);
|
|
return shasum.digest("hex");
|
|
},
|
|
|
|
root.cloakIP = function (ip) {
|
|
if (ip.match(/\d+\.\d+(\.\d+)?(\.\d+)?/)) {
|
|
return cloakIPv4(ip);
|
|
} else if (ip.match(/([0-9a-f]{1,4}:){1,7}[0-9a-f]{1,4}/)) {
|
|
return cloakIPv6(ip);
|
|
} else {
|
|
return ip;
|
|
}
|
|
|
|
function iphash(data, len) {
|
|
var md5 = crypto.createHash("md5");
|
|
md5.update(data);
|
|
return md5.digest("base64").substring(0, len);
|
|
}
|
|
|
|
function cloakIPv4(ip) {
|
|
var parts = ip.split(".");
|
|
var accumulator = "";
|
|
|
|
parts = parts.map(function (segment, i) {
|
|
var part = iphash(accumulator + segment + i, 3);
|
|
accumulator += segment;
|
|
return part;
|
|
});
|
|
|
|
while (parts.length < 4) parts.push("*");
|
|
return parts.join(".");
|
|
}
|
|
|
|
function cloakIPv6(ip) {
|
|
var parts = ip.split(":");
|
|
parts.splice(4, 4);
|
|
var accumulator = "";
|
|
|
|
parts = parts.map(function (segment, i) {
|
|
var part = iphash(accumulator + segment + i, 4);
|
|
accumulator += segment;
|
|
return part;
|
|
});
|
|
|
|
while (parts.length < 4) parts.push("*");
|
|
return parts.join(":");
|
|
}
|
|
};
|
|
})();
|