feat: Get previous messages from the DB when reloading

This commit is contained in:
April Hall 2025-01-09 17:13:22 -05:00
parent 92cf5a8af2
commit 2a5f521bf1
Signed by: arithefirst
GPG Key ID: 4508A15C4DB91C5B
5 changed files with 55 additions and 10 deletions

View File

@ -16,6 +16,23 @@ async function storeMessage(client: cassandra.Client, channelName: string, conte
VALUES (${id}, '${content}', ${now.getTime()}, ${sender})`); VALUES (${id}, '${content}', ${now.getTime()}, ${sender})`);
} }
async function getMessages(client: cassandra.Client, channelName: string, limit: number) {
try {
const res = await client.execute(`SELECT * FROM channels.channel_${channelName} LIMIT ${limit}`);
// We have to sort the rows within the function instead of an ORDER BY
// because of a limitation within Cassandra requiring a partition key
// to be specified by EQ or IN when using ORDER BY
res.rows.sort((a, b) => a.timestamp - b.timestamp);
return res.rows;
} catch (e) {
// @ts-expect-error I don't like this thing yelling at me
// We all know it's gonna work
console.log(`Error fetching messages: ${e.message}`);
}
}
const client = new cassandra.Client({ const client = new cassandra.Client({
contactPoints: ['localhost'], contactPoints: ['localhost'],
localDataCenter: 'datacenter1', localDataCenter: 'datacenter1',
@ -27,4 +44,4 @@ await client.connect();
await client.execute(`CREATE KEYSPACE IF NOT EXISTS users WITH REPLICATION = {'class': 'SimpleStrategy', 'replication_factor': 1};`); await client.execute(`CREATE KEYSPACE IF NOT EXISTS users WITH REPLICATION = {'class': 'SimpleStrategy', 'replication_factor': 1};`);
await client.execute(`CREATE KEYSPACE IF NOT EXISTS channels WITH REPLICATION = {'class': 'SimpleStrategy', 'replication_factor': 1};`); await client.execute(`CREATE KEYSPACE IF NOT EXISTS channels WITH REPLICATION = {'class': 'SimpleStrategy', 'replication_factor': 1};`);
export { client, createChannel, storeMessage }; export { client, createChannel, getMessages, storeMessage };

View File

@ -16,7 +16,7 @@ export function startupSocketIOServer(httpServer: HttpServer | null) {
// Runs on message receive // Runs on message receive
socket.on('message', async (msg) => { socket.on('message', async (msg) => {
// If message not empty // If message not empty
if (msg.content !== "") { if (msg.content !== '') {
console.log(`[ws:kit] message from ${socket.id}: ${msg.content}`); console.log(`[ws:kit] message from ${socket.id}: ${msg.content}`);
// Store the message in the database // Store the message in the database
await createChannel(client, '000'); await createChannel(client, '000');

View File

@ -0,0 +1,15 @@
import type { PageLoad } from './$types';
import type { TypeMessage } from '$lib';
import { getMessages, client } from '../lib/server/db';
export const load: PageLoad = async () => {
const rows = await getMessages(client, '000', 5);
const messages: TypeMessage[] = rows
? rows.map((value) => {
return { message: value.message_content, user: value.sender.toString(), imageSrc: 'https://thispersondoesnotexist.com' };
})
: [];
return {
serverMessages: messages,
};
};

View File

@ -4,11 +4,13 @@
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import Message from '../lib/components/message.svelte'; import Message from '../lib/components/message.svelte';
import { type TypeMessage } from '../lib'; import { type TypeMessage } from '../lib';
import type { PageData } from './$types';
let { data }: { data: PageData } = $props();
let user: string | undefined; let user: string | undefined;
let socket: ReturnType<typeof io> | null = null; let socket: ReturnType<typeof io> | null = null;
let log: TypeMessage[] = []; let log: TypeMessage[] = $state([]);
let msg: string = ''; let msg: string = $state('');
function logEvent(newMsg: TypeMessage) { function logEvent(newMsg: TypeMessage) {
log = [...log, newMsg]; log = [...log, newMsg];
@ -36,18 +38,23 @@
}); });
</script> </script>
{#snippet message(messages: TypeMessage[])}
{#each messages as message}
<Message imageSrc={message.imageSrc} user={message.user} message={message.message} />
{/each}
{/snippet}
<main class="h-full flex flex-col"> <main class="h-full flex flex-col">
<div class="flex-grow flex-auto overflow-y-scroll mx-2 mt-2 mb-1 rounded-lg bg-base-200 border-2 border-primary"> <div class="flex-grow flex-auto overflow-y-scroll mx-2 mt-2 mb-1 rounded-lg bg-base-200 border-2 border-base-300">
<div class="w-full"> <div class="w-full">
<h1 class="text-center text-base-content text-2xl"><span class="text-primary">SV</span>Chat</h1> <h1 class="text-center text-base-content text-2xl"><span class="text-primary">SV</span>Chat</h1>
<hr class="w-11/12 border-primary border-1 mx-auto" /> <hr class="w-11/12 border-primary border-1 mx-auto" />
</div> </div>
{#each log as message} {@render message(data.messages)}
<Message imageSrc={message.imageSrc} user={message.user} message={message.message} /> {@render message(log)}
{/each}
</div> </div>
<form class="flex mb-2 mx-2 mt-1" on:submit={sendMessage}> <form class="flex mb-2 mx-2 mt-1" onsubmit={sendMessage}>
<input type="text" placeholder="Type here" class="input input-secondary w-3/4 mr-1 border-2" bind:value={msg} /> <input type="text" placeholder="Type here" class="input border-2 border-base-300 w-3/4 mr-1 border-2" bind:value={msg} />
<button class="btn w-1/4 btn-primary" type="submit">Send Message</button> <button class="btn w-1/4 btn-primary" type="submit">Send Message</button>
</form> </form>
</main> </main>

6
src/routes/+page.ts Normal file
View File

@ -0,0 +1,6 @@
import type { PageLoad } from './$types';
export const load: PageLoad = async ({ data }) => {
return {
messages: data.serverMessages,
};
};