add messages

This commit is contained in:
biglyderv 2024-11-04 04:21:47 -05:00
parent c029d47157
commit 175975ceeb
11 changed files with 220 additions and 10 deletions

25
client/messages.js Normal file
View file

@ -0,0 +1,25 @@
import Route from "../route.js";
import auth from "../form/auth.js";
import initDb from "../db.js";
let db = await initDb();
let main = new Route([auth], async function (req, res, input) {
let { username } = input;
let msgs = await db.all('SELECT * FROM message WHERE username = ? ORDER BY date DESC', [
username
]);
await db.run('UPDATE message SET read = ? WHERE username = ?', [
'true',
username
]);
return res.render('messages', {
...input,
msgs
});
});
export default main;

2
db.js
View file

@ -22,6 +22,8 @@ async function initDb() {
await db.run(`CREATE TABLE IF NOT EXISTS user (username TEXT, bio TEXT);`); await db.run(`CREATE TABLE IF NOT EXISTS user (username TEXT, bio TEXT);`);
await db.run(`CREATE TABLE IF NOT EXISTS captcha (key TEXT, solution TEXT);`); await db.run(`CREATE TABLE IF NOT EXISTS captcha (key TEXT, solution TEXT);`);
await db.run(`CREATE TABLE IF NOT EXISTS message (username TEXT, targetType TEXT, targetId TEXT, date REAL, content TEXT, read TEXT);`);
return db; return db;
} }

View file

@ -4,8 +4,8 @@ import initDb from "../db.js";
let db = await initDb(); let db = await initDb();
let main = new Route([], async function (req, res, input) { let main = new Route([], async function (req, res, input) {
let {route} = req.params; let { route } = req.params;
let {id} = req.query; let { id } = req.query;
let body = { ...req.cookies, ...req.body }; let body = { ...req.cookies, ...req.body };
@ -21,13 +21,25 @@ let main = new Route([], async function (req, res, input) {
username username
]); ]);
let isRead = false;
if (username) {
let msgs = await db.all('SELECT * FROM message WHERE username = ? AND read = ?', [
username,
'false'
]);
isRead = msgs.length > 0
}
return { return {
username, username,
valid: valid[0] ? valid[0].valid : 'noexist', valid: valid[0] ? valid[0].valid : 'noexist',
url: `${process.env.URL}/client/${route}?id=${id || ''}`, url: `${process.env.URL}/client/${route}?id=${id || ''}`,
icon: `${process.env.URL}/static/img/logo.png`, icon: `${process.env.URL}/static/img/logo.png`,
rootUrl: process.env.URL, rootUrl: process.env.URL,
ogType: 'website' ogType: 'website',
isRead: isRead ? 'unread' : 'read'
}; };
}); });

View file

@ -23,7 +23,20 @@ let main = new Route([auth], async function (req, res, input) {
id id
]); ]);
res.send({ 'message': 'Comment sent', redirect: `/client/${targetType}?id=${targetId}` }); let u = `/client/${targetType}?id=${targetId}`;
if (targetType == 'user') {
await db.run('INSERT INTO message (username, targetType, targetId, date, content, read) VALUES (?,?,?,?,?,?)', [
targetId,
'profile comment',
u,
+new Date(),
content,
'false'
]);
}
res.send({ 'message': 'Comment sent', redirect: u });
}); });
export default main; export default main;

View file

