|
@@ -17,6 +17,25 @@ from sqlalchemy.sql import exists
|
|
####################
|
|
####################
|
|
|
|
|
|
|
|
|
|
|
|
+class MessageReaction(Base):
|
|
|
|
+ __tablename__ = "message_reaction"
|
|
|
|
+ id = Column(Text, primary_key=True)
|
|
|
|
+ user_id = Column(Text)
|
|
|
|
+ message_id = Column(Text)
|
|
|
|
+ name = Column(Text)
|
|
|
|
+ created_at = Column(BigInteger)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+class MessageReactionModel(BaseModel):
|
|
|
|
+ model_config = ConfigDict(from_attributes=True)
|
|
|
|
+
|
|
|
|
+ id: str
|
|
|
|
+ user_id: str
|
|
|
|
+ message_id: str
|
|
|
|
+ name: str
|
|
|
|
+ created_at: int # timestamp in epoch
|
|
|
|
+
|
|
|
|
+
|
|
class Message(Base):
|
|
class Message(Base):
|
|
__tablename__ = "message"
|
|
__tablename__ = "message"
|
|
id = Column(Text, primary_key=True)
|
|
id = Column(Text, primary_key=True)
|
|
@@ -24,6 +43,8 @@ class Message(Base):
|
|
user_id = Column(Text)
|
|
user_id = Column(Text)
|
|
channel_id = Column(Text, nullable=True)
|
|
channel_id = Column(Text, nullable=True)
|
|
|
|
|
|
|
|
+ parent_id = Column(Text, nullable=True)
|
|
|
|
+
|
|
content = Column(Text)
|
|
content = Column(Text)
|
|
data = Column(JSON, nullable=True)
|
|
data = Column(JSON, nullable=True)
|
|
meta = Column(JSON, nullable=True)
|
|
meta = Column(JSON, nullable=True)
|
|
@@ -39,6 +60,8 @@ class MessageModel(BaseModel):
|
|
user_id: str
|
|
user_id: str
|
|
channel_id: Optional[str] = None
|
|
channel_id: Optional[str] = None
|
|
|
|
|
|
|
|
+ parent_id: Optional[str] = None
|
|
|
|
+
|
|
content: str
|
|
content: str
|
|
data: Optional[dict] = None
|
|
data: Optional[dict] = None
|
|
meta: Optional[dict] = None
|
|
meta: Optional[dict] = None
|
|
@@ -54,10 +77,21 @@ class MessageModel(BaseModel):
|
|
|
|
|
|
class MessageForm(BaseModel):
|
|
class MessageForm(BaseModel):
|
|
content: str
|
|
content: str
|
|
|
|
+ parent_id: Optional[str] = None
|
|
data: Optional[dict] = None
|
|
data: Optional[dict] = None
|
|
meta: Optional[dict] = None
|
|
meta: Optional[dict] = None
|
|
|
|
|
|
|
|
|
|
|
|
+class Reactions(BaseModel):
|
|
|
|
+ name: str
|
|
|
|
+ user_ids: list[str]
|
|
|
|
+ count: int
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+class MessageResponse(MessageModel):
|
|
|
|
+ reactions: list[Reactions]
|
|
|
|
+
|
|
|
|
+
|
|
class MessageTable:
|
|
class MessageTable:
|
|
def insert_new_message(
|
|
def insert_new_message(
|
|
self, form_data: MessageForm, channel_id: str, user_id: str
|
|
self, form_data: MessageForm, channel_id: str, user_id: str
|
|
@@ -71,6 +105,7 @@ class MessageTable:
|
|
"id": id,
|
|
"id": id,
|
|
"user_id": user_id,
|
|
"user_id": user_id,
|
|
"channel_id": channel_id,
|
|
"channel_id": channel_id,
|
|
|
|
+ "parent_id": form_data.parent_id,
|
|
"content": form_data.content,
|
|
"content": form_data.content,
|
|
"data": form_data.data,
|
|
"data": form_data.data,
|
|
"meta": form_data.meta,
|
|
"meta": form_data.meta,
|
|
@@ -85,10 +120,19 @@ class MessageTable:
|
|
db.refresh(result)
|
|
db.refresh(result)
|
|
return MessageModel.model_validate(result) if result else None
|
|
return MessageModel.model_validate(result) if result else None
|
|
|
|
|
|
- def get_message_by_id(self, id: str) -> Optional[MessageModel]:
|
|
|
|
|
|
+ def get_message_by_id(self, id: str) -> Optional[MessageResponse]:
|
|
with get_db() as db:
|
|
with get_db() as db:
|
|
message = db.get(Message, id)
|
|
message = db.get(Message, id)
|
|
- return MessageModel.model_validate(message) if message else None
|
|
|
|
|
|
+ if not message:
|
|
|
|
+ return None
|
|
|
|
+
|
|
|
|
+ reactions = self.get_reactions_by_message_id(id)
|
|
|
|
+ return MessageResponse(
|
|
|
|
+ **{
|
|
|
|
+ **MessageModel.model_validate(message).model_dump(),
|
|
|
|
+ "reactions": reactions,
|
|
|
|
+ }
|
|
|
|
+ )
|
|
|
|
|
|
def get_messages_by_channel_id(
|
|
def get_messages_by_channel_id(
|
|
self, channel_id: str, skip: int = 0, limit: int = 50
|
|
self, channel_id: str, skip: int = 0, limit: int = 50
|
|
@@ -104,20 +148,6 @@ class MessageTable:
|
|
)
|
|
)
|
|
return [MessageModel.model_validate(message) for message in all_messages]
|
|
return [MessageModel.model_validate(message) for message in all_messages]
|
|
|
|
|
|
- def get_messages_by_user_id(
|
|
|
|
- self, user_id: str, skip: int = 0, limit: int = 50
|
|
|
|
- ) -> list[MessageModel]:
|
|
|
|
- with get_db() as db:
|
|
|
|
- all_messages = (
|
|
|
|
- db.query(Message)
|
|
|
|
- .filter_by(user_id=user_id)
|
|
|
|
- .order_by(Message.created_at.desc())
|
|
|
|
- .offset(skip)
|
|
|
|
- .limit(limit)
|
|
|
|
- .all()
|
|
|
|
- )
|
|
|
|
- return [MessageModel.model_validate(message) for message in all_messages]
|
|
|
|
-
|
|
|
|
def update_message_by_id(
|
|
def update_message_by_id(
|
|
self, id: str, form_data: MessageForm
|
|
self, id: str, form_data: MessageForm
|
|
) -> Optional[MessageModel]:
|
|
) -> Optional[MessageModel]:
|
|
@@ -131,9 +161,58 @@ class MessageTable:
|
|
db.refresh(message)
|
|
db.refresh(message)
|
|
return MessageModel.model_validate(message) if message else None
|
|
return MessageModel.model_validate(message) if message else None
|
|
|
|
|
|
|
|
+ def add_reaction_to_message(
|
|
|
|
+ self, id: str, user_id: str, name: str
|
|
|
|
+ ) -> Optional[MessageReactionModel]:
|
|
|
|
+ with get_db() as db:
|
|
|
|
+ reaction_id = str(uuid.uuid4())
|
|
|
|
+ reaction = MessageReactionModel(
|
|
|
|
+ id=reaction_id,
|
|
|
|
+ user_id=user_id,
|
|
|
|
+ message_id=id,
|
|
|
|
+ name=name,
|
|
|
|
+ created_at=int(time.time_ns()),
|
|
|
|
+ )
|
|
|
|
+ result = MessageReaction(**reaction.model_dump())
|
|
|
|
+ db.add(result)
|
|
|
|
+ db.commit()
|
|
|
|
+ db.refresh(result)
|
|
|
|
+ return MessageReactionModel.model_validate(result) if result else None
|
|
|
|
+
|
|
|
|
+ def get_reactions_by_message_id(self, id: str) -> list[Reactions]:
|
|
|
|
+ with get_db() as db:
|
|
|
|
+ all_reactions = db.query(MessageReaction).filter_by(message_id=id).all()
|
|
|
|
+
|
|
|
|
+ reactions = {}
|
|
|
|
+ for reaction in all_reactions:
|
|
|
|
+ if reaction.name not in reactions:
|
|
|
|
+ reactions[reaction.name] = {
|
|
|
|
+ "name": reaction.name,
|
|
|
|
+ "user_ids": [],
|
|
|
|
+ "count": 0,
|
|
|
|
+ }
|
|
|
|
+ reactions[reaction.name]["user_ids"].append(reaction.user_id)
|
|
|
|
+ reactions[reaction.name]["count"] += 1
|
|
|
|
+
|
|
|
|
+ return [Reactions(**reaction) for reaction in reactions.values()]
|
|
|
|
+
|
|
|
|
+ def remove_reaction_by_id_and_user_id_and_name(
|
|
|
|
+ self, id: str, user_id: str, name: str
|
|
|
|
+ ) -> bool:
|
|
|
|
+ with get_db() as db:
|
|
|
|
+ db.query(MessageReaction).filter_by(
|
|
|
|
+ message_id=id, user_id=user_id, name=name
|
|
|
|
+ ).delete()
|
|
|
|
+ db.commit()
|
|
|
|
+ return True
|
|
|
|
+
|
|
def delete_message_by_id(self, id: str) -> bool:
|
|
def delete_message_by_id(self, id: str) -> bool:
|
|
with get_db() as db:
|
|
with get_db() as db:
|
|
db.query(Message).filter_by(id=id).delete()
|
|
db.query(Message).filter_by(id=id).delete()
|
|
|
|
+
|
|
|
|
+ # Delete all reactions to this message
|
|
|
|
+ db.query(MessageReaction).filter_by(message_id=id).delete()
|
|
|
|
+
|
|
db.commit()
|
|
db.commit()
|
|
return True
|
|
return True
|
|
|
|
|