coyotte508 HF staff commited on
Commit
76d4779
1 Parent(s): 7b1d57f

♻️ Duplicate convos in DB when they are shared (#44)

Browse files
src/lib/server/database.ts CHANGED
@@ -1,6 +1,7 @@
1
  import { MONGODB_URL, MONGODB_DB_NAME } from '$env/static/private';
2
  import { MongoClient } from 'mongodb';
3
  import type { Conversation } from '$lib/types/Conversation';
 
4
 
5
  const client = new MongoClient(MONGODB_URL, {
6
  // directConnection: true
@@ -11,11 +12,12 @@ export const connectPromise = client.connect().catch(console.error);
11
  const db = client.db(MONGODB_DB_NAME);
12
 
13
  const conversations = db.collection<Conversation>('conversations');
 
14
 
15
  export { client, db };
16
- export const collections = { conversations };
17
 
18
  client.on('open', () => {
19
  conversations.createIndex({ sessionId: 1, updatedAt: -1 });
20
- conversations.createIndex({ 'shares.id': 1 }, { unique: true, sparse: true });
21
  });
 
1
  import { MONGODB_URL, MONGODB_DB_NAME } from '$env/static/private';
2
  import { MongoClient } from 'mongodb';
3
  import type { Conversation } from '$lib/types/Conversation';
4
+ import type { SharedConversation } from '$lib/types/SharedConversation';
5
 
6
  const client = new MongoClient(MONGODB_URL, {
7
  // directConnection: true
 
12
  const db = client.db(MONGODB_DB_NAME);
13
 
14
  const conversations = db.collection<Conversation>('conversations');
15
+ const sharedConversations = db.collection<SharedConversation>('sharedConversations');
16
 
17
  export { client, db };
18
+ export const collections = { conversations, sharedConversations };
19
 
20
  client.on('open', () => {
21
  conversations.createIndex({ sessionId: 1, updatedAt: -1 });
22
+ sharedConversations.createIndex({ hash: 1 }, { unique: true });
23
  });
src/lib/types/Conversation.ts CHANGED
@@ -5,13 +5,11 @@ export interface Conversation {
5
  _id: ObjectId;
6
 
7
  // Can be undefined for shared convo then deleted
8
- sessionId?: string;
9
 
10
  title: string;
11
  messages: Message[];
12
 
13
- shares?: Array<{ id: string; msgCount: number }>;
14
-
15
  createdAt: Date;
16
  updatedAt: Date;
17
  }
 
5
  _id: ObjectId;
6
 
7
  // Can be undefined for shared convo then deleted
8
+ sessionId: string;
9
 
10
  title: string;
11
  messages: Message[];
12
 
 
 
13
  createdAt: Date;
14
  updatedAt: Date;
15
  }
src/lib/types/SharedConversation.ts ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { Message } from './Message';
2
+
3
+ export interface SharedConversation {
4
+ _id: string;
5
+
6
+ hash: string;
7
+
8
+ title: string;
9
+ messages: Message[];
10
+
11
+ createdAt: Date;
12
+ updatedAt: Date;
13
+ }
src/lib/utils/sha256.ts ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ export async function sha256(input: string): Promise<string> {
2
+ const utf8 = new TextEncoder().encode(input);
3
+ const hashBuffer = await crypto.subtle.digest('SHA-256', utf8);
4
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
5
+ const hashHex = hashArray.map((bytes) => bytes.toString(16).padStart(2, '0')).join('');
6
+ return hashHex;
7
+ }
src/routes/conversation/[id]/share/+server.ts CHANGED
@@ -1,4 +1,6 @@
1
  import { collections } from '$lib/server/database.js';
 
 
2
  import { error } from '@sveltejs/kit';
3
  import { ObjectId } from 'mongodb';
4
  import { nanoid } from 'nanoid';
@@ -13,39 +15,33 @@ export async function POST({ params, url, locals }) {
13
  throw error(404, 'Conversation not found');
14
  }
15
 
16
- const shares = conversation.shares || [];
17
 
18
- const existingShare = shares.find((share) => share.msgCount === conversation.messages.length);
19
 
20
  if (existingShare) {
21
  return new Response(
22
  JSON.stringify({
23
- url: url.origin + `/r/${existingShare.id}`
24
  }),
25
  { headers: { 'Content-Type': 'application/json' } }
26
  );
27
  }
28
 
29
- const share = {
30
- id: nanoid(7),
31
- msgCount: conversation.messages.length
 
 
 
 
32
  };
33
 
34
- await collections.conversations.updateOne(
35
- {
36
- _id: conversation._id
37
- },
38
- {
39
- $set: {
40
- shares: [...shares, share],
41
- updatedAt: new Date()
42
- }
43
- }
44
- );
45
 
46
  return new Response(
47
  JSON.stringify({
48
- url: url.origin.replace('huggingface.co', 'hf.co') + `/r/${share.id}`
49
  }),
50
  { headers: { 'Content-Type': 'application/json' } }
51
  );
 
1
  import { collections } from '$lib/server/database.js';
2
+ import type { SharedConversation } from '$lib/types/SharedConversation.js';
3
+ import { sha256 } from '$lib/utils/sha256.js';
4
  import { error } from '@sveltejs/kit';
5
  import { ObjectId } from 'mongodb';
6
  import { nanoid } from 'nanoid';
 
15
  throw error(404, 'Conversation not found');
16
  }
17
 
18
+ const hash = await sha256(JSON.stringify(conversation.messages));
19
 
20
+ const existingShare = await collections.sharedConversations.findOne({ hash });
21
 
22
  if (existingShare) {
23
  return new Response(
24
  JSON.stringify({
25
+ url: url.origin + `/r/${existingShare._id}`
26
  }),
27
  { headers: { 'Content-Type': 'application/json' } }
28
  );
29
  }
30
 
31
+ const shared: SharedConversation = {
32
+ _id: nanoid(7),
33
+ createdAt: new Date(),
34
+ messages: conversation.messages,
35
+ hash,
36
+ updatedAt: new Date(),
37
+ title: conversation.title
38
  };
39
 
40
+ await collections.sharedConversations.insertOne(shared);
 
 
 
 
 
 
 
 
 
 
41
 
42
  return new Response(
43
  JSON.stringify({
44
+ url: url.origin.replace('huggingface.co', 'hf.co') + `/r/${shared._id}`
45
  }),
46
  { headers: { 'Content-Type': 'application/json' } }
47
  );
src/routes/r/[id]/+page.server.ts CHANGED
@@ -1,9 +1,10 @@
1
- import { collections } from '$lib/server/database.js';
 
2
  import { error } from '@sveltejs/kit';
3
 
4
- export async function load({ params }) {
5
- const conversation = await collections.conversations.findOne({
6
- 'shares.id': params.id
7
  });
8
 
9
  if (!conversation) {
@@ -13,4 +14,4 @@ export async function load({ params }) {
13
  return {
14
  messages: conversation.messages
15
  };
16
- }
 
1
+ import type { PageServerLoad } from './$types';
2
+ import { collections } from '$lib/server/database';
3
  import { error } from '@sveltejs/kit';
4
 
5
+ export const load: PageServerLoad = async ({ params }) => {
6
+ const conversation = await collections.sharedConversations.findOne({
7
+ _id: params.id
8
  });
9
 
10
  if (!conversation) {
 
14
  return {
15
  messages: conversation.messages
16
  };
17
+ };