chats.py 7.36 KB
Newer Older
Timothy J. Baek's avatar
Timothy J. Baek committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from pydantic import BaseModel
from typing import List, Union, Optional
from peewee import *
from playhouse.shortcuts import model_to_dict

import json
import uuid
import time

from apps.web.internal.db import DB

####################
# Chat DB Schema
####################


class Chat(Model):
    id = CharField(unique=True)
Timothy J. Baek's avatar
Timothy J. Baek committed
19
    user_id = CharField()
Timothy J. Baek's avatar
Timothy J. Baek committed
20
21
22
    title = CharField()
    chat = TextField()  # Save Chat JSON as Text
    timestamp = DateField()
23
    share_id = CharField(null=True, unique=True)
Timothy J. Baek's avatar
Timothy J. Baek committed
24
25
26
27
28
29
30
31
32

    class Meta:
        database = DB


class ChatModel(BaseModel):
    id: str
    user_id: str
    title: str
Timothy J. Baek's avatar
Timothy J. Baek committed
33
    chat: str
Timothy J. Baek's avatar
Timothy J. Baek committed
34
    timestamp: int  # timestamp in epoch
35
    share_id: Optional[str] = None
Timothy J. Baek's avatar
Timothy J. Baek committed
36
37
38
39
40
41
42
43
44
45
46


####################
# Forms
####################


class ChatForm(BaseModel):
    chat: dict


Timothy J. Baek's avatar
Timothy J. Baek committed
47
48
49
50
class ChatTitleForm(BaseModel):
    title: str


51
class ChatResponse(BaseModel):
Timothy J. Baek's avatar
Timothy J. Baek committed
52
    id: str
53
54
55
56
    user_id: str
    title: str
    chat: dict
    timestamp: int  # timestamp in epoch
57
    share_id: Optional[str] = None  # id of the chat to be shared
Timothy J. Baek's avatar
Timothy J. Baek committed
58
59
60
61
62
63
64
65
66
67
68
69


class ChatTitleIdResponse(BaseModel):
    id: str
    title: str


class ChatTable:
    def __init__(self, db):
        self.db = db
        db.create_tables([Chat])

Timothy J. Baek's avatar
Timothy J. Baek committed
70
    def insert_new_chat(self, user_id: str, form_data: ChatForm) -> Optional[ChatModel]:
Timothy J. Baek's avatar
Timothy J. Baek committed
71
72
73
74
75
        id = str(uuid.uuid4())
        chat = ChatModel(
            **{
                "id": id,
                "user_id": user_id,
76
77
78
                "title": (
                    form_data.chat["title"] if "title" in form_data.chat else "New Chat"
                ),
Timothy J. Baek's avatar
Timothy J. Baek committed
79
                "chat": json.dumps(form_data.chat),
Timothy J. Baek's avatar
Timothy J. Baek committed
80
                "timestamp": int(time.time()),
Timothy J. Baek's avatar
Timothy J. Baek committed
81
82
            }
        )
Timothy J. Baek's avatar
Timothy J. Baek committed
83
84
85
86
87
88

        result = Chat.create(**chat.model_dump())
        return chat if result else None

    def update_chat_by_id(self, id: str, chat: dict) -> Optional[ChatModel]:
        try:
89
90
91
92
93
            query = Chat.update(
                chat=json.dumps(chat),
                title=chat["title"] if "title" in chat else "New Chat",
                timestamp=int(time.time()),
            ).where(Chat.id == id)
Timothy J. Baek's avatar
Timothy J. Baek committed
94
95
96
97
98
99
100
            query.execute()

            chat = Chat.get(Chat.id == id)
            return ChatModel(**model_to_dict(chat))
        except:
            return None

Timothy J. Baek's avatar
Timothy J. Baek committed
101
    def insert_shared_chat_by_chat_id(self, chat_id: str) -> Optional[ChatModel]:
102
103
104
105
106
107
108
109
110
        # Get the existing chat to share
        chat = Chat.get(Chat.id == chat_id)
        # Check if the chat is already shared
        if chat.share_id:
            return self.get_chat_by_id_and_user_id(chat.share_id, "shared")
        # Create a new chat with the same data, but with a new ID
        shared_chat = ChatModel(
            **{
                "id": str(uuid.uuid4()),
Timothy J. Baek's avatar
Timothy J. Baek committed
111
                "user_id": f"shared-{chat_id}",
112
113
114
115
116
117
118
119
120
121
122
123
124
                "title": chat.title,
                "chat": chat.chat,
                "timestamp": int(time.time()),
            }
        )
        shared_result = Chat.create(**shared_chat.model_dump())
        # Update the original chat with the share_id
        result = (
            Chat.update(share_id=shared_chat.id).where(Chat.id == chat_id).execute()
        )

        return shared_chat if (shared_result and result) else None

Timothy J. Baek's avatar
Timothy J. Baek committed
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
    def update_shared_chat_by_chat_id(self, chat_id: str) -> Optional[ChatModel]:
        try:
            print("update_shared_chat_by_id")
            chat = Chat.get(Chat.id == chat_id)
            print(chat)

            query = Chat.update(
                title=chat.title,
                chat=chat.chat,
            ).where(Chat.id == chat.share_id)

            query.execute()

            chat = Chat.get(Chat.id == chat.share_id)
            return ChatModel(**model_to_dict(chat))
        except:
            return None

