Add ability to delete chat (#145)

* Add ability to delete chat

* Leave chat
This commit is contained in:
Nameless 2020-07-18 18:49:45 +08:00 committed by GitHub
parent fbc3e5d07a
commit 0e13cc1cc1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 118 additions and 33 deletions

View file

@ -18,13 +18,14 @@ Telegram terminal client.
- [X] auto download files
- [X] toggle chats: pin/unpin, mark as read/unread, mute/unmute
- [X] message history
- [X] list contacts
- [X] show user status
TODO:
- [ ] secret chats
- [ ] list contacts
- [ ] search
- [ ] show users and their status in current chat
- [ ] show members in chat
- [ ] create new chat
- [ ] bots (bot keyboard)
@ -213,6 +214,7 @@ For navigation arrow keys also can be used.
- `u`: mark read/unread
- `r`: read current chat
- `c`: show list of contacts
- `dd`: delete chat or remove history
- `?`: show help
## Msgs:

View file

@ -13,12 +13,13 @@ from telegram.utils import AsyncResult
from tg import config
from tg.models import Model
from tg.msg import MsgProxy
from tg.tdlib import ChatAction, Tdlib
from tg.tdlib import ChatAction, ChatType, Tdlib, get_chat_type
from tg.utils import (
get_duration,
get_mime,
get_video_resolution,
get_waveform,
is_no,
is_yes,
notify,
suspend,
@ -337,6 +338,8 @@ class Controller:
f"Upload <{file_path}> compressed?[Y/n]"
)
self.render_status()
if resp is None:
return self.present_info("Uploading cancelled")
if not is_yes(resp):
mime = ""
@ -377,7 +380,10 @@ class Controller:
def send_file(
self, send_file_fun: Callable[[str, int], AsyncResult],
) -> None:
file_path = os.path.expanduser(self.view.status.get_input())
_input = self.view.status.get_input()
if _input is None:
return
file_path = os.path.expanduser(_input)
if not file_path or not os.path.isfile(file_path):
return self.present_info("Given path to file does not exist")
@ -397,13 +403,11 @@ class Controller:
resp = self.view.status.get_input(
f"Do you want to send recording: {file_path}? [Y/n]"
)
if not is_yes(resp):
self.present_info("Voice message discarded")
return
if resp is None or not is_yes(resp):
return self.present_info("Voice message discarded")
if not os.path.isfile(file_path):
self.present_info(f"Can't load recording file {file_path}")
return
return self.present_info(f"Can't load recording file {file_path}")
chat_id = self.model.chats.id_by_index(self.model.current_chat)
if not chat_id:
@ -495,6 +499,47 @@ class Controller:
self.model.edit_message(text=text)
self.present_info("Message edited")
@bind(chat_handler, ["dd"])
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
)
self.present_info("Chat was deleted")
@bind(chat_handler, ["n"])
def next_found_chat(self) -> None:
"""Go to next found chat"""

View file

@ -303,6 +303,41 @@ class Tdlib(Telegram):
}
return self._send_data(data)
def leave_chat(self, chat_id: int) -> AsyncResult:
data = {
"@type": "leaveChat",
"chat_id": chat_id,
}
return self._send_data(data)
def join_chat(self, chat_id: int) -> AsyncResult:
data = {
"@type": "joinChat",
"chat_id": chat_id,
}
return self._send_data(data)
def close_secret_chat(self, secret_chat_id: int) -> AsyncResult:
data = {
"@type": "closeSecretChat",
"secret_chat_id": secret_chat_id,
}
return self._send_data(data)
def delete_chat_history(
self, chat_id: int, remove_from_chat_list: bool, revoke: bool = False
) -> AsyncResult:
"""
revoke: Pass true to try to delete chat history for all users
"""
data = {
"@type": "deleteChatHistory",
"chat_id": chat_id,
"remove_from_chat_list": remove_from_chat_list,
"revoke": revoke,
}
return self._send_data(data)
def get_chat_type(chat: Dict[str, Any]) -> Optional[ChatType]:
try:

View file

@ -127,9 +127,11 @@ def num(value: str, default: Optional[int] = None) -> Optional[int]:
def is_yes(resp: str) -> bool:
if resp.strip().lower() == "y" or resp == "":
return True
return False
return not resp or resp.strip().lower() == "y"
def is_no(resp: str) -> bool:
return not resp or resp.strip().lower() == "n"
def get_duration(file_path: str) -> int:

View file

@ -95,31 +95,32 @@ class StatusView:
self.win.addstr(0, 0, msg.replace("\n", " ")[: self.w])
self._refresh()
def get_input(self, buff: str = "", prefix: str = "") -> str:
def get_input(self, buff: str = "", prefix: str = "") -> Optional[str]:
curses.curs_set(1)
while True:
self.win.erase()
line = buff[-(self.w - 1) :]
self.win.addstr(0, 0, f"{prefix}{line}")
try:
while True:
self.win.erase()
line = buff[-(self.w - 1) :]
self.win.addstr(0, 0, f"{prefix}{line}")
key = self.win.get_wch(0, min(len(buff + prefix), self.w - 1))
key = ord(key)
if key == 10: # return
break
elif key == 127: # del
if buff:
buff = buff[:-1]
elif key in (7, 27): # (^G, <esc>) cancel
buff = ""
break
elif chr(key).isprintable():
buff += chr(key)
key = self.win.get_wch(0, min(len(buff + prefix), self.w - 1))
key = ord(key)
if key == 10: # return
break
elif key == 127: # del
if buff:
buff = buff[:-1]
elif key in (7, 27): # (^G, <esc>) cancel
return None
elif chr(key).isprintable():
buff += chr(key)
finally:
self.win.clear()
curses.curs_set(0)
curses.cbreak()
curses.noecho()
self.win.clear()
curses.curs_set(0)
curses.cbreak()
curses.noecho()
return buff