All checks were successful
Build and Release / build-and-release (push) Successful in 10m4s
99 lines
2.7 KiB
TypeScript
99 lines
2.7 KiB
TypeScript
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<string, boolean>)?.["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<string, boolean>)?.["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;
|
|
},
|
|
});
|