diff --git a/src/extensions/chat/index.ts b/src/extensions/chat/index.ts index bf0dafa..d14f182 100644 --- a/src/extensions/chat/index.ts +++ b/src/extensions/chat/index.ts @@ -1,50 +1,56 @@ -import { ExtensionBase } from "../../modules.ts" +import { ExtensionBase, Knex } from "../../modules.ts" +import { unpack } from "../../util.ts" -type message = {user: {name: any, pfp_code: any}, time: any, content: any} +type message = {name: any, pfp_code: any, created_at: any, content: any} export default class extends ExtensionBase { override name = 'chat' override title = 'Chat' + override tables = true private MessageStore = class { - messages: message[] = [{ - user: {name:'SYSTEM',pfp_code:'seed=SYSTEM'}, - time:(new Date()).toLocaleTimeString('en-US', {hour12: false}), - content: 'Welcome to the chatroom!' - }] onPushListeners: Set<(msg: message) => void> = new Set() - push(ctx: Context, content: string) { + async push(ctx: Context, content: string, knex : Knex){ const message: message = { - user: { - name: ctx.context.user?.name, - pfp_code: `${ctx.context.dicebear_host}?${ctx.context.user?.pfp_code}`, - }, - time: (new Date()).toLocaleTimeString('en-US', {hour12: false}), + name: ctx.context.user?.name, + pfp_code: `${ctx.context.dicebear_host}?${ctx.context.user?.pfp_code}`, + created_at: (new Date()).toLocaleTimeString('en-US', {hour12: false}), content, } - this.messages.push(message) + let userID = Number(ctx.context.user?.id) + await knex.query('_message') + // @ts-expect-error + .insert({user_id: userID, created_at: message.created_at, content: message.content}) + this.onPushListeners.forEach((listener) => listener(message)) } } message_store = new this.MessageStore() - override handle: Extension['handle'] = (ctx) => { + override handle: Extension['handle'] = async (ctx) => { const location = ctx.path.shift() + let [knex]: [Knex] = this.get_dependencies('Knex') switch (location) { case '': case undefined: { if (ctx.data && ctx.data.form.message) { const message = ctx.data.form.message.substring(0,255) - this.message_store.push(ctx, message) + this.message_store.push(ctx, message, knex) } - ctx.context.chat = this.message_store.messages return this.return_html(ctx, 'index') } case 'history': { // Should at some point return history by request - return this.return_data(ctx, JSON.stringify({messages: this.message_store.messages})) + + let [message_list, err] = await knex + .query('_message') + .select('_message.created_at', '_message.content', 'user.name', 'user.pfp_code') + .join('user', '_message.user_id', '=', 'user.id') + .then(unpack) + + return this.return_data(ctx, JSON.stringify({messages: message_list})) } case 'new_message_event': { const {req, res} = ctx diff --git a/src/extensions/chat/static/chat.js b/src/extensions/chat/static/chat.js index 6d87125..0898ad3 100644 --- a/src/extensions/chat/static/chat.js +++ b/src/extensions/chat/static/chat.js @@ -31,11 +31,11 @@ function addMessage(msg) { } const row = messages.insertRow(-1) const img_col = row.insertCell(-1) - img_col.innerHTML = '' + img_col.innerHTML = '' const col = row.insertCell(-1) const info_col = col.appendChild(document.createElement('div')) - info_col.appendChild(field(msg.user.name)) - info_col.appendChild(field(msg.time)) + info_col.appendChild(field(msg.name)) + info_col.appendChild(field(msg.created_at)) const msg_col = col.appendChild(document.createElement('div')) msg_col.appendChild(field(msg.content)) } diff --git a/src/extensions/chat/tables.ts b/src/extensions/chat/tables.ts new file mode 100644 index 0000000..6d39123 --- /dev/null +++ b/src/extensions/chat/tables.ts @@ -0,0 +1,27 @@ +import { MigrationMap, Tables, VersionMap } from '../../classes/tables.ts' +import { Knex } from '../../modules.ts' + +export default class extends Tables { + override versions(versions: VersionMap) { + versions.set('message', 0) + + return versions + } + + override migrations(knex: Knex, migrations: MigrationMap) { + migrations.set('message', { + 0: async ()=>{ + await knex.schema() + .createTable('_message', (table) => { + table.increments('id').primary() + table.integer('user_id').notNullable() + table.foreign('user_id', 'fk_user_id').references('_root_user.id') + table.timestamp('created_at').notNullable().defaultTo(knex.raw('CURRENT_TIMESTAMP')) + table.string('content').notNullable() + }) + }, + }) + + return migrations + } +} diff --git a/src/extensions/invite/index.html b/src/extensions/invite/index.html new file mode 100644 index 0000000..017474f --- /dev/null +++ b/src/extensions/invite/index.html @@ -0,0 +1,30 @@ +{% extends "extension.html" %} + +{% block head %} + +{% endblock %} + + +{% block body %} + + + + + + + + + + + {% for link in invite_links %} + + + + + + + {% endfor %} + +
IDLinkCreated atUsed
{{link.id}}{{link.link}}{{link.created_at}}{{"Yes" if link.used else "No"}}
+Create Invite +{% endblock %} diff --git a/src/extensions/invite/index.ts b/src/extensions/invite/index.ts new file mode 100644 index 0000000..ba576d3 --- /dev/null +++ b/src/extensions/invite/index.ts @@ -0,0 +1,52 @@ +import { ExtensionBase, Knex } from '../../modules.ts' +import { unpack } from '../../util.ts' + +export default class extends ExtensionBase { + override name = 'invite' + override title = 'Invite' + override tables = true + override admin_only = true + + invite_URL = 'http://127.0.0.1:8000/invite/register/' + + override handle: Extension['handle'] = async (ctx) => { + let [knex]: [Knex] = this.get_dependencies('Knex') + var location = ctx.path.shift() + + switch (location) { + case '': + case undefined:{ + + var [invite_links, err] = await knex + .query('_invite') + .select('*') + .then(unpack) + + ctx.context.invite_links = invite_links + return this.return_html(ctx, 'index') + } + case 'create': + + const chars = 'abcdefghijklmnopqrstuvwxyz0123456789' + let random_chars = 'r' + for (let i = 0; i < 8; i++) { + random_chars += chars.charAt(Math.floor(Math.random() * chars.length)); + } + + let invite_link = this.invite_URL + random_chars + Date.now(); + const time = new Date().toLocaleTimeString('en-US', {hour12: false}); + + await knex.query('_invite') + // @ts-expect-error + .insert({link: invite_link, created_at: new Date().toLocaleTimeString('en-US', {hour12: false})}) + + ctx.context.invite_links = invite_links + + return this.return(ctx, undefined, location='/invite') + default: { + return this.return_file(ctx, location) + } + } + + } +} diff --git a/src/extensions/invite/static/index.css b/src/extensions/invite/static/index.css new file mode 100644 index 0000000..ee2f0db --- /dev/null +++ b/src/extensions/invite/static/index.css @@ -0,0 +1,17 @@ + +table { + margin: 2%; + padding-bottom: 5%; + text-align: center; +} + +table th, td{ + border: 1px solid; + padding: 10px; +} + +.used{ + color: #a5a5a5; + font-style: italic; + font-weight: lighter; +} diff --git a/src/extensions/invite/tables.ts b/src/extensions/invite/tables.ts new file mode 100644 index 0000000..ac25d49 --- /dev/null +++ b/src/extensions/invite/tables.ts @@ -0,0 +1,26 @@ +import { MigrationMap, Tables, VersionMap } from '../../classes/tables.ts' +import { Knex } from '../../modules.ts' + +export default class extends Tables { + override versions(versions: VersionMap) { + versions.set('invite', 0) + + return versions + } + + override migrations(knex: Knex, migrations: MigrationMap) { + migrations.set('invite', { + 0: async ()=>{ + await knex.schema() + .createTable('_invite', (table) => { + table.increments('id').primary() + table.string('link').notNullable() + table.timestamp('created_at').notNullable().defaultTo(knex.raw('CURRENT_TIMESTAMP')) + table.boolean('used').notNullable().defaultTo(false) + }) + }, + }) + + return migrations + } +}