File size: 5,183 Bytes
992a8de
 
 
 
 
e9f817c
 
3109a5e
89ae59b
992a8de
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3c372b8
 
 
992a8de
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3109a5e
992a8de
 
c755352
53e0136
992a8de
 
 
 
 
 
3109a5e
 
 
 
 
 
 
992a8de
 
 
 
 
 
3109a5e
992a8de
 
 
 
 
e9f817c
 
 
 
 
89ae59b
e9f817c
 
 
 
89ae59b
 
e9f817c
 
 
 
 
 
89ae59b
 
 
e9f817c
 
 
 
 
 
 
 
992a8de
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
786115c
 
992a8de
 
786115c
 
 
 
 
992a8de
 
 
 
 
 
 
 
 
 
 
 
786115c
992a8de
 
 
786115c
 
 
 
 
992a8de
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
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 });

		// and remove it from all users settings
		await collections.settings.updateMany(
			{
				assistants: { $in: [assistant._id] },
			},
			{
				$pull: { assistants: assistant._id },
			}
		);

		// and delete all avatars
		const fileCursor = collections.bucket.find({ filename: assistant._id.toString() });

		// Step 2: Delete the existing file if it exists
		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 }) => {
		// is there already a report from this user for this model ?
		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" });
		}

		// don't push if it's already there
		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 },
		});

		// reduce count only if push succeeded
		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 },
		});

		// reduce count only if pull succeeded
		if (result.modifiedCount > 0) {
			await collections.assistants.updateOne({ _id: assistant._id }, { $inc: { userCount: -1 } });
		}

		throw redirect(302, `${base}/settings`);
	},
};