Initial Commit

This commit is contained in:
2026-10-03 20:07:49 +02:00
commit a1346c98b1
427 changed files with 59320 additions and 0 deletions
+34
View File
@@ -0,0 +1,34 @@
import { unlink } from 'node:fs/promises'
import { join } from 'node:path'
import { eq, sql } from 'drizzle-orm'
import { commentAttachments, comments, uploads } from '../../db/schema'
export default defineEventHandler(async (event) => {
await requirePermission(event, 'comment.delete')
const id = Number(getRouterParam(event, 'id'))
if (!Number.isInteger(id) || id <= 0) {
throw createError({ statusCode: 400, statusMessage: 'Ungültige ID' })
}
const db = useDb()
const comment = await db
.select({ uploadId: comments.uploadId })
.from(comments)
.where(eq(comments.id, id))
.limit(1)
.then(r => r[0])
const files = await db
.select({ fileName: commentAttachments.fileName, cover: commentAttachments.cover })
.from(commentAttachments)
.where(eq(commentAttachments.commentId, id))
await db.delete(comments).where(eq(comments.id, id))
if (comment) {
await db.update(uploads).set({ commentCount: sql`GREATEST(comment_count - 1, 0)` }).where(eq(uploads.id, comment.uploadId))
}
for (const f of files) {
await unlink(join(uploadDir(), 'attachments', f.fileName)).catch(() => {})
if (f.cover) {
await unlink(join(process.cwd(), 'public', f.cover)).catch(() => {})
}
}
return { ok: true }
})
@@ -0,0 +1,69 @@
import { and, eq, sql } from 'drizzle-orm'
import { z } from 'zod'
import { commentReactions, comments } from '../../../db/schema'
const bodySchema = z.object({
emoji: z.string().min(1).max(32),
})
export default defineEventHandler(async (event) => {
const user = await requireUser(event)
const id = Number(getRouterParam(event, 'id'))
if (!Number.isInteger(id) || id <= 0) {
throw createError({ statusCode: 400, statusMessage: 'Ungültige ID' })
}
const { emoji } = await readValidatedBody(event, bodySchema.parse)
const db = useDb()
const [comment] = await db
.select({ id: comments.id, uploadId: comments.uploadId })
.from(comments)
.where(eq(comments.id, id))
.limit(1)
if (!comment) {
throw createError({ statusCode: 404, statusMessage: 'Kommentar nicht gefunden' })
}
const existing = await db
.select({ userId: commentReactions.userId })
.from(commentReactions)
.where(and(
eq(commentReactions.commentId, id),
eq(commentReactions.userId, user.id),
eq(commentReactions.emoji, emoji),
))
.limit(1)
let active: boolean
if (existing.length) {
await db.delete(commentReactions).where(and(
eq(commentReactions.commentId, id),
eq(commentReactions.userId, user.id),
eq(commentReactions.emoji, emoji),
))
active = false
}
else {
await db.insert(commentReactions).values({ commentId: id, userId: user.id, emoji })
active = true
}
const [{ total }] = await db
.select({ total: sql<number>`count(*)` })
.from(commentReactions)
.where(and(eq(commentReactions.commentId, id), eq(commentReactions.emoji, emoji)))
const count = Number(total)
broadcastToAll({
type: 'reaction',
commentId: id,
uploadId: comment.uploadId,
emoji,
actorId: user.id,
actorName: user.name,
active,
count,
})
return { active, count }
})
+47
View File
@@ -0,0 +1,47 @@
import { asc, desc, eq, inArray } from 'drizzle-orm'
import { commentAttachments, comments, uploads, users } from '../../db/schema'
import type { CommentAttachment } from '~~/shared/utils/attachments'
export default defineEventHandler(async () => {
const db = useDb()
const rows = await db
.select({
id: comments.id,
content: comments.content,
createdAt: comments.createdAt,
userName: users.name,
userId: users.id,
userColor: users.color,
userAvatar: users.avatar,
uploadId: uploads.id,
})
.from(comments)
.innerJoin(users, eq(comments.userId, users.id))
.innerJoin(uploads, eq(comments.uploadId, uploads.id))
.orderBy(desc(comments.createdAt))
.limit(15)
const commentIds = rows.map(r => r.id)
const attachmentRows = commentIds.length
? await db
.select()
.from(commentAttachments)
.where(inArray(commentAttachments.commentId, commentIds))
.orderBy(asc(commentAttachments.id))
: []
const attachmentsByComment = new Map<number, CommentAttachment[]>()
for (const a of attachmentRows) {
let list = attachmentsByComment.get(a.commentId)
if (!list) {
list = []
attachmentsByComment.set(a.commentId, list)
}
list.push({ id: a.id, name: a.originalName, url: `/uploads/attachments/${a.fileName}`, mimeType: a.mimeType, size: a.size, cover: a.cover, meta: a.meta as CommentAttachment['meta'] })
}
return rows.map(r => ({
...r,
userAvatarUrl: avatarUrl(r.userAvatar),
attachments: attachmentsByComment.get(r.id) ?? [],
}))
})