From 5bcf2586305bb9f246497558f46f2fa15f686364 Mon Sep 17 00:00:00 2001 From: yo momma Date: Fri, 30 Jan 2026 09:52:51 +0000 Subject: Fix: restore hotlinks + cache-bust pichat.js --- static/js/pages/chat_init.js | 13 +++-- static/js/pichat.butt.js | 104 +++++++++++++++++++++++++++++++------- static/js/pichat.js | 106 +++++++++++++++++++++++++++++++++------ static/js/src/text.js | 104 ++++++++++++++++++++++++++++++++------ static/js/src/youtube.js | 2 +- template/frontpage copy.st | 2 +- template/frontpage.st | 2 +- template/frontpagePROFILE.st | 2 +- template/frontpage_halloffame.st | 2 +- template/fullscreen.st | 2 +- template/fullscreen4.st | 2 +- template/fullscreen5.st | 2 +- template/fullscreen_front.st | 2 +- template/fullscreenphotobooth.st | 2 +- template/head.st | 2 +- template/head_edge.st | 2 +- template/ie_fullscreen.st | 2 +- template/mgmtfull.st | 2 +- template/newlog.st | 2 +- template/rooms/fullscreen.st | 2 +- template/rooms/fullscreen2.st | 2 +- template/rooms/mgmt.st | 2 +- template/rooms/nocss.st | 2 +- template/simplerlog.st | 2 +- 24 files changed, 294 insertions(+), 73 deletions(-) diff --git a/static/js/pages/chat_init.js b/static/js/pages/chat_init.js index 58dba07..7149291 100644 --- a/static/js/pages/chat_init.js +++ b/static/js/pages/chat_init.js @@ -23,9 +23,17 @@ if (typeof window.Recips === 'undefined') { window.Recips = []; } var hasMessageList = document.getElementById('messageList') !== null; + var hasChatInput = document.getElementById('msgInput') !== null; + + if (hasMessageList && hasChatInput && typeof window.initChat === 'function') { window.initChat(); } + if (hasMessageList && hasChatInput && typeof window.initChatMsgs === 'function') { window.initChatMsgs(); } + + // Some room pages render dumps in `.logged-dump` containers without the full chat UI. + // In that case, run the log initializer so URLs become hotlinked images. + if (!hasChatInput && typeof window.initLog === 'function' && jQuery('.logged-dump .content').length) { + window.initLog(window.Recips); + } - if (hasMessageList && typeof window.initChat === 'function') { window.initChat(); } - if (hasMessageList && typeof window.initChatMsgs === 'function') { window.initChatMsgs(); } if (typeof window.Away !== 'undefined' && typeof window.Away.startTitleUpdater === 'function') { window.Away.startTitleUpdater(); } if (window.Nick && typeof window.setupUpload === 'function' && typeof window.Room !== 'undefined') { @@ -33,4 +41,3 @@ } }); })(jQuery); - 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" + + "" + + "" + split.suffix; + } + switch(getUriType(uri)) { case 'image': LastMsgContainsImage = true; - return ""; break; - case 'youtube': + return "" + split.suffix; + case 'video': + LastMsgContainsImage = true; + var videoUrl = linkUrl.replace(/\.gifv([?#].*)?$/i, '.mp4$1'); + return "" + split.suffix; + case 'youtube': Youtube.startAnimation(); - return "" + - "" + - ""; break; + return "" + + "" + + "" + split.suffix; default: - return "" + url + ""; + return "" + split.url + "" + 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"; diff --git a/static/js/pichat.js b/static/js/pichat.js index 2283baf..ad50fae 100755 --- a/static/js/pichat.js +++ b/static/js/pichat.js @@ -2114,21 +2114,74 @@ function escapeHtml(txt) { URLRegex = /((\b(http\:\/\/|https\:\/\/|ftp\:\/\/)|(www\.))+(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi; -PicRegex = /\.(jpg|jpeg|png|gif|bmp|svg|fid)$/i; +PicRegex = /\.(jpg|jpeg|png|gif|bmp|svg|webp|fid)$/i; +VideoRegex = /\.(mp4|webm|mov|m4v|gifv)$/i; RecipRegex = /(^|\s)@\w+/g; TopicRegex = /(^|\s)#\w+/g; +function splitTrailingPunctuation(url) { + if (!url) return { "url": url, "suffix": "" }; + // Common punctuation that follows pasted links in chat. + 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 = (uri.host || "").toLowerCase(); + 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). + var imgurId = imgurIdFromUri(uri); + if (imgurId) { + LastMsgContainsImage = true; + var candidates = imgurCandidateUrls(imgurId); + var first = candidates[0]; + return "" + + "" + + "" + split.suffix; + } + + linkUrl = hrefUrl; - var uri = parseUri(url) var type = getUriType(uri) if (type == 'image') { LastMsgContainsImage = true; - return ""; + return "" + split.suffix; + } else if (type == 'video') { + LastMsgContainsImage = true; + var videoUrl = linkUrl.replace(/\.gifv([?#].*)?$/i, ".mp4$1"); + return "" + split.suffix; } else if (type == 'youtube') { Youtube.startAnimation(); - return "" + - "" + - "" + return "" + + "" + + "" + split.suffix; } else if (type == 'midi') { - return ' '+uri.file+'' + return ' ' + uri.file + '' + split.suffix; } else if (type == 'wav') { - return ' '+uri.file+'' + return ' ' + uri.file + '' + split.suffix; } else - return "" + url + ""; + return "" + split.url + "" + split.suffix; } @@ -2230,6 +2301,9 @@ function linkReplace(url) { function getUriType(uri){ if (PicRegex.test(uri.file.toLowerCase())) return "image"; + + if (VideoRegex.test(uri.file.toLowerCase())) + return "video"; var domain = parseDomain(uri.host) @@ -2443,7 +2517,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] diff --git a/static/js/src/text.js b/static/js/src/text.js index 6fe5c3c..d99efbb 100755 --- a/static/js/src/text.js +++ b/static/js/src/text.js @@ -14,21 +14,74 @@ function escapeHtml(txt) { URLRegex = /((\b(http\:\/\/|https\:\/\/|ftp\:\/\/)|(www\.))+(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi; -PicRegex = /\.(jpg|jpeg|png|gif|bmp|svg|fid)$/i; +PicRegex = /\.(jpg|jpeg|png|gif|bmp|svg|webp|fid)$/i; +VideoRegex = /\.(mp4|webm|mov|m4v|gifv)$/i; RecipRegex = /(^|\s)@\w+/g; TopicRegex = /(^|\s)#\w+/g; +function splitTrailingPunctuation(url) { + if (!url) return { "url": url, "suffix": "" }; + // Common punctuation that follows pasted links in chat. + 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 = (uri.host || "").toLowerCase(); + 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). + var imgurId = imgurIdFromUri(uri); + if (imgurId) { + LastMsgContainsImage = true; + var candidates = imgurCandidateUrls(imgurId); + var first = candidates[0]; + return "" + + "" + + "" + split.suffix; + } + + linkUrl = hrefUrl; - var uri = parseUri(url) var type = getUriType(uri) if (type == 'image') { LastMsgContainsImage = true; - return ""; + return "" + split.suffix; + } else if (type == 'video') { + LastMsgContainsImage = true; + var videoUrl = linkUrl.replace(/\.gifv([?#].*)?$/i, ".mp4$1"); + return "" + split.suffix; } else if (type == 'youtube') { Youtube.startAnimation(); - return "" + - "" + - "" + return "" + + "" + + "" + split.suffix; } else if (type == 'midi') { - return ' '+uri.file+'' + return ' ' + uri.file + '' + split.suffix; } else if (type == 'wav') { - return ' '+uri.file+'' + return ' ' + uri.file + '' + split.suffix; } else - return "" + url + ""; + return "" + split.url + "" + split.suffix; } @@ -130,6 +201,9 @@ function linkReplace(url) { function getUriType(uri){ if (PicRegex.test(uri.file.toLowerCase())) return "image"; + + if (VideoRegex.test(uri.file.toLowerCase())) + return "video"; var domain = parseDomain(uri.host) diff --git a/static/js/src/youtube.js b/static/js/src/youtube.js index 2b6a977..ccb2cd4 100755 --- a/static/js/src/youtube.js +++ b/static/js/src/youtube.js @@ -19,7 +19,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] diff --git a/template/frontpage copy.st b/template/frontpage copy.st index 304446c..582f3e2 100755 --- a/template/frontpage copy.st +++ b/template/frontpage copy.st @@ -16,7 +16,7 @@ setTimeout("refreshing()",300000); - + - + - + diff --git a/template/frontpage_halloffame.st b/template/frontpage_halloffame.st index a13a396..5de88b1 100755 --- a/template/frontpage_halloffame.st +++ b/template/frontpage_halloffame.st @@ -16,7 +16,7 @@ setTimeout("refreshing()",300000); - + - + $if(user_nick)$ $else$ diff --git a/template/fullscreen4.st b/template/fullscreen4.st index 4b34243..1d1a4e6 100755 --- a/template/fullscreen4.st +++ b/template/fullscreen4.st @@ -2,7 +2,7 @@ dump.fm - fullscreen - + - + - + - + + + - + - + - + diff --git a/template/rooms/fullscreen.st b/template/rooms/fullscreen.st index 3a75db0..004684f 100755 --- a/template/rooms/fullscreen.st +++ b/template/rooms/fullscreen.st @@ -2,7 +2,7 @@ dump.fm - fullscreen - + - + - + diff --git a/template/rooms/nocss.st b/template/rooms/nocss.st index 0124d72..527a306 100755 --- a/template/rooms/nocss.st +++ b/template/rooms/nocss.st @@ -23,7 +23,7 @@ - + diff --git a/template/simplerlog.st b/template/simplerlog.st index 9c3e6c4..df9f03b 100755 --- a/template/simplerlog.st +++ b/template/simplerlog.st @@ -13,7 +13,7 @@ - + -- cgit v1.2.3-70-g09d2