|
import { collections } from "$lib/server/database"; |
|
import { type Actions, fail, redirect } from "@sveltejs/kit"; |
|
import { ObjectId } from "mongodb"; |
|
import { authCondition } from "$lib/server/auth"; |
|
import { base } from "$app/paths"; |
|
import { PUBLIC_ORIGIN, PUBLIC_SHARE_PREFIX } from "$env/static/public"; |
|
import { WEBHOOK_URL_REPORT_ASSISTANT } from "$env/static/private"; |
|
import { z } from "zod"; |
|
import type { Assistant } from "$lib/types/Assistant"; |
|
async function assistantOnlyIfAuthor(locals: App.Locals, assistantId?: string) { |
|
const assistant = await collections.assistants.findOne({ _id: new ObjectId(assistantId) }); |
|
|
|
if (!assistant) { |
|
throw Error("Assistant not found"); |
|
} |
|
|
|
if (assistant.createdById.toString() !== (locals.user?._id ?? locals.sessionId).toString()) { |
|
throw Error("You are not the author of this assistant"); |
|
} |
|
|
|
return assistant; |
|
} |
|
|
|
export const actions: Actions = { |
|
delete: async ({ params, locals }) => { |
|
let assistant; |
|
try { |
|
assistant = await assistantOnlyIfAuthor(locals, params.assistantId); |
|
} catch (e) { |
|
return fail(400, { error: true, message: (e as Error).message }); |
|
} |
|
|
|
await collections.assistants.deleteOne({ _id: assistant._id }); |
|
|
|
|
|
await collections.settings.updateMany( |
|
{ |
|
assistants: { $in: [assistant._id] }, |
|
}, |
|
{ |
|
$pull: { assistants: assistant._id }, |
|
} |
|
); |
|
|
|
|
|
const fileCursor = collections.bucket.find({ filename: assistant._id.toString() }); |
|
|
|
|
|
let fileId = await fileCursor.next(); |
|
while (fileId) { |
|
await collections.bucket.delete(fileId._id); |
|
fileId = await fileCursor.next(); |
|
} |
|
|
|
throw redirect(302, `${base}/settings`); |
|
}, |
|
report: async ({ request, params, locals, url }) => { |
|
|
|
const report = await collections.reports.findOne({ |
|
createdBy: locals.user?._id ?? locals.sessionId, |
|
assistantId: new ObjectId(params.assistantId), |
|
}); |
|
|
|
if (report) { |
|
return fail(400, { error: true, message: "Already reported" }); |
|
} |
|
|
|
const formData = await request.formData(); |
|
const result = z.string().min(1).max(128).safeParse(formData?.get("reportReason")); |
|
|
|
if (!result.success) { |
|
return fail(400, { error: true, message: "Invalid report reason" }); |
|
} |
|
|
|
const { acknowledged } = await collections.reports.insertOne({ |
|
_id: new ObjectId(), |
|
assistantId: new ObjectId(params.assistantId), |
|
createdBy: locals.user?._id ?? locals.sessionId, |
|
createdAt: new Date(), |
|
updatedAt: new Date(), |
|
reason: result.data, |
|
}); |
|
|
|
if (!acknowledged) { |
|
return fail(500, { error: true, message: "Failed to report assistant" }); |
|
} |
|
|
|
if (WEBHOOK_URL_REPORT_ASSISTANT) { |
|
const prefixUrl = PUBLIC_SHARE_PREFIX || `${PUBLIC_ORIGIN || url.origin}${base}`; |
|
const assistantUrl = `${prefixUrl}/assistant/${params.assistantId}`; |
|
|
|
const assistant = await collections.assistants.findOne<Pick<Assistant, "name">>( |
|
{ _id: new ObjectId(params.assistantId) }, |
|
{ projection: { name: 1 } } |
|
); |
|
|
|
const username = locals.user?.username; |
|
|
|
const res = await fetch(WEBHOOK_URL_REPORT_ASSISTANT, { |
|
method: "POST", |
|
headers: { |
|
"Content-type": "application/json", |
|
}, |
|
body: JSON.stringify({ |
|
text: `Assistant <${assistantUrl}|${assistant?.name}> reported by ${ |
|
username ? `<http://hf.co/${username}|${username}>` : "non-logged in user" |
|
}.\n\n> ${result.data}`, |
|
}), |
|
}); |
|
|
|
if (!res.ok) { |
|
console.error(`Webhook assistant report failed. ${res.statusText} ${res.text}`); |
|
} |
|
} |
|
|
|
return { from: "report", ok: true, message: "Assistant reported" }; |
|
}, |
|
|
|
subscribe: async ({ params, locals }) => { |
|
const assistant = await collections.assistants.findOne({ |
|
_id: new ObjectId(params.assistantId), |
|
}); |
|
|
|
if (!assistant) { |
|
return fail(404, { error: true, message: "Assistant not found" }); |
|
} |
|
|
|
|
|
const settings = await collections.settings.findOne(authCondition(locals)); |
|
|
|
if (settings?.assistants?.includes(assistant._id)) { |
|
return fail(400, { error: true, message: "Already subscribed" }); |
|
} |
|
|
|
const result = await collections.settings.updateOne(authCondition(locals), { |
|
$addToSet: { assistants: assistant._id }, |
|
}); |
|
|
|
|
|
if (result.modifiedCount > 0) { |
|
await collections.assistants.updateOne({ _id: assistant._id }, { $inc: { userCount: 1 } }); |
|
} |
|
|
|
return { from: "subscribe", ok: true, message: "Assistant added" }; |
|
}, |
|
|
|
unsubscribe: async ({ params, locals }) => { |
|
const assistant = await collections.assistants.findOne({ |
|
_id: new ObjectId(params.assistantId), |
|
}); |
|
|
|
if (!assistant) { |
|
return fail(404, { error: true, message: "Assistant not found" }); |
|
} |
|
|
|
const result = await collections.settings.updateOne(authCondition(locals), { |
|
$pull: { assistants: assistant._id }, |
|
}); |
|
|
|
|
|
if (result.modifiedCount > 0) { |
|
await collections.assistants.updateOne({ _id: assistant._id }, { $inc: { userCount: -1 } }); |
|
} |
|
|
|
throw redirect(302, `${base}/settings`); |
|
}, |
|
}; |
|
|