Timothy J. Baek's avatar
Timothy J. Baek committed
143
144
145
146
147
148
149
150
151
    def delete_shared_chat_by_chat_id(self, chat_id: str) -> bool:
        try:
            query = Chat.delete().where(Chat.user_id == f"shared-{chat_id}")
            query.execute()  # Remove the rows, return number of rows removed.

            return True
        except:
            return False

152
    def update_chat_share_id_by_id(
Timothy J. Baek's avatar
Timothy J. Baek committed
153
        self, id: str, share_id: Optional[str]
154
155
156
157
158
159
160
161
162
163
164
165
    ) -> Optional[ChatModel]:
        try:
            query = Chat.update(
                share_id=share_id,
            ).where(Chat.id == id)
            query.execute()

            chat = Chat.get(Chat.id == id)
            return ChatModel(**model_to_dict(chat))
        except:
            return None

Timothy J. Baek's avatar
Timothy J. Baek committed
166
167
168
    def get_chat_lists_by_user_id(
        self, user_id: str, skip: int = 0, limit: int = 50
    ) -> List[ChatModel]:
Timothy J. Baek's avatar
Timothy J. Baek committed
169
        return [
Timothy J. Baek's avatar
Timothy J. Baek committed
170
171
172
173
            ChatModel(**model_to_dict(chat))
            for chat in Chat.select()
            .where(Chat.user_id == user_id)
            .order_by(Chat.timestamp.desc())
174
175
            # .limit(limit)
            # .offset(skip)
Timothy J. Baek's avatar
Timothy J. Baek committed
176
177
        ]

Timothy J. Baek's avatar
Timothy J. Baek committed
178
179
180
181
182
183
184
185
186
187
    def get_chat_lists_by_chat_ids(
        self, chat_ids: List[str], skip: int = 0, limit: int = 50
    ) -> List[ChatModel]:
        return [
            ChatModel(**model_to_dict(chat))
            for chat in Chat.select()
            .where(Chat.id.in_(chat_ids))
            .order_by(Chat.timestamp.desc())
        ]

188
189
190
191
192
193
    def get_all_chats(self) -> List[ChatModel]:
        return [
            ChatModel(**model_to_dict(chat))
            for chat in Chat.select().order_by(Chat.timestamp.desc())
        ]

Timothy J. Baek's avatar
Timothy J. Baek committed
194
195
    def get_all_chats_by_user_id(self, user_id: str) -> List[ChatModel]:
        return [
Timothy J. Baek's avatar
Timothy J. Baek committed
196
197
198
199
            ChatModel(**model_to_dict(chat))
            for chat in Chat.select()
            .where(Chat.user_id == user_id)
            .order_by(Chat.timestamp.desc())
Timothy J. Baek's avatar
Timothy J. Baek committed
200
201
        ]

Timothy J. Baek's avatar
Timothy J. Baek committed
202
203
204
205
206
207
208
    def get_chat_by_id(self, id: str) -> Optional[ChatModel]:
        try:
            chat = Chat.get(Chat.id == id)
            return ChatModel(**model_to_dict(chat))
        except:
            return None

Timothy J. Baek's avatar
Timothy J. Baek committed
209
    def get_chat_by_id_and_user_id(self, id: str, user_id: str) -> Optional[ChatModel]:
Timothy J. Baek's avatar
Timothy J. Baek committed
210
211
212
213
214
215
216
217
218
219
220
221
        try:
            chat = Chat.get(Chat.id == id, Chat.user_id == user_id)
            return ChatModel(**model_to_dict(chat))
        except:
            return None

    def get_chats(self, skip: int = 0, limit: int = 50) -> List[ChatModel]:
        return [
            ChatModel(**model_to_dict(chat))
            for chat in Chat.select().limit(limit).offset(skip)
        ]

222
223
    def delete_chat_by_id_and_user_id(self, id: str, user_id: str) -> bool:
        try:
Timothy J. Baek's avatar
Timothy J. Baek committed
224
            query = Chat.delete().where((Chat.id == id) & (Chat.user_id == user_id))
225
226
            query.execute()  # Remove the rows, return number of rows removed.

Timothy J. Baek's avatar
Timothy J. Baek committed
227
            return True and self.delete_shared_chat_by_chat_id(id)
228
229
230
        except:
            return False

231
232
    def delete_chats_by_user_id(self, user_id: str) -> bool:
        try:
233
234
235

            self.delete_shared_chats_by_user_id(user_id)

236
237
238
            query = Chat.delete().where(Chat.user_id == user_id)
            query.execute()  # Remove the rows, return number of rows removed.

239
            return True
Timothy J. Baek's avatar
Timothy J. Baek committed
240
241
242
243
244
245
246
247
248
249
        except:
            return False

    def delete_shared_chats_by_user_id(self, user_id: str) -> bool:
        try:
            shared_chat_ids = [
                f"shared-{chat.id}"
                for chat in Chat.select().where(Chat.user_id == user_id)
            ]

250
251
            print(shared_chat_ids)

Timothy J. Baek's avatar
Timothy J. Baek committed
252
253
254
            query = Chat.delete().where(Chat.user_id << shared_chat_ids)
            query.execute()  # Remove the rows, return number of rows removed.

255
256
257
258
            return True
        except:
            return False

Timothy J. Baek's avatar
Timothy J. Baek committed
259
260

Chats = ChatTable(DB)