From 03303b16d7053b19cb342c6798519ba152779f71 Mon Sep 17 00:00:00 2001 From: Miikka Lahtinen Date: Tue, 19 Oct 2021 21:09:23 +0300 Subject: [PATCH 01/10] Initial support for image command --- docker/node/modules/auth/actions.js | 1 + docker/node/modules/auth/service.js | 1 + docker/node/server.js | 31 +++++++++++++++++++++++++++++ web/css/layout-other.css | 4 ++++ web/js/functions.js | 6 ++++++ 5 files changed, 43 insertions(+) diff --git a/docker/node/modules/auth/actions.js b/docker/node/modules/auth/actions.js index f8f7791e..8e61ff84 100644 --- a/docker/node/modules/auth/actions.js +++ b/docker/node/modules/auth/actions.js @@ -29,4 +29,5 @@ exports.actions = { CAN_SEE_OBSCURED_POLLS: "canSeeObscuredPolls", CAN_SEE_PRIVILEGED_USER_DATA: "canSeePrivilegedUserData", CAN_SEE_SHADOWBANS: "canSeeShadowbans", + ACTION_POST_IMAGE: "postImage", }; diff --git a/docker/node/modules/auth/service.js b/docker/node/modules/auth/service.js index b2e3a271..f04f1fbc 100644 --- a/docker/node/modules/auth/service.js +++ b/docker/node/modules/auth/service.js @@ -35,6 +35,7 @@ exports.AuthService = class extends ServiceBase { [actions.CAN_SEE_PRIVILEGED_USER_DATA]: isMod, [actions.CAN_SEE_SHADOWBANS]: isMod, [actions.ACTION_CAN_RESET_PASSWORD]: isAdmin, + [actions.ACTION_POST_IMAGE]: isMod, }; function isBerry({ isBerry }) { diff --git a/docker/node/server.js b/docker/node/server.js index 31d47bce..0ffdbce2 100644 --- a/docker/node/server.js +++ b/docker/node/server.js @@ -1069,6 +1069,37 @@ const chatCommandMap = { ); } }), + ...withAliases(["img", "image"], (parsed, socket, messageData) => { + if (!authService.can(socket.session, actions.ACTION_SHITPOST)) { + kickForIllegalActivity(socket); + return doSuppressChat; + } + + let format = parsed.msg.trim().split('.').pop(); + const supportedFormats = new Set([ + 'png', + 'jpg', + 'jpeg', + 'gif', + 'svg', + 'webp', + 'avif' + ]); + + //not a valid picture + if (format === '') { + return doSuppressChat; + } + + //image source not supported, don't show an attempt + if (!supportedFormats.has(format)) { + return doSuppressChat; + } + + messageData.emote = 'image'; + + return doNormalChatMessage; + }), }; function _sendChat(nick, type, incoming, socket) { diff --git a/web/css/layout-other.css b/web/css/layout-other.css index 36799e79..bc4bd5b9 100644 --- a/web/css/layout-other.css +++ b/web/css/layout-other.css @@ -1031,3 +1031,7 @@ button.ranked-poll__submit-button { .super-select__option:hover { filter: none; } + +#chatbuffer .image > img { + height: 120px; +} \ No newline at end of file diff --git a/web/js/functions.js b/web/js/functions.js index da055e11..08af1f8d 100644 --- a/web/js/functions.js +++ b/web/js/functions.js @@ -1363,6 +1363,12 @@ function addChatMsg(data, _to) { newmsg.addClass("server").appendTo(msgwrap); $("").appendTo(newmsg).html(msgText); break; + case "image": + console.warn(data); + newmsg.addClass('image').append( + $('', {src: msgText}) + ).appendTo(msgwrap); + break; default: dbg("Unknown message type, emote=" + data.msg.emote); return; From 0d2de8877d2b01afe955838ea34b327eb596d77e Mon Sep 17 00:00:00 2001 From: Miikka Lahtinen Date: Tue, 19 Oct 2021 21:11:34 +0300 Subject: [PATCH 02/10] Remove console.warn --- web/js/functions.js | 1 - 1 file changed, 1 deletion(-) diff --git a/web/js/functions.js b/web/js/functions.js index 08af1f8d..c5b2a55b 100644 --- a/web/js/functions.js +++ b/web/js/functions.js @@ -1364,7 +1364,6 @@ function addChatMsg(data, _to) { $("").appendTo(newmsg).html(msgText); break; case "image": - console.warn(data); newmsg.addClass('image').append( $('', {src: msgText}) ).appendTo(msgwrap); From adb05c1b99baf6f4b25387d6e56d18cf5966e180 Mon Sep 17 00:00:00 2001 From: Miikka Lahtinen Date: Tue, 19 Oct 2021 21:12:48 +0300 Subject: [PATCH 03/10] Change to const --- docker/node/server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/node/server.js b/docker/node/server.js index 0ffdbce2..364f677b 100644 --- a/docker/node/server.js +++ b/docker/node/server.js @@ -1075,7 +1075,7 @@ const chatCommandMap = { return doSuppressChat; } - let format = parsed.msg.trim().split('.').pop(); + const format = parsed.msg.trim().split('.').pop(); const supportedFormats = new Set([ 'png', 'jpg', From 3df598204b5f015e84bb356a28b389bf41520199 Mon Sep 17 00:00:00 2001 From: Miikka Lahtinen Date: Tue, 19 Oct 2021 21:20:36 +0300 Subject: [PATCH 04/10] Use correct action --- docker/node/server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/node/server.js b/docker/node/server.js index 364f677b..8c780649 100644 --- a/docker/node/server.js +++ b/docker/node/server.js @@ -1070,7 +1070,7 @@ const chatCommandMap = { } }), ...withAliases(["img", "image"], (parsed, socket, messageData) => { - if (!authService.can(socket.session, actions.ACTION_SHITPOST)) { + if (!authService.can(socket.session, actions.ACTION_POST_IMAGE)) { kickForIllegalActivity(socket); return doSuppressChat; } From 0a74258b5b461bc95488755e0013eb2e28988546 Mon Sep 17 00:00:00 2001 From: Miikka Lahtinen Date: Wed, 20 Oct 2021 09:10:08 +0300 Subject: [PATCH 05/10] Use pre-existing css rules, and add extra info to element --- web/css/layout-other.css | 7 ++----- web/js/functions.js | 6 +++++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/web/css/layout-other.css b/web/css/layout-other.css index bc4bd5b9..8a3492ae 100644 --- a/web/css/layout-other.css +++ b/web/css/layout-other.css @@ -664,7 +664,8 @@ body { } /* mod-embedded images */ -.img-filter > img { +#chatbuffer .img-filter > img, +#chatbuffer .image > img { max-height: 150px; max-width: 100%; } @@ -1031,7 +1032,3 @@ button.ranked-poll__submit-button { .super-select__option:hover { filter: none; } - -#chatbuffer .image > img { - height: 120px; -} \ No newline at end of file diff --git a/web/js/functions.js b/web/js/functions.js index c5b2a55b..b8ba18a9 100644 --- a/web/js/functions.js +++ b/web/js/functions.js @@ -1365,7 +1365,11 @@ function addChatMsg(data, _to) { break; case "image": newmsg.addClass('image').append( - $('', {src: msgText}) + $('', { + src: msgText, + referrerpolicy: "no-referrer", + alt: 'Loading image...', + }) ).appendTo(msgwrap); break; default: From c292c8f5489b99dc4c37a7191752772aa8836b88 Mon Sep 17 00:00:00 2001 From: Miikka Lahtinen Date: Wed, 20 Oct 2021 09:13:54 +0300 Subject: [PATCH 06/10] Wrap the image in clickable link --- web/js/functions.js | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/web/js/functions.js b/web/js/functions.js index b8ba18a9..e3b9e18d 100644 --- a/web/js/functions.js +++ b/web/js/functions.js @@ -1364,12 +1364,21 @@ function addChatMsg(data, _to) { $("").appendTo(newmsg).html(msgText); break; case "image": - newmsg.addClass('image').append( - $('', { - src: msgText, - referrerpolicy: "no-referrer", - alt: 'Loading image...', - }) + const linkAttrs = { + href: msgText, + class: 'image', + target: '_blank', + rel: 'noopener noreferrer' + }; + + newmsg.append( + $('', linkAttrs).append( + $('', { + src: msgText, + referrerpolicy: "no-referrer", + alt: 'Loading image...', + }) + ) ).appendTo(msgwrap); break; default: From 74efc7b86a5f7cde1f0051f70819a6dbfdac4c6b Mon Sep 17 00:00:00 2001 From: Miikka Lahtinen Date: Sat, 23 Oct 2021 13:48:00 +0300 Subject: [PATCH 07/10] Handle urls with query params --- docker/node/server.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docker/node/server.js b/docker/node/server.js index 8c780649..e1dfbe1d 100644 --- a/docker/node/server.js +++ b/docker/node/server.js @@ -1075,7 +1075,12 @@ const chatCommandMap = { return doSuppressChat; } - const format = parsed.msg.trim().split('.').pop(); + let format = parsed.msg.trim().split('.').pop(); + + if (format.includes('?')) { + format = format.split('?')[0]; + } + const supportedFormats = new Set([ 'png', 'jpg', From c3f6b65009c922349011475e62c5ec7b6e238c5b Mon Sep 17 00:00:00 2001 From: Miikka Lahtinen Date: Sat, 23 Oct 2021 13:58:15 +0300 Subject: [PATCH 08/10] Add nick --- web/js/functions.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/web/js/functions.js b/web/js/functions.js index e3b9e18d..3d7966a5 100644 --- a/web/js/functions.js +++ b/web/js/functions.js @@ -1371,7 +1371,8 @@ function addChatMsg(data, _to) { rel: 'noopener noreferrer' }; - newmsg.append( + newmsg.addClass("message").append( + $('', {class: `nick ${nick}`, text: `${nick}:`}), $('', linkAttrs).append( $('', { src: msgText, @@ -1380,6 +1381,8 @@ function addChatMsg(data, _to) { }) ) ).appendTo(msgwrap); + + includeTimestamp = true; break; default: dbg("Unknown message type, emote=" + data.msg.emote); From d3ce58e88b31444fe703006c77d3d91b01f5295d Mon Sep 17 00:00:00 2001 From: Miikka Lahtinen Date: Fri, 5 Nov 2021 18:26:23 +0200 Subject: [PATCH 09/10] Change nick to attr --- web/js/functions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/js/functions.js b/web/js/functions.js index 3d7966a5..d13b25d5 100644 --- a/web/js/functions.js +++ b/web/js/functions.js @@ -1372,7 +1372,7 @@ function addChatMsg(data, _to) { }; newmsg.addClass("message").append( - $('', {class: `nick ${nick}`, text: `${nick}:`}), + $('', {class: `nick`, nick, text: `${nick}:`}), $('', linkAttrs).append( $('', { src: msgText, From 12906467df40a137aed30faad9dcad3483367de8 Mon Sep 17 00:00:00 2001 From: Miikka Lahtinen Date: Sat, 13 Nov 2021 20:06:41 +0200 Subject: [PATCH 10/10] Add possibility for video elements, and scroll buffers on load --- docker/node/server.js | 40 ++++++++++++++++++++++++---------------- web/css/layout-other.css | 3 ++- web/js/functions.js | 20 ++++++++++++++++++++ 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/docker/node/server.js b/docker/node/server.js index e1dfbe1d..68101aa4 100644 --- a/docker/node/server.js +++ b/docker/node/server.js @@ -1069,7 +1069,7 @@ const chatCommandMap = { ); } }), - ...withAliases(["img", "image"], (parsed, socket, messageData) => { + ...withAliases(["img", "image", "video", "media"], (parsed, socket, messageData) => { if (!authService.can(socket.session, actions.ACTION_POST_IMAGE)) { kickForIllegalActivity(socket); return doSuppressChat; @@ -1081,27 +1081,35 @@ const chatCommandMap = { format = format.split('?')[0]; } - const supportedFormats = new Set([ - 'png', - 'jpg', - 'jpeg', - 'gif', - 'svg', - 'webp', - 'avif' - ]); + const supportedFormats = new Map([ + //images + ['png', {kind: 'image'}], + ['jpg', {kind: 'image'}], + ['jpeg', {kind: 'image'}], + ['gif', {kind: 'image'}], + ['svg', {kind: 'image'}], + ['webp', {kind: 'image'}], + ['avif', {kind: 'image'}], - //not a valid picture - if (format === '') { + //videos + ['mp4', {kind: 'video'}], + ['webm', {kind: 'video'}], + ['gifv', {kind: 'video', real: 'mp4'}] + ]) + + + //couldn't get file extension or media not supported, don't show an attempt + if (format === '' || !supportedFormats.has(format)) { return doSuppressChat; } - //image source not supported, don't show an attempt - if (!supportedFormats.has(format)) { - return doSuppressChat; + const info = supportedFormats.get(format); + + if (info.real) { + messageData.msg = parsed.msg.replace(`.${format}`, `.${info.real}`); } - messageData.emote = 'image'; + messageData.emote = info.kind; return doNormalChatMessage; }), diff --git a/web/css/layout-other.css b/web/css/layout-other.css index 8a3492ae..3a634272 100644 --- a/web/css/layout-other.css +++ b/web/css/layout-other.css @@ -665,7 +665,8 @@ body { /* mod-embedded images */ #chatbuffer .img-filter > img, -#chatbuffer .image > img { +#chatbuffer .image > img, +#chatbuffer video { max-height: 150px; max-width: 100%; } diff --git a/web/js/functions.js b/web/js/functions.js index d13b25d5..fb2e22be 100644 --- a/web/js/functions.js +++ b/web/js/functions.js @@ -1378,12 +1378,32 @@ function addChatMsg(data, _to) { src: msgText, referrerpolicy: "no-referrer", alt: 'Loading image...', + onload: "scrollBuffersToBottom()" }) ) ).appendTo(msgwrap); includeTimestamp = true; break; + case "video": { + const attributes = { + autoplay: '', + loop: '', + muted: '', + src: msgText, + referrerpolicy: 'noreferrer', + alt: 'Loading video...', + onload: "scrollBuffersToBottom()" + }; + + newmsg.addClass("message").append( + $('', {class: `nick`, nick, text: `${nick}:`}), + $('