From a4b9adb9b9d43853bee49cee3969083060dcf462 Mon Sep 17 00:00:00 2001 From: Alexander Zveruk Date: Fri, 15 May 2020 23:14:40 +0300 Subject: [PATCH 1/7] processing updateChatOrder & updateChatIsPinned --- tg/controllers/__init__.py | 33 +++++++++++++++++++++++++++++++-- tg/models/__init__.py | 11 ++++++----- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/tg/controllers/__init__.py b/tg/controllers/__init__.py index de8922c..a25765e 100644 --- a/tg/controllers/__init__.py +++ b/tg/controllers/__init__.py @@ -1,4 +1,5 @@ import logging +from typing import Dict, Any import os import threading from datetime import datetime @@ -40,7 +41,9 @@ class Controller: self.tg = tg self.handlers = { "updateNewMessage": self.update_new_msg, + "updateChatIsPinned": self.update_chat_is_pinned, "updateChatLastMessage": self.update_chat_last_msg, + "updateChatOrder": self.update_chat_order, "updateMessageSendSucceeded": self.update_msg_send_succeeded, "updateFile": self.update_file, } @@ -305,12 +308,38 @@ class Controller: notify(text, title=name) @handle_exception - def update_chat_last_msg(self, update): + def update_chat_order(self, update: Dict[str, Any]): + log.info("Proccessing updateChatOrder") + current_chat_id = self.model.chats.id_by_index(self.model.current_chat) + chat_id = update["chat_id"] + order = update["order"] + + self.model.chats.update_chat(chat_id, order=order) + self._refresh_current_chat(current_chat_id) + + @handle_exception + def update_chat_is_pinned(self, update: Dict[str, Any]): + log.info("Proccessing updateChatIsPinned") + chat_id = update["chat_id"] + is_pinned = update["is_pinned"] + order = update["order"] + current_chat_id = self.model.chats.id_by_index(self.model.current_chat) + self.model.chats.update_chat(chat_id, is_pinned=is_pinned, order=order) + self._refresh_current_chat(current_chat_id) + + @handle_exception + def update_chat_last_msg(self, update: Dict[str, Any]): log.info("Proccessing updateChatLastMessage") chat_id = update["chat_id"] message = update["last_message"] + order = update["order"] current_chat_id = self.model.chats.id_by_index(self.model.current_chat) - self.model.chats.update_last_message(chat_id, message) + self.model.chats.update_chat( + chat_id, last_message=message, order=order + ) + self._refresh_current_chat(current_chat_id) + + def _refresh_current_chat(self, current_chat_id: int): # TODO: we can create for chats, it's faster than sqlite anyway # though need to make sure that creatinng index is atomic operation # requires locks for read, until index and chats will be the same diff --git a/tg/models/__init__.py b/tg/models/__init__.py index fe2c36a..63d0dc3 100644 --- a/tg/models/__init__.py +++ b/tg/models/__init__.py @@ -165,18 +165,19 @@ class ChatModel: return {} return result.update - def update_last_message(self, chat_id, message): + def update_chat(self, chat_id: int, **updates: Dict[str, Any]) -> bool: for i, c in enumerate(self.chats): if c["id"] != chat_id: continue - self.chats[i]["last_message"] = message + self.chats[i].update(updates) self.chats = sorted( self.chats, - key=lambda it: it["last_message"]["date"], + # recommended chat order, for more info see + # https://core.telegram.org/tdlib/getting-started#getting-the-lists-of-chats + key=lambda it: (it["order"], it["id"]), reverse=True, ) - - log.info("Updated last message") + log.info(f"Updated chat with keys {list(updates)}") return True else: log.error(f"Can't find chat {chat_id} in existing chats") From 77a81020000c3f8c01441827d64e410bbb0f4868 Mon Sep 17 00:00:00 2001 From: Alexander Zveruk Date: Fri, 15 May 2020 23:45:39 +0300 Subject: [PATCH 2/7] showing pinned messages on the UI --- tg/views/__init__.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tg/views/__init__.py b/tg/views/__init__.py index 1931c00..65356d8 100644 --- a/tg/views/__init__.py +++ b/tg/views/__init__.py @@ -145,10 +145,11 @@ class ChatView: self.win.vline(0, self.w - 1, curses.ACS_VLINE, self.h) for i, chat in enumerate(chats): is_selected = i == current - date, title, unread_count, last_msg = ( + date, title, unread_count, is_pinned, last_msg = ( get_date(chat), chat["title"], chat["unread_count"], + chat["is_pinned"], get_last_msg(chat), ) offset = 0 @@ -173,7 +174,9 @@ class ChatView: self.win.addstr(i, offset, last_msg, self._msg_color(is_selected)) - if left_label := self._get_chat_label(unread_count, chat): + if left_label := self._get_chat_label( + unread_count, is_pinned, chat + ): self.win.addstr( i, self.w - len(left_label) - 1, @@ -184,10 +187,14 @@ class ChatView: self._refresh() @staticmethod - def _get_chat_label(unread_count: int, chat: Dict[str, Any]) -> str: + def _get_chat_label( + unread_count: int, is_pinned: bool, chat: Dict[str, Any] + ) -> str: label = "" + if is_pinned: + label += "pinned " if unread_count: - label = f"{unread_count} " + label += f"{unread_count} " if chat["notification_settings"]["mute_for"]: label = f"muted {label}" From 81bf42718ab2b099b3e73205e6955b64e8c67892 Mon Sep 17 00:00:00 2001 From: Alexander Zveruk Date: Fri, 15 May 2020 23:55:18 +0300 Subject: [PATCH 3/7] processing updateChatDraftMessage --- tg/controllers/__init__.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/tg/controllers/__init__.py b/tg/controllers/__init__.py index a25765e..95a58be 100644 --- a/tg/controllers/__init__.py +++ b/tg/controllers/__init__.py @@ -1,5 +1,5 @@ import logging -from typing import Dict, Any +from typing import Dict, Any, Optional import os import threading from datetime import datetime @@ -43,6 +43,7 @@ class Controller: "updateNewMessage": self.update_new_msg, "updateChatIsPinned": self.update_chat_is_pinned, "updateChatLastMessage": self.update_chat_last_msg, + "updateChatDraftMessage": self.update_chat_draft_msg, "updateChatOrder": self.update_chat_order, "updateMessageSendSucceeded": self.update_msg_send_succeeded, "updateFile": self.update_file, @@ -327,6 +328,17 @@ class Controller: self.model.chats.update_chat(chat_id, is_pinned=is_pinned, order=order) self._refresh_current_chat(current_chat_id) + @handle_exception + def update_chat_draft_msg(self, update: Dict[str, Any]): + log.info("Proccessing updateChatLastMessage") + chat_id = update["chat_id"] + # FIXME: ignoring draft message itself for now because UI can't show it + # draft_message = update["draft_message"] + order = update["order"] + current_chat_id = self.model.chats.id_by_index(self.model.current_chat) + self.model.chats.update_chat(chat_id, order=order) + self._refresh_current_chat(current_chat_id) + @handle_exception def update_chat_last_msg(self, update: Dict[str, Any]): log.info("Proccessing updateChatLastMessage") @@ -339,7 +351,9 @@ class Controller: ) self._refresh_current_chat(current_chat_id) - def _refresh_current_chat(self, current_chat_id: int): + def _refresh_current_chat(self, current_chat_id: Optional[int]): + if current_chat_id is None: + return # TODO: we can create for chats, it's faster than sqlite anyway # though need to make sure that creatinng index is atomic operation # requires locks for read, until index and chats will be the same From 2fe6a83190a01f228d81f04206b089a7d2ef8042 Mon Sep 17 00:00:00 2001 From: Alexander Zveruk Date: Sat, 16 May 2020 00:16:38 +0300 Subject: [PATCH 4/7] process updateChatTitle --- tg/controllers/__init__.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tg/controllers/__init__.py b/tg/controllers/__init__.py index 95a58be..2afca63 100644 --- a/tg/controllers/__init__.py +++ b/tg/controllers/__init__.py @@ -42,6 +42,7 @@ class Controller: self.handlers = { "updateNewMessage": self.update_new_msg, "updateChatIsPinned": self.update_chat_is_pinned, + "updateChatTitle": self.update_chat_title, "updateChatLastMessage": self.update_chat_last_msg, "updateChatDraftMessage": self.update_chat_draft_msg, "updateChatOrder": self.update_chat_order, @@ -318,6 +319,16 @@ class Controller: self.model.chats.update_chat(chat_id, order=order) self._refresh_current_chat(current_chat_id) + @handle_exception + def update_chat_title(self, update: Dict[str, Any]): + log.info("Proccessing updateChatTitle") + chat_id = update["chat_id"] + title = update["title"] + current_chat_id = self.model.chats.id_by_index(self.model.current_chat) + self.model.chats.update_chat(chat_id, title=title) + self._refresh_current_chat(current_chat_id) + + @handle_exception def update_chat_is_pinned(self, update: Dict[str, Any]): log.info("Proccessing updateChatIsPinned") From c3f09546d6df8201a61a30d72d50bb68abc8460c Mon Sep 17 00:00:00 2001 From: Alexander Zveruk Date: Sat, 16 May 2020 00:22:59 +0300 Subject: [PATCH 5/7] process updateChatReadInbox --- tg/controllers/__init__.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/tg/controllers/__init__.py b/tg/controllers/__init__.py index 2afca63..981b060 100644 --- a/tg/controllers/__init__.py +++ b/tg/controllers/__init__.py @@ -42,6 +42,7 @@ class Controller: self.handlers = { "updateNewMessage": self.update_new_msg, "updateChatIsPinned": self.update_chat_is_pinned, + "updateChatReadInbox": self.update_chat_read_inbox, "updateChatTitle": self.update_chat_title, "updateChatLastMessage": self.update_chat_last_msg, "updateChatDraftMessage": self.update_chat_draft_msg, @@ -328,7 +329,6 @@ class Controller: self.model.chats.update_chat(chat_id, title=title) self._refresh_current_chat(current_chat_id) - @handle_exception def update_chat_is_pinned(self, update: Dict[str, Any]): log.info("Proccessing updateChatIsPinned") @@ -339,9 +339,23 @@ class Controller: self.model.chats.update_chat(chat_id, is_pinned=is_pinned, order=order) self._refresh_current_chat(current_chat_id) + @handle_exception + def update_chat_read_inbox(self, update: Dict[str, Any]): + log.info("Proccessing updateChatReadInbox") + chat_id = update["chat_id"] + last_read_inbox_message_id = update["last_read_inbox_message_id"] + unread_count = update["unread_count"] + current_chat_id = self.model.chats.id_by_index(self.model.current_chat) + self.model.chats.update_chat( + chat_id, + last_read_inbox_message_id=last_read_inbox_message_id, + unread_count=unread_count, + ) + self._refresh_current_chat(current_chat_id) + @handle_exception def update_chat_draft_msg(self, update: Dict[str, Any]): - log.info("Proccessing updateChatLastMessage") + log.info("Proccessing updateChatDraftMessage") chat_id = update["chat_id"] # FIXME: ignoring draft message itself for now because UI can't show it # draft_message = update["draft_message"] From 4a719af0037aff37feb86014f0c3410718ce3b64 Mon Sep 17 00:00:00 2001 From: Alexander Zveruk Date: Sat, 16 May 2020 00:32:01 +0300 Subject: [PATCH 6/7] updateChatIsMarkedAsUnread --- tg/controllers/__init__.py | 12 ++++++++++++ tg/views/__init__.py | 12 ++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/tg/controllers/__init__.py b/tg/controllers/__init__.py index 981b060..b194c80 100644 --- a/tg/controllers/__init__.py +++ b/tg/controllers/__init__.py @@ -42,6 +42,7 @@ class Controller: self.handlers = { "updateNewMessage": self.update_new_msg, "updateChatIsPinned": self.update_chat_is_pinned, + "updateChatIsMarkedAsUnread": self.update_chat_marked_as_unread, "updateChatReadInbox": self.update_chat_read_inbox, "updateChatTitle": self.update_chat_title, "updateChatLastMessage": self.update_chat_last_msg, @@ -329,6 +330,17 @@ class Controller: self.model.chats.update_chat(chat_id, title=title) self._refresh_current_chat(current_chat_id) + @handle_exception + def update_chat_marked_as_unread(self, update: Dict[str, Any]): + log.info("Proccessing updateChatIsMarkedAsUnread") + chat_id = update["chat_id"] + is_marked_as_unread = update["is_marked_as_unread"] + current_chat_id = self.model.chats.id_by_index(self.model.current_chat) + self.model.chats.update_chat( + chat_id, is_marked_as_unread=is_marked_as_unread + ) + self._refresh_current_chat(current_chat_id) + @handle_exception def update_chat_is_pinned(self, update: Dict[str, Any]): log.info("Proccessing updateChatIsPinned") diff --git a/tg/views/__init__.py b/tg/views/__init__.py index 65356d8..afdf2c2 100644 --- a/tg/views/__init__.py +++ b/tg/views/__init__.py @@ -145,13 +145,13 @@ class ChatView: self.win.vline(0, self.w - 1, curses.ACS_VLINE, self.h) for i, chat in enumerate(chats): is_selected = i == current - date, title, unread_count, is_pinned, last_msg = ( - get_date(chat), - chat["title"], - chat["unread_count"], - chat["is_pinned"], - get_last_msg(chat), + unread_count = ( + chat["unread_count"] or 1 if chat["is_marked_as_unread"] else 0 ) + date = get_date(chat) + title = chat["title"] + is_pinned = chat["is_pinned"] + last_msg = get_last_msg(chat) offset = 0 for attr, elem in zip( self._msg_attribures(is_selected), [f"{date} ", title] From f8e53ac6c18fbe0ca0bbc52797c8f773d6152e87 Mon Sep 17 00:00:00 2001 From: Alexander Zveruk Date: Sat, 16 May 2020 00:53:53 +0300 Subject: [PATCH 7/7] processing updateMessageContent --- tg/controllers/__init__.py | 14 ++++++++++++++ tg/models/__init__.py | 10 ++++++++++ 2 files changed, 24 insertions(+) diff --git a/tg/controllers/__init__.py b/tg/controllers/__init__.py index b194c80..fbe1a21 100644 --- a/tg/controllers/__init__.py +++ b/tg/controllers/__init__.py @@ -41,6 +41,7 @@ class Controller: self.tg = tg self.handlers = { "updateNewMessage": self.update_new_msg, + "updateMessageContent": self.update_msg_content, "updateChatIsPinned": self.update_chat_is_pinned, "updateChatIsMarkedAsUnread": self.update_chat_marked_as_unread, "updateChatReadInbox": self.update_chat_read_inbox, @@ -271,6 +272,16 @@ class Controller: msgs = self.model.fetch_msgs(limit=self.view.msgs.h) self.view.msgs.draw(self.model.get_current_chat_msg(), msgs) + @handle_exception + def update_msg_content(self, update): + content = MsgProxy(update["new_content"]) + chat_id = update["chat_id"] + message_id = update["message_id"] + self.model.msgs.update_msg_content(chat_id, message_id, content) + current_chat_id = self.model.chats.id_by_index(self.model.current_chat) + if current_chat_id == chat_id: + self.refresh_msgs() + @handle_exception def update_new_msg(self, update): msg = MsgProxy(update["message"]) @@ -282,6 +293,9 @@ class Controller: if msg.file_id and msg.size <= config.max_download_size: self.download(msg.file_id, chat_id, msg["id"]) + self._notify_for_message(chat_id, msg) + + def _notify_for_message(self, chat_id: int, msg: Dict[str, Any]): # do not notify, if muted # TODO: optimize chat = None diff --git a/tg/models/__init__.py b/tg/models/__init__.py index 63d0dc3..fcda39b 100644 --- a/tg/models/__init__.py +++ b/tg/models/__init__.py @@ -223,6 +223,16 @@ class MsgModel: msg_set.remove(msg_id) return True + def update_msg_content( + self, chat_id: int, msg_id: int, message_content: Dict[str, Any] + ) -> bool: + log.info(f"updating {msg_id=} {message_content=}") + for msg in self.msgs[chat_id]: + if msg["id"] != msg_id: + continue + msg["content"] = message_content + return True + def add_message(self, chat_id: int, message: Dict[str, Any]) -> bool: msg_id = message["id"] msg_set = self.msg_ids[chat_id]