import { query, mutation } from "./_generated/server"; import { v } from "convex/values"; import { getRolesForUser } from "./roles"; import { getPublicStorageUrl } from "./storageUrl"; export const list = query({ args: {}, returns: v.any(), handler: async (ctx) => { const emojis = await ctx.db.query("customEmojis").collect(); const results = await Promise.all( emojis.map(async (emoji) => { const src = await getPublicStorageUrl(ctx, emoji.storageId); const user = await ctx.db.get(emoji.uploadedBy); return { _id: emoji._id, name: emoji.name, src, createdAt: emoji.createdAt, uploadedByUsername: user?.username || "Unknown", }; }) ); return results.filter((e) => e.src !== null); }, }); export const upload = mutation({ args: { userId: v.id("userProfiles"), name: v.string(), storageId: v.id("_storage"), }, returns: v.null(), handler: async (ctx, args) => { // Permission check const roles = await getRolesForUser(ctx, args.userId); const canManage = roles.some( (role) => (role.permissions as Record)?.["manage_channels"] ); if (!canManage) { throw new Error("You don't have permission to manage emojis"); } // Validate name format const name = args.name.trim(); if (!/^[a-zA-Z0-9_]+$/.test(name)) { throw new Error("Emoji name can only contain letters, numbers, and underscores"); } if (name.length < 2 || name.length > 32) { throw new Error("Emoji name must be between 2 and 32 characters"); } // Check for duplicate name among custom emojis const existing = await ctx.db .query("customEmojis") .withIndex("by_name", (q) => q.eq("name", name)) .first(); if (existing) { throw new Error(`A custom emoji named "${name}" already exists`); } await ctx.db.insert("customEmojis", { name, storageId: args.storageId, uploadedBy: args.userId, createdAt: Date.now(), }); return null; }, }); export const remove = mutation({ args: { userId: v.id("userProfiles"), emojiId: v.id("customEmojis"), }, returns: v.null(), handler: async (ctx, args) => { // Permission check const roles = await getRolesForUser(ctx, args.userId); const canManage = roles.some( (role) => (role.permissions as Record)?.["manage_channels"] ); if (!canManage) { throw new Error("You don't have permission to manage emojis"); } const emoji = await ctx.db.get(args.emojiId); if (!emoji) throw new Error("Emoji not found"); await ctx.storage.delete(emoji.storageId); await ctx.db.delete(args.emojiId); return null; }, });