mirror of
https://github.com/paul-nameless/tg
synced 2024-11-26 05:40:17 +00:00
Merge branch 'master' into quick-fix-notification
This commit is contained in:
commit
f17a42bad2
3 changed files with 143 additions and 39 deletions
|
@ -1,9 +1,9 @@
|
|||
import logging
|
||||
from typing import Dict, Any, Optional
|
||||
import os
|
||||
import threading
|
||||
from datetime import datetime
|
||||
from tempfile import NamedTemporaryFile
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from telegram.client import Telegram
|
||||
|
||||
|
@ -47,17 +47,18 @@ class Controller:
|
|||
self.lock = threading.Lock()
|
||||
self.tg = tg
|
||||
self.handlers = {
|
||||
"updateNewMessage": self.update_new_msg,
|
||||
"updateMessageContent": self.update_msg_content,
|
||||
"updateChatIsPinned": self.update_chat_is_pinned,
|
||||
"updateChatDraftMessage": self.update_chat_draft_msg,
|
||||
"updateChatIsMarkedAsUnread": self.update_chat_marked_as_unread,
|
||||
"updateChatIsPinned": self.update_chat_is_pinned,
|
||||
"updateChatLastMessage": self.update_chat_last_msg,
|
||||
"updateChatNotificationSettings": self.update_chat_notification_settings,
|
||||
"updateChatOrder": self.update_chat_order,
|
||||
"updateChatReadInbox": self.update_chat_read_inbox,
|
||||
"updateChatTitle": self.update_chat_title,
|
||||
"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,
|
||||
"updateMessageContent": self.update_msg_content,
|
||||
"updateMessageSendSucceeded": self.update_msg_send_succeeded,
|
||||
"updateNewMessage": self.update_new_msg,
|
||||
}
|
||||
|
||||
def send_file(self, send_file_fun, *args, **kwargs):
|
||||
|
@ -258,6 +259,39 @@ class Controller:
|
|||
with suspend(self.view):
|
||||
breakpoint()
|
||||
|
||||
elif keys == "u":
|
||||
chat = self.model.chats.chats[self.model.current_chat]
|
||||
chat_id = chat["id"]
|
||||
toggle = not chat["is_marked_as_unread"]
|
||||
self.tg.toggle_chat_is_marked_as_unread(chat_id, toggle)
|
||||
|
||||
elif keys == "p":
|
||||
chat = self.model.chats.chats[self.model.current_chat]
|
||||
chat_id = chat["id"]
|
||||
toggle = not chat["is_pinned"]
|
||||
self.tg.toggle_chat_is_pinned(chat_id, toggle)
|
||||
|
||||
elif keys == "r":
|
||||
chat = self.model.chats.chats[self.model.current_chat]
|
||||
chat_id = chat["id"]
|
||||
msg_id = chat["last_message"]["id"]
|
||||
self.tg.view_messages(chat_id, [msg_id])
|
||||
|
||||
elif keys == "m":
|
||||
# TODO: if it's msg to yourself, do not change its
|
||||
# notification setting, because we can't by documentation,
|
||||
# instead write about it in status
|
||||
chat = self.model.chats.chats[self.model.current_chat]
|
||||
chat_id = chat["id"]
|
||||
notification_settings = chat["notification_settings"]
|
||||
if notification_settings["mute_for"]:
|
||||
notification_settings["mute_for"] = 0
|
||||
else:
|
||||
notification_settings["mute_for"] = 2147483647
|
||||
self.tg.set_chat_nottification_settings(
|
||||
chat_id, notification_settings
|
||||
)
|
||||
|
||||
def refresh_chats(self) -> None:
|
||||
with self.lock:
|
||||
# using lock here, because refresh_chats is used from another
|
||||
|
@ -424,6 +458,16 @@ class Controller:
|
|||
break
|
||||
self.refresh_chats()
|
||||
|
||||
@handle_exception
|
||||
def update_chat_notification_settings(self, update):
|
||||
log.info("Proccessing update_chat_notification_settings")
|
||||
chat_id = update["chat_id"]
|
||||
notification_settings = update["notification_settings"]
|
||||
self.model.chats.update_chat(
|
||||
chat_id, notification_settings=notification_settings
|
||||
)
|
||||
self.refresh_chats()
|
||||
|
||||
@handle_exception
|
||||
def update_msg_send_succeeded(self, update):
|
||||
chat_id = update["message"]["chat_id"]
|
||||
|
|
40
tg/main.py
40
tg/main.py
|
@ -106,6 +106,45 @@ class TelegramApi(Telegram):
|
|||
}
|
||||
return self._send_data(data)
|
||||
|
||||
def toggle_chat_is_marked_as_unread(
|
||||
self, chat_id: int, is_marked_as_unread: bool
|
||||
):
|
||||
data = {
|
||||
"@type": "toggleChatIsMarkedAsUnread",
|
||||
"chat_id": chat_id,
|
||||
"is_marked_as_unread": is_marked_as_unread,
|
||||
}
|
||||
return self._send_data(data)
|
||||
|
||||
def toggle_chat_is_pinned(self, chat_id: int, is_pinned: bool):
|
||||
data = {
|
||||
"@type": "toggleChatIsPinned",
|
||||
"chat_id": chat_id,
|
||||
"is_pinned": is_pinned,
|
||||
}
|
||||
return self._send_data(data)
|
||||
|
||||
def set_chat_nottification_settings(
|
||||
self, chat_id: int, notification_settings: dict
|
||||
):
|
||||
data = {
|
||||
"@type": "setChatNotificationSettings",
|
||||
"chat_id": chat_id,
|
||||
"notification_settings": notification_settings,
|
||||
}
|
||||
return self._send_data(data)
|
||||
|
||||
def view_messages(
|
||||
self, chat_id: int, message_ids: list, force_read: bool = True
|
||||
):
|
||||
data = {
|
||||
"@type": "viewMessages",
|
||||
"chat_id": chat_id,
|
||||
"message_ids": message_ids,
|
||||
"force_read": force_read,
|
||||
}
|
||||
return self._send_data(data)
|
||||
|
||||
|
||||
def main():
|
||||
def signal_handler(sig, frame):
|
||||
|
@ -130,6 +169,7 @@ def main():
|
|||
)
|
||||
config.record_cmd = cfg.get("record_cmd")
|
||||
tg.login()
|
||||
|
||||
wrapper(partial(run, tg))
|
||||
|
||||
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import curses
|
||||
import logging
|
||||
import re
|
||||
from _curses import window
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, List, Optional, Tuple, Iterator
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
from tg.colors import blue, cyan, get_color, magenta, reverse, white
|
||||
from tg.msg import MsgProxy
|
||||
from tg.utils import num, truncate_to_len, emoji_pattern
|
||||
from tg.utils import emoji_pattern, num, truncate_to_len
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -25,13 +24,14 @@ MULTICHAR_KEYBINDINGS = (
|
|||
|
||||
class View:
|
||||
def __init__(self, stdscr: window) -> None:
|
||||
curses.start_color()
|
||||
curses.noecho()
|
||||
curses.cbreak()
|
||||
stdscr.keypad(True)
|
||||
curses.curs_set(0)
|
||||
curses.start_color()
|
||||
curses.use_default_colors()
|
||||
# init white color first to initialize colors correctly
|
||||
get_color(white, -1)
|
||||
|
||||
self.stdscr = stdscr
|
||||
self.chats = ChatView(stdscr)
|
||||
|
@ -129,32 +129,43 @@ class ChatView:
|
|||
self.win.resize(self.h, self.w)
|
||||
|
||||
def _msg_color(self, is_selected: bool = False) -> int:
|
||||
return get_color(white, -1) | (reverse if is_selected else 0)
|
||||
color = get_color(white, -1)
|
||||
if is_selected:
|
||||
return color | reverse
|
||||
return color
|
||||
|
||||
def _unread_color(self, is_selected: bool = False) -> int:
|
||||
return get_color(magenta, -1) | (reverse if is_selected else 0)
|
||||
color = get_color(magenta, -1)
|
||||
if is_selected:
|
||||
return color | reverse
|
||||
return color
|
||||
|
||||
def _msg_attribures(self, is_selected: bool = False) -> List[int]:
|
||||
return map(
|
||||
lambda x: x | (reverse if is_selected else 0),
|
||||
[get_color(cyan, -1), get_color(blue, -1), self._msg_color(),],
|
||||
def _chat_attributes(self, is_selected: bool = False) -> Tuple[int]:
|
||||
attrs = (
|
||||
get_color(cyan, -1),
|
||||
get_color(blue, -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]]) -> None:
|
||||
self.win.erase()
|
||||
self.win.vline(0, self.w - 1, curses.ACS_VLINE, self.h)
|
||||
for i, chat in enumerate(chats):
|
||||
is_selected = i == current
|
||||
unread_count = (
|
||||
chat["unread_count"] or 1 if chat["is_marked_as_unread"] else 0
|
||||
)
|
||||
unread_count = chat["unread_count"]
|
||||
if chat["is_marked_as_unread"]:
|
||||
unread_count = "unread"
|
||||
|
||||
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]
|
||||
self._chat_attributes(is_selected), [f"{date} ", title]
|
||||
):
|
||||
if offset > self.w:
|
||||
break
|
||||
|
@ -167,12 +178,14 @@ class ChatView:
|
|||
offset += len(elem)
|
||||
|
||||
if offset >= self.w:
|
||||
continue
|
||||
break
|
||||
|
||||
last_msg = " " + last_msg.replace("\n", " ")
|
||||
last_msg = truncate_to_len(last_msg, self.w - offset - 1)
|
||||
|
||||
self.win.addstr(i, offset, last_msg, self._msg_color(is_selected))
|
||||
last_msg = truncate_to_len(last_msg, self.w - offset)
|
||||
if last_msg.strip():
|
||||
self.win.addstr(
|
||||
i, offset, last_msg, self._msg_color(is_selected)
|
||||
)
|
||||
|
||||
if left_label := self._get_chat_label(
|
||||
unread_count, is_pinned, chat
|
||||
|
@ -190,16 +203,20 @@ class ChatView:
|
|||
def _get_chat_label(
|
||||
unread_count: int, is_pinned: bool, chat: Dict[str, Any]
|
||||
) -> str:
|
||||
label = ""
|
||||
labels = []
|
||||
if is_pinned:
|
||||
label += "pinned "
|
||||
if unread_count:
|
||||
label += f"{unread_count} "
|
||||
labels.append("pinned")
|
||||
|
||||
if chat["notification_settings"]["mute_for"]:
|
||||
label = f"muted {label}"
|
||||
labels.append("muted")
|
||||
|
||||
return f" {label}"
|
||||
if unread_count:
|
||||
labels.append(str(unread_count))
|
||||
|
||||
label = " ".join(labels)
|
||||
if label:
|
||||
return f" {label}"
|
||||
return label
|
||||
|
||||
|
||||
class MsgView:
|
||||
|
@ -247,7 +264,8 @@ class MsgView:
|
|||
# count wide character utf-8 symbols that take > 1 bytes to
|
||||
# print it causes invalid offset
|
||||
wide_char_len = sum(map(len, emoji_pattern.findall(msg)))
|
||||
elements = tuple(map(lambda x: f" {x}", (dt, user_id, msg)))
|
||||
elements = (f" {dt} ", user_id, " " + msg)
|
||||
# elements = tuple(map(lambda x: f" {x}", (dt, user_id, msg)))
|
||||
total_len = sum(len(e) for e in elements) + wide_char_len
|
||||
|
||||
needed_lines = (total_len // self.w) + 1
|
||||
|
@ -283,7 +301,7 @@ class MsgView:
|
|||
|
||||
for elements, selected, line_num in msgs_to_draw:
|
||||
column = 0
|
||||
for attr, elem in zip(self._msg_attribures(selected), elements):
|
||||
for attr, elem in zip(self._msg_attributes(selected), elements):
|
||||
if not elem:
|
||||
continue
|
||||
self.win.addstr(line_num, column, elem, attr)
|
||||
|
@ -291,14 +309,16 @@ class MsgView:
|
|||
|
||||
self._refresh()
|
||||
|
||||
@staticmethod
|
||||
def _msg_attribures(is_selected: bool) -> Iterator[int]:
|
||||
attrs = [
|
||||
def _msg_attributes(self, is_selected: bool) -> Tuple[int]:
|
||||
attrs = (
|
||||
get_color(cyan, -1),
|
||||
get_color(blue, -1),
|
||||
get_color(white, -1),
|
||||
]
|
||||
return map(lambda x: x | reverse if is_selected else 0, attrs)
|
||||
)
|
||||
|
||||
if is_selected:
|
||||
return (attr | reverse for attr in attrs)
|
||||
return attrs
|
||||
|
||||
def _get_user_by_id(self, user_id: int) -> str:
|
||||
if user_id == 0:
|
||||
|
|
Loading…
Reference in a new issue