var is_iphone =
navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPod/i);
var is_ipad = navigator.userAgent.match(/iPad/i);
var is_android = navigator.userAgent.match(/Android/i);
var is_mobile = is_iphone || is_ipad || is_android;
var is_desktop = !is_mobile;
document.body.classList.add(is_desktop ? "desktop" : "mobile");
const AUDIO_REGEXP = /\.(mp3|wav|aif|aiff|ogg|opus|flac)$/i;
const IMAGE_REGEXP = /\.(gif|jpg|jpeg|png)$/i;
const CONTAINS_IMAGE_URL_REGEXP = /http\S+\.(gif|jpe?g|png)/i;
function choice(a) {
return a[randint(a.length)];
}
function csrf() {
return $("[name=_csrf]").attr("value");
}
function bold_terms(s, terms) {
s = sanitizeHTML(s);
terms.forEach((term) => {
s = s.replace(new RegExp(term, "ig"), "" + term + "");
});
return s;
}
function querystring(opt) {
return (
"?" +
Object.keys(opt)
.map((key) => {
return encodeURIComponent(key) + "=" + encodeURIComponent(opt[key]);
})
.join("&")
);
}
function commatize(n, radix) {
radix = radix || 1000;
var nums = [],
i,
counter = 0,
r = Math.floor;
if (radix !== -1 && n > radix) {
n /= radix;
nums.unshift(r((n * 10) % 10));
nums.unshift(".");
}
do {
i = r(n % 10);
n = r(n / 10);
counter += 1;
if (n && !(counter % 3)) {
i = " " + r(i);
}
nums.unshift(i);
} while (n);
return nums.join("");
}
function privacy_dot(p) {
if (!p) return "·";
else return ".:";
}
var short_months = "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" ");
function verbose_date(date, no_pad_hours) {
var date = new Date(date * 1000);
var d = date.getDate();
var m = date.getMinutes();
var h = date.getHours();
var meridian;
if (h == 0) {
h = 12;
meridian = " am";
} else if (h == 12) {
meridian = " pm";
} else if (h > 12) {
h -= 12;
meridian = " pm";
} else {
meridian = " am";
}
if (d < 10) d = "0" + d;
if (m < 10) m = "0" + m;
if (!no_pad_hours && h < 10) h = "0" + h;
// non-breaking hyphen: ‑
var date =
d +
" " +
short_months[date.getMonth()] +
" " +
date.getFullYear();
var time = h + ":" + m + meridian;
return [date, time];
}
function carbon_date(date, no_bold) {
var span = +new Date() / 1000 - date;
if (!no_bold && span < 86400) {
// modified today
color = "new";
} else if (span < 604800) {
// modifed this week
color = "recent";
} else if (span < 1209600) {
// modifed 2 weeks ago
color = "med";
} else if (span < 3024000) {
// modifed 5 weeks ago
color = "old";
} else if (span < 12315200) {
// modifed 6 months ago
color = "older";
} else {
color = "quiet";
}
return color;
}
function hush_views(n, bias, no_bold) {
var txt = commatize(n, 1000);
bias = bias || 1;
n = n || 0;
if (n < 30) {
return ["quiet", n + " v."];
}
if (n < 200) {
return ["quiet", txt + " v."];
} else if (n < 500) {
return ["old", txt + " v."];
} else if (n < 1000) {
return ["med", txt + " v."];
} else if (n < 5000) {
return ["recent", txt + " kv."];
} else if (no_bold || n < 10000) {
return ["recent", txt + " kv."];
} else {
return ["new", txt + " kv."];
}
}
function hush_threads(n, bias, no_bold) {
var txt = commatize(n, -1);
bias = bias || 1;
n = n || 0;
if (n < 10) {
return ["quiet", n + " t."];
} else if (n < 25) {
return ["old", txt + " t."];
} else if (n < 50) {
return ["med", txt + " t."];
} else if (no_bold || n < 100) {
return ["recent", txt + " t."];
} else {
return ["new", txt + " t."];
}
}
function hush_size(n, bias, no_bold) {
var txt = commatize(Math.floor(n / 1024), 1000);
bias = 1 || bias;
n = n || 0;
if (n < 1024) {
return ["quiet", n + " b."];
}
if (n < 1000 * 1000) {
return ["quiet", txt + " kb."];
}
if (n < 20000000 / bias) {
return ["quiet", txt + " mb."];
}
if (n < 50000000 / bias) {
return ["old", txt + " mb."];
}
if (n < 80000000 / bias) {
return ["med", txt + " mb."];
}
if (no_bold || n < 170000000 / bias) {
return ["recent", txt + " mb."];
}
if (n >= 10000 * 1000 * 1000) {
console.log(n);
txt = commatize(Math.floor(n / (1024 * 1024 * 1024)));
return ["new", txt + " gb."];
}
return ["new", txt + " mb."];
}
function hush_null(n, unit, no_bold) {
n = commatize(n, -1);
var s = unit ? n + " " + unit + "." : n;
if (n < 3) {
return ["quiet", s];
} else if (n < 6) {
return ["older", s];
} else if (n < 10) {
return ["old", s];
} else if (n < 16) {
return ["med", s];
} else if (no_bold || n < 21) {
return ["recent", s];
} else {
return ["new", s];
}
}
function courtesy_s(n, s) {
return n == 1 ? "" : s || "s";
}
var revision_letters = "z a b c d f g h j k l m n p q r s t v w x y".split(" ");
function get_revision(thread) {
if (!thread.revision) return "";
var rev = thread.revision;
var n = 0;
var digits = "";
do {
n = rev % 21;
rev = Math.floor(rev / 21);
digits = revision_letters[n] + digits;
} while (rev !== 0);
return digits;
}
function get_age(t, long) {
var age = Math.abs(Date.now() / 1000 - t);
var r = Math.floor;
var m;
if (age < 5) {
return "now";
}
if (age < 60) {
return r(age) + (long ? " seconds" : "s");
}
age /= 60;
if (age < 60) {
return r(age) + (long ? " minutes" : "m");
}
m = r(age % 60);
age /= 60;
if (m > 0 && age < 2) {
return r(age) + (long ? " hours " + m + " minutes" : "h" + m + "m");
}
if (age < 24) {
return r(age) + (long ? " hours" : "h");
}
age /= 24;
if (age < 7) {
return r(age) + (long ? " days" : "d");
}
age /= 7;
if (age < 12) {
return r(age) + (long ? " weeks" : "w");
}
age /= 4;
if (age < 12) {
return r(age) + (long ? " months" : "m");
}
age /= 12;
return r(age) + (long ? " years" : "y");
}
const age_scale = [
[0, 1.0],
[60 * 10, 1.0],
[60 * 60, 0.975],
[60 * 60 * 8, 0.95],
[60 * 60 * 24, 0.925],
[60 * 60 * 24 * 7, 0.9],
[60 * 60 * 24 * 7 * 4, 0.875],
[60 * 60 * 24 * 7 * 4 * 12, 0.85],
];
function get_age_opacity(t) {
var age = Math.abs(Date.now() / 1000 - t);
return get_scale_opacity(age, age_scale);
}
const size_scale = [
[0, 0.0],
[1, 0.7],
[5, 0.8],
[10, 0.9],
[15, 0.95],
[20, 0.99],
];
function get_size_opacity(n) {
return get_scale_opacity(n, size_scale);
}
const views_scale = [
[0, 0.5],
[100, 0.8],
[1000, 0.9],
[10000, 1.0],
];
function get_views_opacity(n) {
return get_scale_opacity(n, views_scale);
}
/**
* find a value on one axis of an array of points, and return the proportional point
* @param {Array} value a value, to be matched on the first column of scale
* @param {Array} scale an array of points: (value, target)
* @return {Number} a proportional point within the closest target values
*/
function get_scale_opacity(value, scale) {
for (let i = 1; i < scale.length; i++) {
const [max_value, max_lerp] = scale[i];
if (value === max_value) {
return max_lerp;
}
if (value < max_value) {
const [min_value, min_lerp] = scale[i - 1];
return lerp(norm(value, min_value, max_value), min_lerp, max_lerp);
}
}
return scale[scale.length - 1][1];
}
function trimComment({ isViewingThread, lines, snippetSize, cropSize }) {
return function (comment) {
return isViewingThread || comment.comment.length < (cropSize || 256)
? comment
: {
...comment,
comment:
comment.comment
.split("\n")
.slice(0, lines || 5)
.join("\n")
.substr(0, snippetSize || 512)
.replace(/\s+\w+$/, "")
.replace(/<[^>]+$/, "") +
`... Read more...`,
};
};
}
function tidy_urls(s, short_urls) {
var ret = (s || "")
.split("\n")
.map(function (line) {
if (line.indexOf("<") !== -1) {
return line;
}
return line.replace(/https?:\/\/[^ ]+/g, function (url) {
if (is_image(url)) {
return (
'
'
);
} else if (short_urls) {
return (
'[' +
get_domain(url) +
"]"
);
} else {
return (
'' +
url +
""
);
}
});
})
.join("\n")
.replace(/\r/g, "")
.replace(/\n/g, "")
.replace(/<\/code>\n/g, "");
return ret;
}
function get_domain(url) {
return url
.replace(/https?:\/\//, "")
.replace(/\/.*/, "")
.replace(/www\./, "");
}
function is_image(url) {
return !!url.match(/\.(gif|jpe?g|png)(\?.*)?$/i);
}
function make_link(file) {
if (file.storage) {
return (
"//s3.amazonaws.com/" +
file.storage +
sdk.opt.s3.path +
"/data/" +
file.thread +
"/" +
encodeURIComponent(file.filename)
);
}
if (file.filename.indexOf("http") !== 0) {
return "/data/" + file.thread + "/" + encodeURIComponent(file.filename);
}
return file.filename;
}
function profile_image(username) {
return "//s3.amazonaws.com/i.asdf.us/bucky/profile/" + username + ".jpg";
}
function make_thumb(file) {
if (file.storage) {
return (
"//s3.amazonaws.com/" +
file.storage +
sdk.opt.s3.path +
"/data/" +
file.thread +
"/" +
encodeURIComponent(file.filename)
);
}
if (file.filename.indexOf("http") !== 0) {
return "/data/" + file.thread + "/" + file.filename;
}
return "/data/" + file.thread + "/" + file.filename;
// var partz = file.filename.toLowerCase().split("/")
// return partz.splice(partz.length-2, 0, ".thumb").join("/")
}
var metadataTemplate = $(".metadata_template").html();
function metadata(thread) {
var datetime = verbose_date(thread.createdate, true);
var age = get_age(thread.lastmodified, true);
var t = metadataTemplate
.replace(/{{username}}/g, thread.username)
.replace(/{{date}}/g, datetime[0])
.replace(/{{time}}/g, datetime[1])
.replace(/{{active}}/g, age + " ago")
.replace(/{{views}}/g, thread.viewed + " view" + courtesy_s(thread.viewed));
return t;
}