mirror of
https://github.com/paul-nameless/tg
synced 2024-11-22 03:43:19 +00:00
Show chat info with <c> shortcut in msg panel
This commit is contained in:
parent
ef09ba6e7b
commit
bf266c7999
4 changed files with 167 additions and 23 deletions
|
@ -20,13 +20,13 @@ Telegram terminal client.
|
||||||
- [X] message history
|
- [X] message history
|
||||||
- [X] list contacts
|
- [X] list contacts
|
||||||
- [X] show user status
|
- [X] show user status
|
||||||
|
- [X] secret chats
|
||||||
|
- [X] create new chat
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
|
|
||||||
- [ ] secret chats
|
|
||||||
- [ ] search
|
- [ ] search
|
||||||
- [ ] show members in chat
|
- [ ] show members in chat
|
||||||
- [ ] create new chat
|
|
||||||
- [ ] bots (bot keyboard)
|
- [ ] bots (bot keyboard)
|
||||||
|
|
||||||
|
|
||||||
|
@ -245,6 +245,8 @@ For navigation arrow keys also can be used.
|
||||||
- `r`: read current chat
|
- `r`: read current chat
|
||||||
- `c`: show list of contacts
|
- `c`: show list of contacts
|
||||||
- `dd`: delete chat or remove history
|
- `dd`: delete chat or remove history
|
||||||
|
- `ng`: create new group chat
|
||||||
|
- `ns`: create new secret chat
|
||||||
- `/`: search in chats
|
- `/`: search in chats
|
||||||
- `?`: show help
|
- `?`: show help
|
||||||
|
|
||||||
|
@ -277,5 +279,7 @@ For navigation arrow keys also can be used.
|
||||||
- `o`: open url present in message (if multiple urls, `urlview` will be opened)
|
- `o`: open url present in message (if multiple urls, `urlview` will be opened)
|
||||||
- `]`: next chat
|
- `]`: next chat
|
||||||
- `[`: prev chat
|
- `[`: prev chat
|
||||||
|
- `u`: show user info (username, bio, phone, etc.)
|
||||||
|
- `c`: show chat info (e.g. secret chat encryption key, chat id, state, etc.)
|
||||||
- `?`: show help
|
- `?`: show help
|
||||||
- `!`: open msg with custom cmd
|
- `!`: open msg with custom cmd
|
||||||
|
|
|
@ -13,7 +13,7 @@ from telegram.utils import AsyncResult
|
||||||
from tg import config
|
from tg import config
|
||||||
from tg.models import Model
|
from tg.models import Model
|
||||||
from tg.msg import MsgProxy
|
from tg.msg import MsgProxy
|
||||||
from tg.tdlib import ChatAction, ChatType, Tdlib, UserType, get_chat_type
|
from tg.tdlib import ChatAction, ChatType, Tdlib, get_chat_type
|
||||||
from tg.utils import (
|
from tg.utils import (
|
||||||
get_duration,
|
get_duration,
|
||||||
get_mime,
|
get_mime,
|
||||||
|
@ -76,29 +76,25 @@ class Controller:
|
||||||
self.tg = tg
|
self.tg = tg
|
||||||
self.chat_size = 0.5
|
self.chat_size = 0.5
|
||||||
|
|
||||||
|
@bind(msg_handler, ["c"])
|
||||||
|
def show_chat_info(self) -> None:
|
||||||
|
"""Show chat information"""
|
||||||
|
chat = self.model.chats.chats[self.model.current_chat]
|
||||||
|
info = self.model.get_chat_info(chat)
|
||||||
|
|
||||||
|
with suspend(self.view) as s:
|
||||||
|
s.run_with_input(
|
||||||
|
config.VIEW_TEXT_CMD,
|
||||||
|
"\n".join(f"{k}: {v}" for k, v in info.items() if v),
|
||||||
|
)
|
||||||
|
|
||||||
@bind(msg_handler, ["u"])
|
@bind(msg_handler, ["u"])
|
||||||
def user_info(self) -> None:
|
def show_user_info(self) -> None:
|
||||||
"""Show user profile"""
|
"""Show user profile"""
|
||||||
msg = MsgProxy(self.model.current_msg)
|
msg = MsgProxy(self.model.current_msg)
|
||||||
user_id = msg.sender_id
|
user_id = msg.sender_id
|
||||||
users = self.model.users
|
info = self.model.get_user_info(user_id)
|
||||||
name = users.get_user_label(user_id)
|
|
||||||
status = users.get_status(user_id)
|
|
||||||
user = users.get_user(user_id)
|
|
||||||
user_info = users.get_user_full_info(user_id)
|
|
||||||
user_type = None
|
|
||||||
try:
|
|
||||||
user_type = UserType[user["type"]["@type"]].value
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
info = {
|
|
||||||
name: status,
|
|
||||||
"Username": user.get("username", ""),
|
|
||||||
"UserId": user_id,
|
|
||||||
"Bio": user_info.get("bio", ""),
|
|
||||||
"Phone": user.get("phone_number", ""),
|
|
||||||
"Type": user_type,
|
|
||||||
}
|
|
||||||
with suspend(self.view) as s:
|
with suspend(self.view) as s:
|
||||||
s.run_with_input(
|
s.run_with_input(
|
||||||
config.VIEW_TEXT_CMD,
|
config.VIEW_TEXT_CMD,
|
||||||
|
|
119
tg/models.py
119
tg/models.py
|
@ -1,3 +1,4 @@
|
||||||
|
import base64
|
||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
@ -5,7 +6,15 @@ from collections import defaultdict, namedtuple
|
||||||
from typing import Any, Dict, List, Optional, Set, Tuple
|
from typing import Any, Dict, List, Optional, Set, Tuple
|
||||||
|
|
||||||
from tg.msg import MsgProxy
|
from tg.msg import MsgProxy
|
||||||
from tg.tdlib import ChatAction, Tdlib, UserStatus
|
from tg.tdlib import (
|
||||||
|
ChatAction,
|
||||||
|
ChatType,
|
||||||
|
SecretChatState,
|
||||||
|
Tdlib,
|
||||||
|
UserStatus,
|
||||||
|
UserType,
|
||||||
|
get_chat_type,
|
||||||
|
)
|
||||||
from tg.utils import copy_to_clipboard, pretty_ts
|
from tg.utils import copy_to_clipboard, pretty_ts
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
@ -217,6 +226,114 @@ class Model:
|
||||||
copy_to_clipboard("\n".join(buffer))
|
copy_to_clipboard("\n".join(buffer))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def get_chat_info(self, chat: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
|
chat_type = get_chat_type(chat)
|
||||||
|
if chat_type is None:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
info = {}
|
||||||
|
|
||||||
|
if chat_type == ChatType.chatTypePrivate:
|
||||||
|
user_id = chat["id"]
|
||||||
|
user = self.users.get_user(user_id)
|
||||||
|
user_info = self.users.get_user_full_info(user_id)
|
||||||
|
status = self.users.get_status(user_id)
|
||||||
|
info.update(
|
||||||
|
{
|
||||||
|
chat["title"]: status,
|
||||||
|
"Username": user.get("username", ""),
|
||||||
|
"Phone": user.get("phone_number", ""),
|
||||||
|
"Bio": user_info.get("bio", ""),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if chat_type == ChatType.chatTypeBasicGroup:
|
||||||
|
group_id = chat["type"]["basic_group_id"]
|
||||||
|
result = self.tg.get_basic_group_full_info(group_id)
|
||||||
|
result.wait()
|
||||||
|
chat_info = result.update
|
||||||
|
basic_info = self.tg.get_basic_group(group_id)
|
||||||
|
basic_info.wait()
|
||||||
|
basic_info = basic_info.update
|
||||||
|
info.update(
|
||||||
|
{
|
||||||
|
chat["title"]: f"{basic_info['member_count']} members",
|
||||||
|
"Info": chat_info["description"],
|
||||||
|
"Share link": chat_info["invite_link"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if chat_type == ChatType.chatTypeSupergroup:
|
||||||
|
result = self.tg.get_supergroup_full_info(
|
||||||
|
chat["type"]["supergroup_id"]
|
||||||
|
)
|
||||||
|
result.wait()
|
||||||
|
chat_info = result.update
|
||||||
|
info.update(
|
||||||
|
{
|
||||||
|
chat["title"]: f"{chat_info['member_count']} members",
|
||||||
|
"Info": chat_info["description"],
|
||||||
|
"Share link": chat_info["invite_link"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if chat_type == ChatType.channel:
|
||||||
|
chat_info = self.tg.get_supergroup_full_info(
|
||||||
|
chat["type"]["supergroup_id"]
|
||||||
|
)
|
||||||
|
info.update(
|
||||||
|
{
|
||||||
|
chat["title"]: "subscribers",
|
||||||
|
"Info": chat_info["description"],
|
||||||
|
"Share link": chat_info["invite_link"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if chat_type == ChatType.chatTypeSecret:
|
||||||
|
result = self.tg.get_secret_chat(chat["type"]["secret_chat_id"])
|
||||||
|
result.wait()
|
||||||
|
chat_info = result.update
|
||||||
|
enc_key = base64.b64decode(chat_info["key_hash"])[:32].hex()
|
||||||
|
hex_key = " ".join(
|
||||||
|
[enc_key[i : i + 2] for i in range(0, len(enc_key), 2)]
|
||||||
|
)
|
||||||
|
|
||||||
|
state = "Unknown"
|
||||||
|
try:
|
||||||
|
state = SecretChatState[chat_info["state"]["@type"]].value
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
user_id = chat_info["user_id"]
|
||||||
|
user_info = self.get_user_info(user_id)
|
||||||
|
|
||||||
|
info.update(
|
||||||
|
{**user_info, "State": state, "Encryption Key": hex_key}
|
||||||
|
)
|
||||||
|
|
||||||
|
info.update({"Type": chat_type.value, "Chat Id": chat["id"]})
|
||||||
|
return info
|
||||||
|
|
||||||
|
def get_user_info(self, user_id: int) -> Dict[str, Any]:
|
||||||
|
name = self.users.get_user_label(user_id)
|
||||||
|
status = self.users.get_status(user_id)
|
||||||
|
user = self.users.get_user(user_id)
|
||||||
|
user_info = self.users.get_user_full_info(user_id)
|
||||||
|
user_type = "Unknown"
|
||||||
|
try:
|
||||||
|
user_type = UserType[user["type"]["@type"]].value
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
info = {
|
||||||
|
name: status,
|
||||||
|
"Username": user.get("username", ""),
|
||||||
|
"Bio": user_info.get("bio", ""),
|
||||||
|
"Phone": user.get("phone_number", ""),
|
||||||
|
"User Id": user_id,
|
||||||
|
"Type": user_type,
|
||||||
|
}
|
||||||
|
return info
|
||||||
|
|
||||||
|
|
||||||
class ChatModel:
|
class ChatModel:
|
||||||
def __init__(self, tg: Tdlib) -> None:
|
def __init__(self, tg: Tdlib) -> None:
|
||||||
|
|
27
tg/tdlib.py
27
tg/tdlib.py
|
@ -49,6 +49,12 @@ class TextParseModeInput(Enum):
|
||||||
textParseModeHTML = "html"
|
textParseModeHTML = "html"
|
||||||
|
|
||||||
|
|
||||||
|
class SecretChatState(Enum):
|
||||||
|
secretChatStatePending = "pending"
|
||||||
|
secretChatStateReady = "ready"
|
||||||
|
secretChatStateClosed = "closed"
|
||||||
|
|
||||||
|
|
||||||
class Tdlib(Telegram):
|
class Tdlib(Telegram):
|
||||||
def parse_text_entities(
|
def parse_text_entities(
|
||||||
self,
|
self,
|
||||||
|
@ -295,6 +301,13 @@ class Tdlib(Telegram):
|
||||||
}
|
}
|
||||||
return self._send_data(data)
|
return self._send_data(data)
|
||||||
|
|
||||||
|
def get_basic_group_full_info(self, basic_group_id: int,) -> AsyncResult:
|
||||||
|
data = {
|
||||||
|
"@type": "getBasicGroupFullInfo",
|
||||||
|
"basic_group_id": basic_group_id,
|
||||||
|
}
|
||||||
|
return self._send_data(data)
|
||||||
|
|
||||||
def get_supergroup(self, supergroup_id: int,) -> AsyncResult:
|
def get_supergroup(self, supergroup_id: int,) -> AsyncResult:
|
||||||
data = {
|
data = {
|
||||||
"@type": "getSupergroup",
|
"@type": "getSupergroup",
|
||||||
|
@ -302,6 +315,20 @@ class Tdlib(Telegram):
|
||||||
}
|
}
|
||||||
return self._send_data(data)
|
return self._send_data(data)
|
||||||
|
|
||||||
|
def get_supergroup_full_info(self, supergroup_id: int,) -> AsyncResult:
|
||||||
|
data = {
|
||||||
|
"@type": "getSupergroupFullInfo",
|
||||||
|
"supergroup_id": supergroup_id,
|
||||||
|
}
|
||||||
|
return self._send_data(data)
|
||||||
|
|
||||||
|
def get_secret_chat(self, secret_chat_id: int,) -> AsyncResult:
|
||||||
|
data = {
|
||||||
|
"@type": "getSecretChat",
|
||||||
|
"secret_chat_id": secret_chat_id,
|
||||||
|
}
|
||||||
|
return self._send_data(data)
|
||||||
|
|
||||||
def send_chat_action(
|
def send_chat_action(
|
||||||
self, chat_id: int, action: ChatAction, progress: int = None
|
self, chat_id: int, action: ChatAction, progress: int = None
|
||||||
) -> AsyncResult:
|
) -> AsyncResult:
|
||||||
|
|
Loading…
Reference in a new issue