diff --git a/public/s/js/comments.js b/public/s/js/comments.js index 05241d9..89875b0 100644 --- a/public/s/js/comments.js +++ b/public/s/js/comments.js @@ -105,7 +105,7 @@ class CommentSystem { try { // Decode Base64 for safe template transfer const raw = dataEl.textContent.trim(); - const json = atob(raw); + const json = new TextDecoder().decode(Uint8Array.from(atob(raw), c => c.charCodeAt(0))); const comments = JSON.parse(json); const subEl = document.getElementById('initial-subscription'); diff --git a/src/inc/routes/comments.mjs b/src/inc/routes/comments.mjs index 9012414..95b9fe2 100644 --- a/src/inc/routes/comments.mjs +++ b/src/inc/routes/comments.mjs @@ -13,7 +13,7 @@ export default (router, tpl) => { // Require login if (!req.session) { return res.reply({ - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json; charset=utf-8' }, body: JSON.stringify({ success: true, comments: [], @@ -39,7 +39,7 @@ export default (router, tpl) => { // Transform for frontend if needed, or send as is return res.reply({ - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json; charset=utf-8' }, body: JSON.stringify({ success: true, comments, @@ -84,7 +84,7 @@ export default (router, tpl) => { if (!req.session || !req.session.user) { if (isJson) { return res.reply({ - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json; charset=utf-8' }, body: JSON.stringify({ success: false, require_login: true }) }); } else { @@ -132,7 +132,7 @@ export default (router, tpl) => { if (isJson) { return res.reply({ - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json; charset=utf-8' }, body: JSON.stringify({ success: true, comments: processedComments }) }); } @@ -201,13 +201,10 @@ export default (router, tpl) => { const mentionedNames = [...new Set(matches.map(m => m[1]))]; const lowerNames = mentionedNames.map(n => n.toLowerCase()); - console.log("DEBUG: Mentions found:", mentionedNames); - let mentionedUsers = []; if (lowerNames.length > 0) { // Fetch IDs via login column (lowercase) mentionedUsers = await db`SELECT id, user FROM "user" WHERE login IN ${db(lowerNames)}`; - console.log("DEBUG: Users resolved:", mentionedUsers); } // 2. Get parent author @@ -263,7 +260,7 @@ export default (router, tpl) => { } return res.reply({ - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json; charset=utf-8' }, body: JSON.stringify({ success: true, comment: newComment[0] }) }); } catch (err) { @@ -295,7 +292,7 @@ export default (router, tpl) => { } return res.reply({ - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json; charset=utf-8' }, body: JSON.stringify({ success: true, subscribed }) }); } catch (e) { @@ -319,7 +316,7 @@ export default (router, tpl) => { await db`UPDATE comments SET is_deleted = true, content = '[deleted]' WHERE id = ${commentId}`; return res.reply({ - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json; charset=utf-8' }, body: JSON.stringify({ success: true }) }); } catch (e) { @@ -347,7 +344,7 @@ export default (router, tpl) => { await db`UPDATE comments SET content = ${content}, updated_at = NOW() WHERE id = ${commentId}`; return res.reply({ - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json; charset=utf-8' }, body: JSON.stringify({ success: true }) }); } catch (e) { @@ -370,7 +367,7 @@ export default (router, tpl) => { await db`UPDATE comments SET is_pinned = ${newPinned} WHERE id = ${commentId}`; return res.reply({ - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json; charset=utf-8' }, body: JSON.stringify({ success: true, is_pinned: newPinned }) }); } catch (e) { @@ -393,7 +390,7 @@ export default (router, tpl) => { await db`UPDATE items SET is_comments_locked = ${newLocked} WHERE id = ${itemId}`; return res.reply({ - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json; charset=utf-8' }, body: JSON.stringify({ success: true, is_locked: newLocked }) }); } catch (e) { diff --git a/src/inc/routes/notifications.mjs b/src/inc/routes/notifications.mjs index 3175270..d61d882 100644 --- a/src/inc/routes/notifications.mjs +++ b/src/inc/routes/notifications.mjs @@ -20,7 +20,7 @@ export default (router, tpl) => { `; return res.reply({ - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json; charset=utf-8' }, body: JSON.stringify({ success: true, notifications }) }); } catch (err) { @@ -36,7 +36,7 @@ export default (router, tpl) => { try { await db`UPDATE notifications SET is_read = true WHERE user_id = ${req.session.id}`; return res.reply({ - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json; charset=utf-8' }, body: JSON.stringify({ success: true }) }); } catch (err) { @@ -51,7 +51,7 @@ export default (router, tpl) => { try { await db`UPDATE notifications SET is_read = true WHERE id = ${id} AND user_id = ${req.session.id}`; return res.reply({ - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json; charset=utf-8' }, body: JSON.stringify({ success: true }) }); } catch (err) {