mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2024-11-25 10:53:44 +03:00
Ability to retrieve message history, example improved
The example has been improved with more options (such as print message history), and the TelegramClient now can retrieve the message history from any given point in time or other offsets
This commit is contained in:
parent
e6706080ad
commit
a4f68dd29a
67
main.py
67
main.py
|
@ -2,6 +2,8 @@ import tl_generator
|
||||||
from tl.telegram_client import TelegramClient
|
from tl.telegram_client import TelegramClient
|
||||||
from utils.helpers import load_settings
|
from utils.helpers import load_settings
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
if not tl_generator.tlobjects_exist():
|
if not tl_generator.tlobjects_exist():
|
||||||
|
@ -27,28 +29,51 @@ if __name__ == '__main__':
|
||||||
code = input('Enter the code you just received: ')
|
code = input('Enter the code you just received: ')
|
||||||
client.make_auth(settings['user_phone'], code)
|
client.make_auth(settings['user_phone'], code)
|
||||||
|
|
||||||
# After that, load the top dialogs and show a list
|
# Enter a while loop to chat as long as the user wants
|
||||||
# We use zip(*list_of_tuples) to pair all the elements together,
|
|
||||||
# hence being able to return a new list of each triple pair!
|
|
||||||
# See http://stackoverflow.com/a/12974504/4759433 for a better explanation
|
|
||||||
dialogs, displays, inputs = zip(*client.get_dialogs(8))
|
|
||||||
|
|
||||||
for i, display in enumerate(displays):
|
|
||||||
i += 1 # 1-based index for normies
|
|
||||||
print('{}. {}'.format(i, display))
|
|
||||||
|
|
||||||
# Let the user decide who they want to talk to
|
|
||||||
i = int(input('Who do you want to send messages to?: ')) - 1
|
|
||||||
dialog = dialogs[i]
|
|
||||||
display = displays[i]
|
|
||||||
input_peer = inputs[i]
|
|
||||||
|
|
||||||
# And start a while loop!
|
|
||||||
print('You are now sending messages to "{}". Type "!q" when you want to exit.'.format(display))
|
|
||||||
while True:
|
while True:
|
||||||
msg = input('Enter a message: ')
|
# Retrieve the top dialogs
|
||||||
if msg == '!q':
|
dialogs, displays, inputs = client.get_dialogs(8)
|
||||||
|
|
||||||
|
# Display them so the user can choose
|
||||||
|
for i, display in enumerate(displays):
|
||||||
|
i += 1 # 1-based index for normies
|
||||||
|
print('{}. {}'.format(i, display))
|
||||||
|
|
||||||
|
# Let the user decide who they want to talk to
|
||||||
|
i = int(input('Who do you want to send messages to (0 to exit)?: ')) - 1
|
||||||
|
if i == -1:
|
||||||
break
|
break
|
||||||
client.send_message(input_peer, msg, markdown=True, no_web_page=True)
|
|
||||||
|
# Retrieve the selected user
|
||||||
|
dialog = dialogs[i]
|
||||||
|
display = displays[i]
|
||||||
|
input_peer = inputs[i]
|
||||||
|
|
||||||
|
# Show some information
|
||||||
|
print('You are now sending messages to "{}". Available commands:'.format(display))
|
||||||
|
print(' !q: Quits the current chat.')
|
||||||
|
print(' !h: prints the latest messages (message History) of the chat.')
|
||||||
|
|
||||||
|
# And start a while loop to chat
|
||||||
|
while True:
|
||||||
|
msg = input('Enter a message: ')
|
||||||
|
# Quit
|
||||||
|
if msg == '!q':
|
||||||
|
break
|
||||||
|
|
||||||
|
# History
|
||||||
|
elif msg == '!h':
|
||||||
|
# First retrieve the messages and some information
|
||||||
|
total_count, messages, senders = client.get_message_history(input_peer, limit=10)
|
||||||
|
# Iterate over all (in reverse order so the latest appears the last in the console)
|
||||||
|
# and print them in "[hh:mm] Sender: Message" text format
|
||||||
|
for msg, sender in zip(reversed(messages), reversed(senders)):
|
||||||
|
name = sender.first_name if sender else '???'
|
||||||
|
date = datetime.fromtimestamp(msg.date)
|
||||||
|
print('[{}:{}] {}: {}'.format(date.hour, date.minute, name, msg.message))
|
||||||
|
|
||||||
|
# Send chat message
|
||||||
|
else:
|
||||||
|
client.send_message(input_peer, msg, markdown=True, no_web_page=True)
|
||||||
|
|
||||||
print('Thanks for trying the interactive example! Exiting.')
|
print('Thanks for trying the interactive example! Exiting.')
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# This file is based on TLSharp
|
# This file structure is based on TLSharp
|
||||||
# https://github.com/sochix/TLSharp/blob/master/TLSharp.Core/TelegramClient.cs
|
# https://github.com/sochix/TLSharp/blob/master/TLSharp.Core/TelegramClient.cs
|
||||||
import platform
|
import platform
|
||||||
from parser.markdown_parser import parse_message_entities
|
from parser.markdown_parser import parse_message_entities
|
||||||
|
@ -12,8 +12,8 @@ from tl import Session
|
||||||
from tl.types import PeerUser, PeerChat, PeerChannel, InputPeerUser, InputPeerChat, InputPeerChannel, InputPeerEmpty
|
from tl.types import PeerUser, PeerChat, PeerChannel, InputPeerUser, InputPeerChat, InputPeerChannel, InputPeerEmpty
|
||||||
from tl.functions import InvokeWithLayerRequest, InitConnectionRequest
|
from tl.functions import InvokeWithLayerRequest, InitConnectionRequest
|
||||||
from tl.functions.help import GetConfigRequest
|
from tl.functions.help import GetConfigRequest
|
||||||
from tl.functions.auth import CheckPhoneRequest, SendCodeRequest, SignInRequest
|
from tl.functions.auth import SendCodeRequest, SignInRequest
|
||||||
from tl.functions.messages import GetDialogsRequest, SendMessageRequest
|
from tl.functions.messages import GetDialogsRequest, GetHistoryRequest, SendMessageRequest
|
||||||
|
|
||||||
|
|
||||||
class TelegramClient:
|
class TelegramClient:
|
||||||
|
@ -126,16 +126,8 @@ class TelegramClient:
|
||||||
return self.session.user
|
return self.session.user
|
||||||
|
|
||||||
def get_dialogs(self, count=10, offset_date=None, offset_id=0, offset_peer=InputPeerEmpty()):
|
def get_dialogs(self, count=10, offset_date=None, offset_id=0, offset_peer=InputPeerEmpty()):
|
||||||
"""Returns 'count' dialogs in a (dialog, display, input_peer) list format"""
|
"""Returns a tuple of lists ([dialogs], [displays], [input_peers]) with 'count' items each"""
|
||||||
|
request = GetDialogsRequest(offset_date=TelegramClient.get_tg_date(offset_date),
|
||||||
# Telegram wants the offset_date in an unix-timestamp format, not Python's datetime
|
|
||||||
# However that's not very comfortable, so calculate the correct value here
|
|
||||||
if offset_date is None:
|
|
||||||
offset_date = 0
|
|
||||||
else:
|
|
||||||
offset_date = int(offset_date.timestamp())
|
|
||||||
|
|
||||||
request = GetDialogsRequest(offset_date=offset_date,
|
|
||||||
offset_id=offset_id,
|
offset_id=offset_id,
|
||||||
offset_peer=offset_peer,
|
offset_peer=offset_peer,
|
||||||
limit=count)
|
limit=count)
|
||||||
|
@ -143,11 +135,10 @@ class TelegramClient:
|
||||||
self.sender.send(request)
|
self.sender.send(request)
|
||||||
self.sender.receive(request)
|
self.sender.receive(request)
|
||||||
|
|
||||||
result = request.result
|
r = request.result
|
||||||
return [(dialog,
|
return (r.dialogs,
|
||||||
TelegramClient.find_display_name(dialog.peer, result.users, result.chats),
|
[self.find_display_name(d.peer, r.users, r.chats) for d in r.dialogs],
|
||||||
TelegramClient.find_input_peer_name(dialog.peer, result.users, result.chats))
|
[self.find_input_peer(d.peer, r.users, r.chats) for d in r.dialogs])
|
||||||
for dialog in result.dialogs]
|
|
||||||
|
|
||||||
def send_message(self, input_peer, message, markdown=False, no_web_page=False):
|
def send_message(self, input_peer, message, markdown=False, no_web_page=False):
|
||||||
"""Sends a message to the given input peer"""
|
"""Sends a message to the given input peer"""
|
||||||
|
@ -165,10 +156,55 @@ class TelegramClient:
|
||||||
self.sender.send(request)
|
self.sender.send(request)
|
||||||
self.sender.receive(request)
|
self.sender.receive(request)
|
||||||
|
|
||||||
|
def get_message_history(self, input_peer, limit=20,
|
||||||
|
offset_date=None, offset_id=0, max_id=0, min_id=0, add_offset=0):
|
||||||
|
"""
|
||||||
|
Gets the message history for the specified InputPeer
|
||||||
|
|
||||||
|
:param input_peer: The InputPeer from whom to retrieve the message history
|
||||||
|
:param limit: Number of messages to be retrieved
|
||||||
|
:param offset_date: Offset date (messages *previous* to this date will be retrieved)
|
||||||
|
:param offset_id: Offset message ID (only messages *previous* to the given ID will be retrieved)
|
||||||
|
:param max_id: All the messages with a higher (newer) ID or equal to this will be excluded
|
||||||
|
:param min_id: All the messages with a lower (older) ID or equal to this will be excluded
|
||||||
|
:param add_offset: Additional message offset (all of the specified offsets + this offset = older messages)
|
||||||
|
|
||||||
|
:return: A tuple containing total message count and two more lists ([messages], [senders]).
|
||||||
|
Note that the sender can be null if it was not found!
|
||||||
|
"""
|
||||||
|
request = GetHistoryRequest(input_peer,
|
||||||
|
limit=limit,
|
||||||
|
offset_date=self.get_tg_date(offset_date),
|
||||||
|
offset_id=offset_id,
|
||||||
|
max_id=max_id,
|
||||||
|
min_id=min_id,
|
||||||
|
add_offset=add_offset)
|
||||||
|
|
||||||
|
self.sender.send(request)
|
||||||
|
self.sender.receive(request)
|
||||||
|
|
||||||
|
result = request.result
|
||||||
|
# The result may be a messages slice (not all messages were retrieved) or
|
||||||
|
# simply a messages TLObject. In the later case, no "count" attribute is specified:
|
||||||
|
# the total messages count is retrieved by counting all the retrieved messages
|
||||||
|
total_messages = getattr(result, 'count', len(result.messages))
|
||||||
|
|
||||||
|
return (total_messages,
|
||||||
|
result.messages,
|
||||||
|
[usr # Create a list with the users...
|
||||||
|
if usr.id == msg.from_id else None # ...whose ID equals the current message ID...
|
||||||
|
for msg in result.messages # ...from all the messages...
|
||||||
|
for usr in result.users]) # ...from all of the available users
|
||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
|
|
||||||
# region Utilities
|
# region Utilities
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_tg_date(datetime):
|
||||||
|
"""Parses a datetime Python object to Telegram's required integer Unix timestamp"""
|
||||||
|
return 0 if datetime is None else int(datetime.timestamp())
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def find_display_name(peer, users, chats):
|
def find_display_name(peer, users, chats):
|
||||||
"""Searches the display name for peer in both users and chats.
|
"""Searches the display name for peer in both users and chats.
|
||||||
|
@ -192,7 +228,7 @@ class TelegramClient:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def find_input_peer_name(peer, users, chats):
|
def find_input_peer(peer, users, chats):
|
||||||
"""Searches the given peer in both users and chats and returns an InputPeer for it.
|
"""Searches the given peer in both users and chats and returns an InputPeer for it.
|
||||||
Returns None if it was not found"""
|
Returns None if it was not found"""
|
||||||
try:
|
try:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user