Coverage for /opt/conda/envs/apienv/lib/python3.10/site-packages/daiquiri/core/components/chat.py: 92%
75 statements
« prev ^ index » next coverage.py v7.6.5, created at 2024-11-15 02:12 +0000
« prev ^ index » next coverage.py v7.6.5, created at 2024-11-15 02:12 +0000
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3import time
4import logging
6from marshmallow import Schema, fields
7from flask import g
9from daiquiri.core import marshal
10from daiquiri.core.components import Component, ComponentResource
11from daiquiri.core.schema import ErrorSchema, MessageSchema
12from daiquiri.core.schema.metadata import paginated
14logger = logging.getLogger(__name__)
17class NewChatSchema(Schema):
18 """New Chat Message Schema"""
20 message = fields.Str(required=True, metadata={"description": "The message"})
23class ChatSchema(NewChatSchema):
24 """Chat Message Schema"""
26 messageid = fields.Int(metadata={"description": "Unique id of the message"})
27 timestamp = fields.Int(metadata={"description": "Epoch timestamp message was sent"})
28 sessionid = fields.Str(metadata={"description": "Author sessionid"})
29 user = fields.Str(metadata={"description": "User name associated with sessionid"})
30 read = fields.List(
31 fields.Str(),
32 metadata={"description": "List of sessions that have read the message"},
33 )
36class AllMessagesReadSchema(Schema):
37 """All messages read schema"""
39 maxid = fields.Int(metadata={"description": "Maximum chat messageid"})
42class ChatResource(ComponentResource):
43 @marshal(
44 inp={"limit": fields.Int(), "offset": fields.Int()},
45 out=[[200, paginated(ChatSchema), "List of chat messages"]],
46 )
47 def get(self, **kwargs):
48 """Get the last n chat messages"""
49 return self._parent.get_messages(**kwargs)
51 @marshal(
52 inp=ChatSchema,
53 out=[
54 [200, ChatSchema(), "Sent message"],
55 [400, ErrorSchema(), "Could not send messsage"],
56 ],
57 )
58 def post(self, **kwargs):
59 """Add a new chat message"""
60 message = self._parent.add_message(**kwargs)
61 if message:
62 return message
64 return {"error": "Could not send message"}, 400
66 @marshal(
67 out=[
68 [200, AllMessagesReadSchema(), "All messages marked as read"],
69 [400, ErrorSchema(), "Could not mark all messsages read"],
70 ],
71 )
72 def patch(self, **kwargs):
73 """Mark all chat message as read"""
74 maxid = self._parent.mark_all(**kwargs)
75 if maxid is not None:
76 return {"maxid": maxid}
78 return {"error": "Could not mark all messages read"}, 400
81class ChatMessageResource(ComponentResource):
82 @marshal(
83 out=[
84 [200, MessageSchema(), "Message marked as read"],
85 [400, ErrorSchema(), "Could not mark messsage read"],
86 ],
87 )
88 def patch(self, messageid, **kwargs):
89 """Mark a chat message as read"""
90 read = self._parent.mark_message(messageid, **kwargs)
91 if read:
92 return {"message": "Message marked as read"}
94 return {"error": "Could not mark message read"}, 400
97class Chat(Component):
98 """Chat Component
100 A simple chat component
101 """
103 _require_blsession = False
105 _messageid = 0
106 _messages = []
108 def setup(self, *args, **kwargs):
109 self.register_route(ChatResource, "")
110 self.register_route(ChatMessageResource, "/<int:messageid>")
112 def add_message(self, **kwargs):
113 """Add a new message"""
114 self._messageid += 1
115 message = {
116 "messageid": self._messageid,
117 "timestamp": time.time(),
118 "sessionid": g.sessionid,
119 "user": g.user.get("fullname"),
120 "message": kwargs["message"],
121 "read": [g.sessionid],
122 }
124 self._messages.append(message)
125 self.emit("new_message", message)
127 return message
129 def get_messages(self, **kwargs):
130 """Get all messages"""
131 limit = kwargs.get("limit", 50)
132 offset = kwargs.get("offset", 0)
134 return {
135 "rows": self._messages[::-1][offset : offset + limit],
136 "total": len(self._messages),
137 }
139 def mark_message(self, messageid, **kwargs):
140 """Mark a message as read"""
141 message = next(
142 (msg for msg in self._messages if msg["messageid"] == messageid), None
143 )
144 if message:
145 if g.sessionid not in message["read"]:
146 message["read"].append(g.sessionid)
148 self.emit(
149 "message_read",
150 message,
151 )
153 return True
155 def mark_all(self, **kwargs):
156 """Mark all messages read"""
157 maxid = 0
158 for message in self._messages:
159 if g.sessionid not in message["read"]:
160 message["read"].append(g.sessionid)
162 if message["messageid"] > maxid:
163 maxid = message["messageid"]
165 self.emit(
166 "all_message_read",
167 {"sessionid": g.sessionid},
168 )
170 return maxid