//! TODO: There is like no error checking in queries at all import type { Response, Request } from "express"; import "dotenv/config"; import dayjs from "dayjs"; import relativeTime from "dayjs/plugin/relativeTime.js"; import express from "express"; import bodyParser from "body-parser"; import session from "express-session"; import connectPgSimple from "connect-pg-simple"; import flash from "connect-flash"; import { drizzle } from "drizzle-orm/node-postgres"; import { follows, profiles, updates, users } from "./db/schema.js"; import { and, desc, eq } from "drizzle-orm"; // routes import loginRoutes from "./routes/login.js"; import userRoutes from "./routes/users.js"; import { getMoods, render } from "./routes/util.js"; const db = drizzle(process.env.DATABASE_URL!); //! TODO: Make sure SQL queries arent being repeated too much (async () => { const { moods, moodsSorted } = await getMoods(); // setup dayjs dayjs.extend(relativeTime); // setup express app const app = express(); app.set("view engine", "pug"); app.use(express.static("static")); app.use(bodyParser.urlencoded({ extended: false })); app.use( session({ store: new (connectPgSimple(session))(), secret: process.env.COOKIE_SECRET, resave: false, cookie: { maxAge: 7 * 24 * 60 * 60 * 1000 } }) ); app.use(flash()); app.get("/", async (req, res) => { const upd = db .selectDistinctOn([updates.user], { date: updates.date, user: users.name }) .from(updates) .innerJoin(users, eq(updates.user, users.id)) .orderBy(updates.user, desc(updates.date)) .limit(25) .as("upd"); const recentUpdates = await db.select().from(upd).orderBy(desc(upd.date)); render(db, "index", "Home", res, req, { users: (await db.select().from(users)).length, recentUpdates }); }); await userRoutes(app, db); //! -- TEMP DASHBOARD START -- app.get("/dashboard", async (req, res) => { if (!req.session["loggedIn"]) { res.redirect("/login"); return; } const user = ( await db .select({ name: users.name, bio: profiles.bio, website: profiles.website //! validate this }) .from(users) .where(eq(users.name, req.session["user"])) .leftJoin(profiles, eq(users.id, profiles.user)) )[0]; const now = dayjs(); const moodHistory = ( await db .select({ mood: updates.mood, date: updates.date }) .from(updates) .where(eq(updates.user, req.session["uid"])) .orderBy(desc(updates.date)) .limit(10) ).map((e) => { return { mood: moods[e.mood], date: now.to(dayjs(e.date)) }; }); const recentUpdates = ( await db .select({ user: users.name, mood: updates.mood, desc: updates.description, date: updates.date }) .from(updates) .innerJoin( follows, and( eq(follows.userId, updates.user), eq(follows.followerId, req.session["uid"]) ) ) .leftJoin(users, eq(updates.user, users.id)) .orderBy(desc(updates.date)) .limit(25) ).map((e) => { return { user: e.user, mood: moods[e.mood], desc: e.desc, date: dayjs().to(dayjs(e.date)) }; }); render(db, "dashboard", "Dashboard", res, req, { user, moods, moodsSorted, moodHistory, recentUpdates, feed: [] }); }); app.post("/update", async (req, res) => { if (!req.session["loggedIn"]) { res.redirect("/login"); return; } const moodIndex = moods.indexOf(req.body.mood.trim()); if (moodIndex === -1) { req.flash( "error", "That mood doesn't exist in the database, WTF are you trying to do??" ); res.redirect("/dashboard"); return; } if (req.body.desc.length > 512) { req.flash( "error", "Mood description can't be longer than 512 characters" ); res.redirect("/dashboard"); } await db .insert(updates) // @ts-expect-error .values({ user: req.session["uid"], mood: moodIndex, description: req.body.desc, date: new Date(Date.now()) }); req.flash("success", "Mood updated!"); res.redirect("/dashboard"); }); //! -- TEMP DASHBOARD END -- //! TEMP Also not sanitized like at all //! Also make sure user isnt logged in before doing this loginRoutes(app, db); //! TEMP done app.listen(1337, () => { console.log("Listening on http://127.0.0.1:1337/"); }); })();