summaryrefslogtreecommitdiff
path: root/static/js/pichat.butt.js
diff options
context:
space:
mode:
authoryo momma <shutup@oops.wtf>2026-01-30 09:52:51 +0000
committeryo momma <shutup@oops.wtf>2026-01-30 09:52:51 +0000
commit5bcf2586305bb9f246497558f46f2fa15f686364 (patch)
treeb08e56aebc4f1b27dda222f8f46e7c3f3d8d780d /static/js/pichat.butt.js
parent5aea6f7791d9a5238581b04d2198205c90495baf (diff)
Fix: restore hotlinks + cache-bust pichat.js
Diffstat (limited to 'static/js/pichat.butt.js')
-rwxr-xr-xstatic/js/pichat.butt.js104
1 files changed, 85 insertions, 19 deletions
diff --git a/static/js/pichat.butt.js b/static/js/pichat.butt.js
index 220e873..f0baae5 100755
--- a/static/js/pichat.butt.js
+++ b/static/js/pichat.butt.js
@@ -65,18 +65,68 @@ function normalizeUrl(url) {
}
URLRegex = /((\b(http\:\/\/|https\:\/\/|ftp\:\/\/)|(www\.))+(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi;
-PicRegex = /\.(jpg|jpeg|png|gif|bmp)$/i;
+PicRegex = /\.(jpg|jpeg|png|gif|bmp|svg|webp|fid)$/i;
+VideoRegex = /\.(mp4|webm|mov|m4v|gifv)$/i;
+
+function splitTrailingPunctuation(url) {
+ if (!url) return { "url": url, "suffix": "" };
+ var match = url.match(/[)\]\}\.,!\?;:'"]+$/);
+ if (!match) return { "url": url, "suffix": "" };
+ return { "url": url.slice(0, -match[0].length), "suffix": match[0] };
+}
+
+function imgurIdFromUri(uri) {
+ var host = parseDomain(uri.host || "");
+ if (!host || !host.match(/(^|\\.)imgur\\.com$/i)) return null;
+ if (!uri.file) return null;
+
+ var fileLower = uri.file.toLowerCase();
+ if (PicRegex.test(fileLower) || VideoRegex.test(fileLower)) return null;
+
+ if (!uri.file.match(/^[A-Za-z0-9]+$/)) return null;
+ return uri.file;
+}
+
+function imgurCandidateUrls(id) {
+ var base = "https://i.imgur.com/" + id;
+ return [base + ".jpg", base + ".png", base + ".gif", base + ".jpeg"];
+}
+
+function imgurHotlinkFallback(img) {
+ try {
+ var candidates = (img.getAttribute("data-imgur-candidates") || "").split("|");
+ if (!candidates.length || !candidates[0]) return;
+
+ var idx = parseInt(img.getAttribute("data-imgur-idx") || "0", 10);
+ var next = idx + 1;
+ if (next >= candidates.length) {
+ var link = img.parentNode;
+ if (link && link.tagName == "A") {
+ var href = link.getAttribute("href") || "";
+ while (link.firstChild) link.removeChild(link.firstChild);
+ link.appendChild(document.createTextNode(href));
+ }
+ return;
+ }
+
+ img.setAttribute("data-imgur-idx", "" + next);
+ img.src = candidates[next];
+ } catch (e) {}
+}
function getImagesAsArray(text) {
var imgs = []
var urls = text.match(URLRegex)
if (urls === null) return imgs
for (var i = 0; i<urls.length; i++){
- var url = urls[i]
- var normalized = normalizeUrl(url);
- var urlWithoutParams = normalized.replace(/[?#].*$/i, "");
- if (PicRegex.test(urlWithoutParams))
- imgs.push(normalized)
+ var split = splitTrailingPunctuation(urls[i]);
+ var normalized = normalizeUrl(split.url);
+ var uri = parseUri(normalized);
+ var imgurId = imgurIdFromUri(uri);
+ var candidate = imgurId ? imgurCandidateUrls(imgurId)[0] : normalized;
+
+ var urlWithoutParams = candidate.replace(/[?#].*$/i, "");
+ if (PicRegex.test(urlWithoutParams)) imgs.push(candidate)
}
return imgs
}
@@ -89,22 +139,35 @@ function linkify(text) {
// durty hack to use a global to check this... but otherwise i'd have to rewrite the String.replace function? :/
var LastMsgContainsImage = false
function linkReplace(url) {
- //var urlWithoutParams = url.replace(/\?.*$/i, "");
-
- linkUrl = normalizeUrl(url);
-
- var uri = parseUri(url)
+ var split = splitTrailingPunctuation(url);
+ linkUrl = normalizeUrl(split.url);
+ var uri = parseUri(linkUrl);
+
+ var imgurId = imgurIdFromUri(uri);
+ if (imgurId) {
+ LastMsgContainsImage = true;
+ var candidates = imgurCandidateUrls(imgurId);
+ var first = candidates[0];
+ return "<a target=\"_blank\" href=\"" + linkUrl + "\">"
+ + "<img src=\"" + first + "\" class=\"imgur-hotlink\" data-imgur-idx=\"0\" data-imgur-candidates=\"" + candidates.join('|') + "\" onerror=\"imgurHotlinkFallback(this)\">"
+ + "</a>" + split.suffix;
+ }
+
switch(getUriType(uri)) {
case 'image':
LastMsgContainsImage = true;
- return "<a target='_blank' href='" + linkUrl + "'><img src='" + linkUrl + "'></a>"; break;
- case 'youtube':
+ return "<a target='_blank' href='" + linkUrl + "'><img src='" + linkUrl + "'></a>" + split.suffix;
+ case 'video':
+ LastMsgContainsImage = true;
+ var videoUrl = linkUrl.replace(/\.gifv([?#].*)?$/i, '.mp4$1');
+ return "<a target=\"_blank\" href=\"" + linkUrl + "\"><video src=\"" + videoUrl + "\" autoplay loop muted controls playsinline></video></a>" + split.suffix;
+ case 'youtube':
Youtube.startAnimation();
- return "<a target='_blank' class='youtube' href='" + linkUrl + "'>" +
- "<img class='youtube-thumb' width='130' height='97' src='"+Youtube.nextThumbUrl(uri.queryKey.v)+"'>" +
- "<img class='youtube-controls' src='/static/img/youtube.controls.png'></a>"; break;
+ return "<a target=\"_blank\" class=\"youtube\" href=\"" + linkUrl + "\">" +
+ "<img class=\"youtube-thumb\" width=\"130\" height=\"97\" src=\"" + Youtube.nextThumbUrl(uri.queryKey.v) + "\">" +
+ "<img class=\"youtube-controls\" src=\"/static/img/youtube.controls.png\"></a>" + split.suffix;
default:
- return "<a target='_blank' href='" + linkUrl + "'>" + url + "</a>";
+ return "<a target=\"_blank\" href=\"" + linkUrl + "\">" + split.url + "</a>" + split.suffix;
}
}
@@ -130,7 +193,7 @@ Youtube = {
var img = $(this);
// yt thumb url example: https://i.ytimg.com/vi/0123456789A/1.jpg
var src = img.attr("src") || ""
- var match = src.match(/\\/vi\\/([^/]{11})\\/(\\d)\\.jpg/i)
+ var match = src.match(/\/vi\/([^/]{11})\/(\d)\.jpg/i)
if (!match) return
var v = match[1]
var num = match[2]
@@ -149,8 +212,11 @@ Youtube = {
function getUriType(uri){
if (PicRegex.test(uri.file.toLowerCase()))
return "image";
+
+ if (VideoRegex.test(uri.file.toLowerCase()))
+ return "video";
- if (parseDomain(uri.host) == "youtube.com" && 'v' in uri.queryKey || uri.anchor.indexOf('v') != -1)
+ if (parseDomain(uri.host) == "youtube.com" && ('v' in uri.queryKey || uri.anchor.indexOf('v') != -1))
return "youtube";
return "link";