feat : update
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { isSingleEmoji } from "./reaction";
|
||||
|
||||
describe("commission reactions", () => {
|
||||
it("accepts emoji outside the old six choices, including sequences", () => {
|
||||
for (const emoji of ["🔥", "🇹🇭", "👨👩👧👦", "1️⃣"]) expect(isSingleEmoji(emoji)).toBe(true);
|
||||
});
|
||||
|
||||
it("rejects text and multiple reactions", () => {
|
||||
for (const value of ["", "hello", "1", "🔥🔥", "🔥 hello"]) expect(isSingleEmoji(value)).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
import emojiRegex from "emoji-regex";
|
||||
|
||||
export function isSingleEmoji(value: string): boolean {
|
||||
if (!value || value.length > 64) return false;
|
||||
const matches = [...value.matchAll(emojiRegex())];
|
||||
return matches.length === 1 && matches[0][0] === value;
|
||||
}
|
||||
@@ -18,7 +18,7 @@ export async function getCommissionTicket(id: string) {
|
||||
if (!row || (user.role !== "admin" || !user.emailVerified) && row.ticket.userId !== user.id)
|
||||
throw new HttpError(404, "ticket-not-found");
|
||||
const [messages, reactions] = await Promise.all([
|
||||
getDb().select({ message: commissionMessages, authorName: users.name }).from(commissionMessages)
|
||||
getDb().select({ message: commissionMessages, authorName: users.name, authorImage: users.image }).from(commissionMessages)
|
||||
.innerJoin(users, eq(commissionMessages.authorId, users.id))
|
||||
.where(eq(commissionMessages.ticketId, id)).orderBy(asc(commissionMessages.createdAt)),
|
||||
getDb().select({ reaction: commissionReactions, messageId: commissionMessages.id })
|
||||
@@ -26,8 +26,14 @@ export async function getCommissionTicket(id: string) {
|
||||
.innerJoin(commissionMessages, eq(commissionReactions.messageId, commissionMessages.id))
|
||||
.where(eq(commissionMessages.ticketId, id)),
|
||||
]);
|
||||
return { ...row, messages: messages.map(({ message, authorName }) => ({ ...message, authorName,
|
||||
reactions: reactions.filter(({ messageId }) => messageId === message.id).map(({ reaction }) => reaction) })),
|
||||
const reactionsByMessage = new Map<string, typeof commissionReactions.$inferSelect[]>();
|
||||
for (const { reaction, messageId } of reactions) {
|
||||
const group = reactionsByMessage.get(messageId) ?? [];
|
||||
group.push(reaction);
|
||||
reactionsByMessage.set(messageId, group);
|
||||
}
|
||||
return { ...row, messages: messages.map(({ message, authorName, authorImage }) => ({ ...message, authorName,
|
||||
authorImage, reactions: reactionsByMessage.get(message.id) ?? [] })),
|
||||
currentUserId: user.id };
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export function securityHeaders(production: boolean) {
|
||||
export function securityHeaders(production: boolean, emojiImageCdn: string) {
|
||||
const ads = "https://*.googlesyndication.com https://*.doubleclick.net https://*.googleadservices.com https://*.googletagservices.com https://www.google.com";
|
||||
const cloudflareAnalytics = "https://static.cloudflareinsights.com";
|
||||
const adConnections = "https://*.adtrafficquality.google";
|
||||
@@ -6,7 +6,7 @@ export function securityHeaders(production: boolean) {
|
||||
"default-src 'self'",
|
||||
`script-src 'self' 'unsafe-inline' ${production ? "" : "'unsafe-eval'"} https://challenges.cloudflare.com ${cloudflareAnalytics} ${ads}`,
|
||||
"style-src 'self' 'unsafe-inline'",
|
||||
`img-src 'self' data: blob: https://buzz-cdn.astrxl.dev ${ads}`,
|
||||
`img-src 'self' data: blob: https://buzz-cdn.astrxl.dev ${emojiImageCdn} ${ads}`,
|
||||
"font-src 'self' data:",
|
||||
`connect-src 'self' https://buzz-cdn.astrxl.dev https://challenges.cloudflare.com ${adConnections} ${ads}${production ? "" : " ws: wss:"}`,
|
||||
`frame-src https://challenges.cloudflare.com https://www.youtube-nocookie.com ${ads}`,
|
||||
|
||||
Reference in New Issue
Block a user