def _get_last_msg_data( self, chat: Dict[str, Any]) -> Tuple[Optional[str], Optional[str]]: user, last_msg = get_last_msg(chat, self.model.users) if user: last_msg_sender = self.model.users.get_user_label(user) chat_type = get_chat_type(chat) if chat_type and is_group(chat_type): return last_msg_sender, last_msg return None, last_msg
def _get_action_label(users: UserModel, chat: Dict[str, Any]) -> Optional[str]: actioner, action = users.get_user_action(chat["id"]) if actioner and action: label = f"{action}..." chat_type = get_chat_type(chat) if chat_type and is_group(chat_type): user_label = users.get_user_label(actioner) label = f"{user_label} {label}" return label return None
def get_chat_info(self, chat: Dict[str, Any]) -> Dict[str, Any]: chat_type = get_chat_type(chat) if chat_type is None: return {} handlers = { ChatType.chatTypePrivate: self.get_private_chat_info, ChatType.chatTypeBasicGroup: self.get_basic_group_info, ChatType.chatTypeSupergroup: self.get_supergroup_info, ChatType.channel: self.get_channel_info, ChatType.chatTypeSecret: self.get_secret_chat_info, } info = handlers.get(chat_type, lambda _: dict())(chat) info.update({"Type": chat_type.value, "Chat Id": chat["id"]}) return info
def delete_chat(self) -> None: """Leave group/channel or delete private/secret chats""" chat = self.model.chats.chats[self.model.current_chat] chat_type = get_chat_type(chat) if chat_type in ( ChatType.chatTypeSupergroup, ChatType.chatTypeBasicGroup, ChatType.channel, ): resp = self.view.status.get_input( "Are you sure you want to leave this group/channel?[y/N]" ) if is_no(resp or ""): return self.present_info("Not leaving group/channel") self.tg.leave_chat(chat["id"]) self.tg.delete_chat_history( chat["id"], remove_from_chat_list=True, revoke=False ) return resp = self.view.status.get_input( "Are you sure you want to delete the chat?[y/N]" ) if is_no(resp or ""): return self.present_info("Not deleting chat") is_revoke = False if chat["can_be_deleted_for_all_users"]: resp = self.view.status.get_input("Delete for all users?[y/N]") if resp is None: return self.present_info("Not deleting chat") self.render_status() is_revoke = is_no(resp) self.tg.delete_chat_history( chat["id"], remove_from_chat_list=True, revoke=is_revoke ) if chat_type == ChatType.chatTypeSecret: self.tg.close_secret_chat(chat["type"]["secret_chat_id"]) self.present_info("Chat was deleted")
def _msg_title(self, chat: Dict[str, Any]) -> str: chat_type = get_chat_type(chat) status = "" if action_label := _get_action_label(self.model.users, chat): status = action_label
class ChatView: def __init__(self, stdscr: window, model: Model) -> None: self.stdscr = stdscr self.h = 0 self.w = 0 self.win = stdscr.subwin(self.h, self.w, 0, 0) self._refresh = self.win.refresh self.model = model def resize(self, rows: int, cols: int, width: int) -> None: self.h = rows - 1 self.w = width self.win.resize(self.h, self.w) def _msg_color(self, is_selected: bool = False) -> int: color = get_color(white, -1) if is_selected: return color | reverse return color def _unread_color(self, is_selected: bool = False) -> int: color = get_color(magenta, -1) if is_selected: return color | reverse return color def _chat_attributes(self, is_selected: bool, title: str, user: Optional[str]) -> Tuple[int, ...]: attrs = ( get_color(cyan, -1), get_color(get_color_by_str(title), -1), get_color(get_color_by_str(user or ""), -1), self._msg_color(is_selected), ) if is_selected: return tuple(attr | reverse for attr in attrs) return attrs def draw(self, current: int, chats: List[Dict[str, Any]], title: str = "Chats") -> None: self.win.erase() line = curses.ACS_VLINE # type: ignore width = self.w - 1 self.win.vline(0, width, line, self.h) self.win.addstr(0, 0, title.center(width)[:width], get_color(cyan, -1) | bold) for i, chat in enumerate(chats, 1): is_selected = i == current + 1 date = get_date(chat) title = chat["title"] offset = 0 last_msg_sender, last_msg = self._get_last_msg_data(chat) sender_label = f" {last_msg_sender}" if last_msg_sender else "" flags = self._get_flags(chat) flags_len = string_len_dwc(flags) if flags: self.win.addstr( i, max(0, width - flags_len), truncate_to_len(flags, width)[-width:], # flags[-width:], self._unread_color(is_selected), ) for attr, elem in zip( self._chat_attributes(is_selected, title, last_msg_sender), [f"{date} ", title, sender_label, f" {last_msg}"], ): if not elem: continue item = truncate_to_len(elem, max(0, width - offset - flags_len)) if len(item) > 1: self.win.addstr(i, offset, item, attr) offset += string_len_dwc(elem) self._refresh() def _get_last_msg_data( self, chat: Dict[str, Any]) -> Tuple[Optional[str], Optional[str]]: user, last_msg = get_last_msg(chat, self.model.users) if user: last_msg_sender = self.model.users.get_user_label(user) chat_type = get_chat_type(chat) if chat_type and is_group(chat_type): return last_msg_sender, last_msg return None, last_msg def _get_flags(self, chat: Dict[str, Any]) -> str: flags = [] msg = chat.get("last_message") if (msg and self.model.is_me(msg["sender"].get("user_id")) and msg["id"] > chat["last_read_outbox_message_id"] and not self.model.is_me(chat["id"])): # last msg haven't been seen by recipient flags.append("unseen") elif (msg and self.model.is_me(msg["sender"].get("user_id")) and msg["id"] <= chat["last_read_outbox_message_id"]): flags.append("seen") if action_label := _get_action_label(self.model.users, chat): flags.append(action_label) if self.model.users.is_online(chat["id"]): flags.append("online") if "is_pinned" in chat and chat["is_pinned"]: flags.append("pinned") if chat["notification_settings"]["mute_for"]: flags.append("muted") if chat["is_marked_as_unread"]: flags.append("unread") elif chat["unread_count"]: flags.append(str(chat["unread_count"])) if get_chat_type(chat) == ChatType.chatTypeSecret: flags.append("secret") label = " ".join(config.CHAT_FLAGS.get(flag, flag) for flag in flags) if label: return f" {label}" return label
if self.model.users.is_online(chat["id"]): flags.append("online") if chat["is_pinned"]: flags.append("pinned") if chat["notification_settings"]["mute_for"]: flags.append("muted") if chat["is_marked_as_unread"]: flags.append("unread") elif chat["unread_count"]: flags.append(str(chat["unread_count"])) if get_chat_type(chat) == ChatType.chatTypeSecret: flags.append("secret") label = " ".join(config.CHAT_FLAGS.get(flag, flag) for flag in flags) if label: return f" {label}" return label class MsgView: def __init__( self, stdscr: window, model: Model, ) -> None: self.model = model