Python backend for a Slack's kudos plugin.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'feature/errors' into develop

+142 -23
+1 -1
kefi/constants.py
··· 19 19 20 20 21 21 class Actions: 22 - JOIN_MEET: str = "meet_join" 23 22 LEAVE_MEET: str = "meet_leave" 23 + SHOW_MEETS_MODAL: str = "show_meets_modal" 24 24 25 25 26 26 class EventBodyType:
+93 -10
kefi/routers/helpers.py
··· 4 4 5 5 from sqlmodel import Session 6 6 7 - from kefi.constants import Command, EventBodyType, InteractionType 7 + from kefi.constants import Actions, Command, EventBodyType, InteractionType 8 8 from kefi.dependencies import EventBody, InteractionParams, SlashCommandParams 9 9 from kefi.models.core.exceptions import NotEnoughKefi 10 10 from kefi.models.core.helpers import ( ··· 17 17 received_balance, 18 18 send_admin_amount, 19 19 ) 20 + from kefi.models.database import User 20 21 from kefi.models.kudos.helpers import ( 21 22 get_action, 22 23 notify_receiver_user_chat_action, ··· 28 29 delete_attendance, 29 30 is_attending, 30 31 ) 31 - from kefi.routers.messages import UserJoinedMeet, UserLeftMeet 32 + from kefi.routers.messages import ( 33 + AlreadyAttendingMessage, 34 + BaseMessage, 35 + NotAttendingMessage, 36 + NotEnoughKefiMessage, 37 + UserJoinedMeetMessage, 38 + UserLeftMeetMessage, 39 + ) 32 40 from kefi.routers.responses import ( 33 41 ActionResponse, 34 42 HelpResponse, ··· 171 179 InteractionType.VIEW_SUBMISSION: self.interaction_view_submission, 172 180 } 173 181 _type = self.payload["type"] 174 - print(self.payload) 175 182 response = handlers.get(_type, self.not_found)() 176 183 return response 177 184 ··· 194 201 return [] 195 202 196 203 def interaction_block_actions(self) -> list: 204 + handler = ActionsHandler( 205 + payload=self.payload, 206 + session=self.session, 207 + user=self.user, 208 + ) 209 + handler.handle() 197 210 return [] 198 211 199 212 def _view_submission_meet_join(self, view_id: str) -> list | dict: 200 213 """Joins the plaza.""" 214 + message: BaseMessage 201 215 try: 202 216 create_attendance(user=self.user, session=self.session) 217 + message = UserJoinedMeetMessage() 203 218 self.slack.post_message_user( 204 219 user_id=self.user.slack_user_id, 205 - blocks=UserJoinedMeet.blocks(), 206 - text=UserJoinedMeet.text(), 220 + blocks=message.blocks(), 221 + text=message.text(), 207 222 ) 208 223 except NotEnoughKefi: 209 - ... 224 + message = NotEnoughKefiMessage() 225 + self.slack.post_message_user( 226 + user_id=self.user.slack_user_id, 227 + blocks=message.blocks(), 228 + text=message.text(), 229 + ) 210 230 except AlreadyAttending: 211 - ... 231 + message = AlreadyAttendingMessage() 232 + self.slack.post_message_user( 233 + user_id=self.user.slack_user_id, 234 + blocks=message.blocks(), 235 + text=message.text(), 236 + ) 212 237 return {"response_action": "clear"} 213 238 214 239 def _view_submission_meet_leave(self, view_id: str) -> list | dict: 215 240 """Leaves the plaza.""" 241 + message: BaseMessage 216 242 try: 217 243 delete_attendance(user=self.user, session=self.session) 244 + message = UserLeftMeetMessage() 218 245 self.slack.post_message_user( 219 246 user_id=self.user.slack_user_id, 220 - blocks=UserLeftMeet.blocks(), 221 - text=UserLeftMeet.text(), 247 + blocks=message.blocks(), 248 + text=message.text(), 222 249 ) 223 250 except NotAttending: 224 - ... 251 + message = NotAttendingMessage() 252 + self.slack.post_message_user( 253 + user_id=self.user.slack_user_id, 254 + blocks=message.blocks(), 255 + text=message.text(), 256 + ) 225 257 return {"response_action": "clear"} 226 258 227 259 def interaction_view_submission(self) -> list | dict: ··· 238 270 239 271 def not_found(self) -> list: 240 272 return [] 273 + 274 + 275 + class ActionsHandler: 276 + def __init__(self, session: Session, user: User, payload: dict): 277 + self.payload = payload 278 + self.session = session 279 + self.user = user 280 + self.slack = Slack() 281 + 282 + def handle(self): 283 + actions = self.payload.get("actions") 284 + if actions is not None: 285 + for action in actions: 286 + handlers: dict[str, Callable] = { 287 + Actions.LEAVE_MEET: self.action_leave_meet, 288 + Actions.SHOW_MEETS_MODAL: self.action_show_meets_modal, 289 + } 290 + handlers.get(action["action_id"], self.not_found)() 291 + 292 + def not_found(self): 293 + ... 294 + 295 + def action_leave_meet(self): 296 + message: BaseMessage 297 + try: 298 + delete_attendance(user=self.user, session=self.session) 299 + message = UserLeftMeetMessage() 300 + self.slack.update_message( 301 + channel=self.payload["channel"]["id"], 302 + blocks=message.blocks(), 303 + text=message.text(), 304 + timestamp=self.payload["message"]["ts"], 305 + ) 306 + except NotAttending: 307 + message = NotAttendingMessage() 308 + self.slack.post_message_user( 309 + user_id=self.user.slack_user_id, 310 + blocks=message.blocks(), 311 + text=message.text(), 312 + ) 313 + 314 + def action_show_meets_modal(self): 315 + trigger_id = self.payload["trigger_id"] 316 + if not is_attending(user=self.user, session=self.session): 317 + self.slack.open_view( 318 + trigger_id=trigger_id, view=JoinMeetView(session=self.session) 319 + ) 320 + else: 321 + self.slack.open_view( 322 + trigger_id=trigger_id, view=LeaveMeetView(session=self.session) 323 + ) 241 324 242 325 243 326 class EventHandler:
+38 -10
kefi/routers/messages.py
··· 10 10 from kefi.constants import Actions 11 11 12 12 13 - class UserJoinedMeet: 14 - @staticmethod 15 - def text() -> str: 13 + class BaseMessage: 14 + def text(self) -> str: 15 + pass 16 + 17 + def blocks(self) -> list[Block]: 18 + pass 19 + 20 + 21 + class UserJoinedMeetMessage(BaseMessage): 22 + def text(self) -> str: 16 23 return ":tada: ¡Genial! ¡Nos vemos el próximo viernes!" 17 24 18 - @staticmethod 19 - def blocks() -> list[Block]: 25 + def blocks(self) -> list[Block]: 20 26 return [ 21 27 SectionBlock( 22 28 text=MarkdownTextObject( ··· 35 41 ] 36 42 37 43 38 - class UserLeftMeet: 39 - @staticmethod 40 - def text() -> str: 44 + class UserLeftMeetMessage(BaseMessage): 45 + def text(self) -> str: 41 46 return ":disappointed: ¡Vaya! ¡Esperamos verte la próxima vez!" 42 47 43 - @staticmethod 44 - def blocks() -> list[Block]: 48 + def blocks(self) -> list[Block]: 45 49 return [ 46 50 SectionBlock( 47 51 text=MarkdownTextObject( ··· 49 53 ) 50 54 ), 51 55 ] 56 + 57 + 58 + class NotEnoughKefiMessage(BaseMessage): 59 + def text(self) -> str: 60 + return "NotEnoughKefiMessage" 61 + 62 + def blocks(self) -> list[Block]: 63 + return [SectionBlock(text="NotEnoughKefiMessage")] 64 + 65 + 66 + class AlreadyAttendingMessage(BaseMessage): 67 + def text(self) -> str: 68 + return "AlreadyAttendingMessage" 69 + 70 + def blocks(self) -> list[Block]: 71 + return [SectionBlock(text="AlreadyAttendingMessage")] 72 + 73 + 74 + class NotAttendingMessage(BaseMessage): 75 + def text(self) -> str: 76 + return "NotAttendingMessage" 77 + 78 + def blocks(self) -> list[Block]: 79 + return [SectionBlock(text="NotAttendingMessage")]
+1 -2
kefi/routers/views.py
··· 92 92 def __init__(self, *args, **kwargs): 93 93 super().__init__( 94 94 type="home", 95 - # TODO: not needed: submit=PlainTextObject(text="No asistiré"), 96 95 blocks=[ 97 96 HeaderBlock( 98 97 text=PlainTextObject(text="Esto es lo que puedes hacer con Kefi:") ··· 153 152 elements=[ 154 153 ButtonElement( 155 154 text=PlainTextObject(text="¡Me Apunto!"), 156 - action_id=Actions.JOIN_MEET, 155 + action_id=Actions.SHOW_MEETS_MODAL, 157 156 ) 158 157 ] 159 158 ),
+9
kefi/slack.py
··· 47 47 ): 48 48 self.client.chat_postMessage(channel=user_id, blocks=blocks, text=text) 49 49 50 + def update_message( 51 + self, 52 + channel: str, 53 + timestamp: str, 54 + blocks: Sequence[dict | Block], 55 + text: str | None = None, 56 + ): 57 + self.client.chat_update(channel=channel, blocks=blocks, text=text, ts=timestamp) 58 + 50 59 def open_view(self, trigger_id: str, view: View): 51 60 self.client.views_open(trigger_id=trigger_id, view=view) 52 61