@ -8,6 +8,7 @@ import settings from "./client/settings.js";
import e404 from "./client/e404.js"; import e404 from "./client/e404.js";
import tou from "./client/tou.js"; import tou from "./client/tou.js";
import captcha from './client/captcha.js'; import captcha from './client/captcha.js';
import messages from './client/messages.js';
import loginB from "./form/login.js"; import loginB from "./form/login.js";
import registerB from "./form/register.js"; import registerB from "./form/register.js";
@ -35,7 +36,8 @@ routes.client = {
settings, settings,
e404, e404,
tou, tou,
captcha captcha,
messages
} }
routes.get = { routes.get = {

59
static/img/read.svg Normal file
View file

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="217.18312"
height="217.18312"
viewBox="0 0 217.18312 217.18313"
version="1.1"
id="svg1"
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
sodipodi:docname="read.svg"
inkscape:export-filename="logo.png"
inkscape:export-xdpi="452.63"
inkscape:export-ydpi="452.63"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#000000"
bordercolor="#ffffff"
borderopacity="0.24705882"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="2"
inkscape:cx="112.5"
inkscape:cy="86.25"
inkscape:window-width="1918"
inkscape:window-height="1056"
inkscape:window-x="0"
inkscape:window-y="22"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
showgrid="false" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(47.661312,-32.274754)">
<rect
style="fill:#e64e4e;fill-opacity:1;stroke:#ffffff;stroke-width:15;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect6"
width="202.18312"
height="202.18312"
x="-40.161308"
y="39.774757" />
<path
style="fill:#ef8f8f;fill-opacity:1;stroke:#ffffff;stroke-width:25;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
d="M -32.66127,47.774754 61.186505,133.77475 157.83862,44.274754 Z"
id="path2"
sodipodi:nodetypes="cccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2 KiB

65
static/img/unread.svg Normal file
View file

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="217.18312"
height="217.18312"
viewBox="0 0 217.18312 217.18313"
version="1.1"
id="svg1"
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
sodipodi:docname="unread.svg"
inkscape:export-filename="logo.png"
inkscape:export-xdpi="452.63"
inkscape:export-ydpi="452.63"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#000000"
bordercolor="#ffffff"
borderopacity="0.24705882"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="2"
inkscape:cx="112.5"
inkscape:cy="86.75"
inkscape:window-width="1290"
inkscape:window-height="1056"
inkscape:window-x="0"
inkscape:window-y="22"
inkscape:window-maximized="1"
inkscape:current-layer="layer1"
showgrid="false" />
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(47.661312,-32.274754)">
<rect
style="fill:#e64e4e;fill-opacity:1;stroke:#ffffff;stroke-width:15;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
id="rect6"
width="202.18312"
height="202.18312"
x="-40.161308"
y="39.774757" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:25;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
d="m 41.430323,72.560616 h 38.99996 L 57.9053,159.62856 Z"
id="path1" />
<ellipse
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:25;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
id="path2"
cx="58.301094"
cy="198.05249"
rx="10.735944"
ry="11.119534" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -72,20 +72,29 @@ body {
.header-link, .header-link,
.link { .link {
text-decoration: none;
font-weight: 700; font-weight: 700;
color: var(--white) color: var(--white)
} }
.header-link { .header-link {
text-decoration: none;
padding-left: .5em; padding-left: .5em;
margin-left: .5em; margin-left: .5em;
border-left: solid var(--white) 2px border-left: solid var(--white) 2px;
}
.header>a {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 1.5em;
} }
.header-img { .header-img {
height: 2em; height: 1.5em;
width: 2em; width: 1.5em;
object-fit: cover object-fit: cover
} }

View file

@ -16,7 +16,9 @@ async function formClick(ev) {
let json = await fetched.json(); let json = await fetched.json();
target.querySelector('.captcha').src += '&a=b'; let c = target.querySelector('.captcha');
if (c) c.src += '&a=b';
target.querySelector('.form-message').textContent = json.message; target.querySelector('.form-message').textContent = json.message;

View file

@ -12,5 +12,8 @@
<a class="header-link" href="/client/settings"> <a class="header-link" href="/client/settings">
Settings Settings
</a> </a>
<a class="header-link" href="/client/messages">
<img class="header-img" src="/static/img/<%= isRead %>.svg">
</a>
<% } %> <% } %>
</div> </div>

18
views/messages.ejs Normal file
View file

@ -0,0 +1,18 @@
<%- include('header.ejs') -%>
<div class="content">
<h1>Messages</h1>
<% for (let message of msgs) { %>
<div class='comment'>
<div><b>
<%= (new Date(message.date)+'').split(/(GMT|UTC)/g)[0] %>
</b></div>
<p>A <a class='link' href='<%= message.targetId %>'>
<%= message.targetType %>
</a> was sent</p>
<div class='comment'>
<pre><%= message.content %></pre>
</div>
</div>
<% } %>
</div>
<%- include('footer.ejs') -%>