mirror of
https://github.com/paul-nameless/tg
synced 2024-11-22 11:53:08 +00:00
Merge branch 'master' into edit-msg
This commit is contained in:
commit
36d5d8a1e3
5 changed files with 101 additions and 20 deletions
|
@ -61,6 +61,7 @@ class Controller:
|
|||
"updateMessageContent": self.update_msg_content,
|
||||
"updateMessageSendSucceeded": self.update_msg_send_succeeded,
|
||||
"updateNewMessage": self.update_new_msg,
|
||||
"updateMessageContentOpened": self.update_message_content_opened,
|
||||
}
|
||||
self.chat_size = 0.5
|
||||
signal(SIGWINCH, self.resize_handler)
|
||||
|
@ -107,7 +108,6 @@ class Controller:
|
|||
|
||||
def open_current_msg(self):
|
||||
msg = MsgProxy(self.model.current_msg)
|
||||
log.info("Open msg: %s", msg.msg)
|
||||
if msg.is_text:
|
||||
with NamedTemporaryFile("w", suffix=".txt") as f:
|
||||
f.write(msg.text_content)
|
||||
|
@ -118,8 +118,9 @@ class Controller:
|
|||
|
||||
path = msg.local_path
|
||||
if path:
|
||||
chat_id = self.model.chats.id_by_index(self.model.current_chat)
|
||||
self.tg.open_message_content(chat_id, msg.msg_id)
|
||||
with suspend(self.view) as s:
|
||||
log.info("Opening file: %s", path)
|
||||
s.open_file(path)
|
||||
|
||||
def present_error(self, msg: str):
|
||||
|
@ -553,3 +554,10 @@ class Controller:
|
|||
if proxy.is_downloaded:
|
||||
self.model.downloads.pop(file_id)
|
||||
break
|
||||
|
||||
@handle_exception
|
||||
def update_message_content_opened(self, update: Dict[str, Any]):
|
||||
chat_id = update["chat_id"]
|
||||
message_id = update["message_id"]
|
||||
self.model.msgs.update_msg_content_opened(chat_id, message_id)
|
||||
self.refresh_msgs()
|
||||
|
|
39
tg/main.py
39
tg/main.py
|
@ -5,7 +5,7 @@ import threading
|
|||
from curses import window, wrapper # type: ignore
|
||||
from functools import partial
|
||||
|
||||
from telegram.client import Telegram
|
||||
from telegram.client import AsyncResult, Telegram
|
||||
|
||||
from tg import config, utils
|
||||
from tg.controllers import Controller
|
||||
|
@ -48,7 +48,7 @@ class TelegramApi(Telegram):
|
|||
)
|
||||
result.wait()
|
||||
|
||||
def send_doc(self, file_path, chat_id):
|
||||
def send_doc(self, file_path: str, chat_id: int) -> AsyncResult:
|
||||
data = {
|
||||
"@type": "sendMessage",
|
||||
"chat_id": chat_id,
|
||||
|
@ -59,7 +59,7 @@ class TelegramApi(Telegram):
|
|||
}
|
||||
return self._send_data(data)
|
||||
|
||||
def send_audio(self, file_path, chat_id):
|
||||
def send_audio(self, file_path: str, chat_id: int) -> AsyncResult:
|
||||
data = {
|
||||
"@type": "sendMessage",
|
||||
"chat_id": chat_id,
|
||||
|
@ -70,7 +70,7 @@ class TelegramApi(Telegram):
|
|||
}
|
||||
return self._send_data(data)
|
||||
|
||||
def send_photo(self, file_path, chat_id):
|
||||
def send_photo(self, file_path: str, chat_id: int) -> AsyncResult:
|
||||
data = {
|
||||
"@type": "sendMessage",
|
||||
"chat_id": chat_id,
|
||||
|
@ -81,7 +81,14 @@ class TelegramApi(Telegram):
|
|||
}
|
||||
return self._send_data(data)
|
||||
|
||||
def send_video(self, file_path, chat_id, width, height, duration):
|
||||
def send_video(
|
||||
self,
|
||||
file_path: str,
|
||||
chat_id: int,
|
||||
width: int,
|
||||
height: int,
|
||||
duration: int,
|
||||
) -> AsyncResult:
|
||||
data = {
|
||||
"@type": "sendMessage",
|
||||
"chat_id": chat_id,
|
||||
|
@ -95,7 +102,9 @@ class TelegramApi(Telegram):
|
|||
}
|
||||
return self._send_data(data)
|
||||
|
||||
def send_voice(self, file_path, chat_id, duration, waveform):
|
||||
def send_voice(
|
||||
self, file_path: str, chat_id: int, duration: int, waveform: int
|
||||
):
|
||||
data = {
|
||||
"@type": "sendMessage",
|
||||
"chat_id": chat_id,
|
||||
|
@ -122,7 +131,7 @@ class TelegramApi(Telegram):
|
|||
|
||||
def toggle_chat_is_marked_as_unread(
|
||||
self, chat_id: int, is_marked_as_unread: bool
|
||||
):
|
||||
) -> AsyncResult:
|
||||
data = {
|
||||
"@type": "toggleChatIsMarkedAsUnread",
|
||||
"chat_id": chat_id,
|
||||
|
@ -130,7 +139,9 @@ class TelegramApi(Telegram):
|
|||
}
|
||||
return self._send_data(data)
|
||||
|
||||
def toggle_chat_is_pinned(self, chat_id: int, is_pinned: bool):
|
||||
def toggle_chat_is_pinned(
|
||||
self, chat_id: int, is_pinned: bool
|
||||
) -> AsyncResult:
|
||||
data = {
|
||||
"@type": "toggleChatIsPinned",
|
||||
"chat_id": chat_id,
|
||||
|
@ -150,7 +161,7 @@ class TelegramApi(Telegram):
|
|||
|
||||
def view_messages(
|
||||
self, chat_id: int, message_ids: list, force_read: bool = True
|
||||
):
|
||||
) -> AsyncResult:
|
||||
data = {
|
||||
"@type": "viewMessages",
|
||||
"chat_id": chat_id,
|
||||
|
@ -159,6 +170,16 @@ class TelegramApi(Telegram):
|
|||
}
|
||||
return self._send_data(data)
|
||||
|
||||
def open_message_content(
|
||||
self, chat_id: int, message_id: int
|
||||
) -> AsyncResult:
|
||||
data = {
|
||||
"@type": "openMessageContent",
|
||||
"chat_id": chat_id,
|
||||
"message_id": message_id,
|
||||
}
|
||||
return self._send_data(data)
|
||||
|
||||
|
||||
def main():
|
||||
def signal_handler(sig, frame):
|
||||
|
|
|
@ -4,6 +4,8 @@ from typing import Any, Dict, List, Optional, Set, Tuple
|
|||
|
||||
from telegram.client import Telegram
|
||||
|
||||
from tg.msg import MsgProxy
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
@ -262,7 +264,22 @@ class MsgModel:
|
|||
if msg["id"] != msg_id:
|
||||
continue
|
||||
msg["content"] = message_content
|
||||
return True
|
||||
return True
|
||||
return False
|
||||
|
||||
def update_msg_content_opened(self, chat_id: int, msg_id: int):
|
||||
for message in self.msgs[chat_id]:
|
||||
if message["id"] != msg_id:
|
||||
continue
|
||||
msg = MsgProxy(message)
|
||||
if msg.type == "voice":
|
||||
msg.is_listened = True
|
||||
elif msg.type == "recording":
|
||||
msg.is_viewed = True
|
||||
# TODO: start the TTL timer for self-destructing messages
|
||||
# that is the last case to implement
|
||||
# https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1update_message_content_opened.html
|
||||
return
|
||||
|
||||
def add_message(self, chat_id: int, message: Dict[str, Any]) -> bool:
|
||||
msg_id = message["id"]
|
||||
|
|
36
tg/msg.py
36
tg/msg.py
|
@ -1,6 +1,6 @@
|
|||
import logging
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from tg import utils
|
||||
|
||||
|
@ -58,8 +58,8 @@ class MsgProxy:
|
|||
self.msg[key] = value
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return self.msg["@type"]
|
||||
def type(self) -> Optional[str]:
|
||||
return self.msg.get("@type")
|
||||
|
||||
@property
|
||||
def date(self) -> datetime:
|
||||
|
@ -145,7 +145,35 @@ class MsgProxy:
|
|||
return doc["local"]["is_downloading_completed"]
|
||||
|
||||
@property
|
||||
def reply_msg_id(self):
|
||||
def is_listened(self) -> Optional[bool]:
|
||||
if self.type != "voice":
|
||||
return None
|
||||
return self.msg["content"]["is_listened"]
|
||||
|
||||
@is_listened.setter
|
||||
def is_listened(self, value: bool):
|
||||
if self.type != "voice":
|
||||
return None
|
||||
self.msg["content"]["is_listened"] = value
|
||||
|
||||
@property
|
||||
def is_viewed(self) -> Optional[bool]:
|
||||
if self.type != "recording":
|
||||
return None
|
||||
return self.msg["content"]["is_viewed"]
|
||||
|
||||
@is_viewed.setter
|
||||
def is_viewed(self, value: bool):
|
||||
if self.type != "recording":
|
||||
return None
|
||||
self.msg["content"]["is_viewed"] = value
|
||||
|
||||
@property
|
||||
def msg_id(self) -> int:
|
||||
return self.msg["id"]
|
||||
|
||||
@property
|
||||
def reply_msg_id(self) -> Optional[int]:
|
||||
return self.msg.get("reply_to_message_id")
|
||||
|
||||
@property
|
||||
|
|
|
@ -5,8 +5,7 @@ from datetime import datetime
|
|||
from typing import Any, Dict, List, Optional, Tuple, cast
|
||||
|
||||
from tg.colors import blue, cyan, get_color, magenta, reverse, white
|
||||
from tg.models import MsgModel
|
||||
from tg.models import UserModel
|
||||
from tg.models import MsgModel, UserModel
|
||||
from tg.msg import MsgProxy
|
||||
from tg.utils import emoji_pattern, num, truncate_to_len
|
||||
|
||||
|
@ -420,15 +419,23 @@ def parse_content(content: Dict[str, Any]) -> str:
|
|||
|
||||
fields = dict(
|
||||
name=msg.file_name,
|
||||
duration=msg.duration,
|
||||
size=msg.human_size,
|
||||
download=get_download(msg.local, msg.size),
|
||||
size=msg.human_size,
|
||||
duration=msg.duration,
|
||||
listened=format_bool(msg.is_listened),
|
||||
viewed=format_bool(msg.is_viewed),
|
||||
)
|
||||
info = ", ".join(f"{k}={v}" for k, v in fields.items() if v)
|
||||
|
||||
return f"[{msg.content_type}: {info}]"
|
||||
|
||||
|
||||
def format_bool(value: Optional[bool]) -> Optional[str]:
|
||||
if value is None:
|
||||
return None
|
||||
return "yes" if value else "no"
|
||||
|
||||
|
||||
def get_download(local, size):
|
||||
if local["is_downloading_completed"]:
|
||||
return "yes"
|
||||
|
|
Loading…
Reference in a new issue