From 2a9869ca7dadc910bfa944c1d853f6d45afc1e4e Mon Sep 17 00:00:00 2001
From: bytedream <bytedream@protonmail.com>
Date: Thu, 21 Dec 2023 15:02:29 +0100
Subject: [PATCH] change strike layout and add outlawed option

---
 src/lib/server/database.ts          | 23 ++++--------
 src/routes/admin/reports/+server.ts | 57 ++---------------------------
 src/routes/api/user/+server.ts      | 37 ++++++++++++++++---
 3 files changed, 43 insertions(+), 74 deletions(-)

diff --git a/src/lib/server/database.ts b/src/lib/server/database.ts
index c923a34..bcb58e7 100644
--- a/src/lib/server/database.ts
+++ b/src/lib/server/database.ts
@@ -74,6 +74,9 @@ export class Report extends Model {
 	declare auditor: Admin;
 	@BelongsTo(() => StrikeReason, 'strike_reason_id')
 	declare strike_reason: StrikeReason;
+
+	@Column({ type: DataTypes.DATE })
+	declare striked_at: Date | null;
 }
 
 @Table({ modelName: 'strike_reason', underscored: true, createdAt: false, updatedAt: false })
@@ -88,22 +91,10 @@ export class StrikeReason extends Model {
 export class StrikePunishment extends Model {
 	@Column({ type: DataTypes.INTEGER, allowNull: false })
 	declare weight: number;
+	@Column({ type: DataTypes.ENUM('ban', 'outlawed'), allowNull: false })
+	declare type: 'ban' | 'outlawed';
 	@Column({ type: DataTypes.INTEGER, allowNull: false })
-	declare ban_in_seconds: number;
-}
-
-@Table({ modelName: 'strike', underscored: true })
-export class Strike extends Model {
-	@Column({ type: DataTypes.INTEGER, allowNull: false, defaultValue: 0 })
-	declare weight: number;
-	@Column({ type: DataTypes.DATE, allowNull: false, defaultValue: 0 })
-	declare ban_until: Date;
-	@Column({ type: DataTypes.INTEGER, allowNull: false })
-	@ForeignKey(() => User)
-	declare user_id: number;
-
-	@BelongsTo(() => User, 'user_id')
-	declare user: User;
+	declare punishment_in_seconds: number;
 }
 
 @Table({ modelName: 'admin', underscored: true })
@@ -157,5 +148,5 @@ export class Settings extends Model {
 export const sequelize = new Sequelize(building ? 'sqlite::memory:' : env.DATABASE_URI, {
 	// only log sql queries in dev mode
 	logging: dev ? console.log : false,
-	models: [User, Report, StrikeReason, StrikePunishment, Strike, Admin, Settings]
+	models: [User, Report, StrikeReason, StrikePunishment, Admin, Settings]
 });
diff --git a/src/routes/admin/reports/+server.ts b/src/routes/admin/reports/+server.ts
index 09fdf4d..75c669b 100644
--- a/src/routes/admin/reports/+server.ts
+++ b/src/routes/admin/reports/+server.ts
@@ -1,7 +1,7 @@
 import type { RequestHandler } from '@sveltejs/kit';
 import { getSession } from '$lib/server/session';
 import { Permissions } from '$lib/permissions';
-import { Admin, Report, Strike, StrikePunishment, StrikeReason, User } from '$lib/server/database';
+import { Admin, Report, StrikeReason, User } from '$lib/server/database';
 import type { Attributes } from 'sequelize';
 import { Op } from 'sequelize';
 import { env } from '$env/dynamic/private';
@@ -127,63 +127,14 @@ export const PATCH = (async ({ request, cookies }) => {
 				if (strike_reason == null) return new Response(null, { status: 400 });
 				report.strike_reason_id = strike_reason.id;
 			}
-		} else if (data.strike_reason == -1) {
-			const strike = await Strike.findOne({ where: { user_id: report.reported_id } });
-			if (strike != null && report.strike_reason_id != null) {
-				const strike_weight = (await StrikeReason.findByPk(report.strike_reason_id, {
-					attributes: ['weight']
-				}))!.weight;
-				const current_ban_in_seconds = (
-					await StrikePunishment.findOne({
-						attributes: ['ban_in_seconds'],
-						where: { weight: { [Op.lte]: strike.weight } }
-					})
-				)?.ban_in_seconds;
-				if (current_ban_in_seconds) {
-					const new_ban_in_seconds = (
-						await StrikePunishment.findOne({
-							attributes: ['ban_in_seconds'],
-							where: { weight: { [Op.lte]: strike.weight - strike_weight } }
-						})
-					)?.ban_in_seconds;
-					const time_left =
-						strike.ban_until.getTime() / 1000 - current_ban_in_seconds + (new_ban_in_seconds || 0);
-					strike.ban_until = new Date(time_left * 1000);
-				}
-				strike.weight -= strike_weight;
-				await strike.save();
-				report.strike_reason_id = null;
-			}
+		} else if (data.strike_reason == -1 && report.strike_reason_id != null) {
+			report.strike_reason_id = null;
 		} else if (data.strike_reason != report.strike_reason_id) {
 			if (!report.reported_id) return new Response(null, { status: 400 });
 			const strike_reason = await StrikeReason.findByPk(data.strike_reason);
 			if (strike_reason == null) return new Response(null, { status: 400 });
-			const [strike] = await Strike.findOrCreate({ where: { user_id: report.reported_id } });
-			const old_punishment = (
-				await StrikePunishment.findOne({
-					attributes: ['ban_in_seconds'],
-					where: { weight: { [Op.lte]: strike.weight } }
-				})
-			)?.ban_in_seconds;
-			if (report.strike_reason_id) {
-				strike.weight -=
-					(await StrikeReason.findByPk(report.strike_reason_id, { attributes: ['weight'] }))
-						?.weight || 0;
-			}
-			strike.weight += (await StrikeReason.findByPk(strike_reason.id, {
-				attributes: ['weight']
-			}))!.weight;
-			const new_punishment = (
-				await StrikePunishment.findOne({
-					attributes: ['ban_in_seconds'],
-					where: { weight: { [Op.lte]: strike.weight } }
-				})
-			)?.ban_in_seconds;
-			if (old_punishment != new_punishment && new_punishment != null) {
-				strike.ban_until = new Date(Date.now() + new_punishment / 1000);
-			}
-			await strike.save();
 			report.strike_reason_id = strike_reason.id;
+			report.striked_at = new Date(Date.now());
 		}
 	}
 	if (admin != null) report.auditor_id = admin.id;
diff --git a/src/routes/api/user/+server.ts b/src/routes/api/user/+server.ts
index ba9c475..98f737d 100644
--- a/src/routes/api/user/+server.ts
+++ b/src/routes/api/user/+server.ts
@@ -1,6 +1,7 @@
 import type { RequestHandler } from '@sveltejs/kit';
-import { Strike, User } from '$lib/server/database';
+import { Report, sequelize, StrikePunishment, StrikeReason, User } from '$lib/server/database';
 import { env } from '$env/dynamic/private';
+import { Op } from 'sequelize';
 
 export const GET = (async ({ url }) => {
 	if (env.REPORT_SECRET && url.searchParams.get('secret') !== env.REPORT_SECRET)
@@ -12,7 +13,28 @@ export const GET = (async ({ url }) => {
 	const user = await User.findOne({ where: { uuid: uuid } });
 	if (user == null) return new Response(null, { status: 400 });
 
-	const strike = await Strike.findOne({ where: { user_id: user.id } });
+	const query = (await Report.findOne({
+		where: { reported_id: user.id },
+		attributes: [
+			[sequelize.fn('SUM', sequelize.col('strike_reason.weight')), 'weight'],
+			'striked_at'
+		],
+		include: { model: StrikeReason, as: 'strike_reason' }
+	})) as { dataValues: { weight: number; striked_at: Date } } | null;
+	const ban_time = (
+		await StrikePunishment.findOne({
+			attributes: ['punishment_in_seconds'],
+			where: { type: ['ban'], weight: { [Op.lte]: query?.dataValues.weight } },
+			order: [['weight', 'DESC']]
+		})
+	)?.punishment_in_seconds;
+	const outlawed_time = (
+		await StrikePunishment.findOne({
+			attributes: ['punishment_in_seconds'],
+			where: { type: ['outlawed'], weight: { [Op.lte]: query?.dataValues.weight } },
+			order: [['weight', 'DESC']]
+		})
+	)?.punishment_in_seconds;
 
 	return new Response(
 		JSON.stringify({
@@ -20,9 +42,14 @@ export const GET = (async ({ url }) => {
 			username: user.username,
 			firstname: user.firstname,
 			lastname: user.lastname,
-			banned:
-				new Date(new Date(Date.now()).toUTCString()) <
-				new Date((strike?.ban_until ?? new Date(0)).toUTCString())
+			banned_until:
+				query && ban_time
+					? Math.round(query.dataValues.striked_at.getTime() / 1000 + ban_time!)
+					: null,
+			outlawed_until:
+				query && outlawed_time
+					? Math.round(query.dataValues.striked_at.getTime() / 1000 + outlawed_time!)
+					: null
 		}),
 		{ status: 200 }
 	);