I would like to get all the messages from a chat that have been sent today.
import sys,datetime
from telethon import TelegramClient
api_id = 1234567
api_hash = "0986asdgshjfag"
client = TelegramClient('session_name', api_id, api_hash)
client.start()
dialogs = client.get_dialogs()
chat = client.get_input_entity('username')
filter = InputMessagesFilterEmpty()
result = client(SearchRequest(
peer=chat, # On which chat/conversation
q='', # What to search for
filter=filter, # Filter to use (maybe filter for media)
min_date=datetime.date.today(), # Minimum date
max_date=None, # Maximum date
offset_id=0, # ID of the message to use as offset
add_offset=0, # Additional offset
limit=5, # How many results
max_id=0, # Maximum message ID
min_id=0, # Minimum message ID
from_id=None, # Who must have sent the message (peer)
hash=0 # Special number to return nothing on no-change
))
for message in client.iter_messages(chat,filter=result):
print(message.message)
The filter doesn't work at all, I can see more than 5 messages (the whole chat) and it doesn't care about the time.
Why?
You can use 'message.date'.
If you want to get the message from today you need to check the sent day. and this would be like :
if datetime.datetime.now().strftime('%Y-%m-%d') == message.date.strftime('%Y-%m-%d')
Related
I have pulled data from a private slack channel, using conversation history, and it pulls the userid instead of username, how can I change the code to pull the user name so I can identify who each user is? Code below
CHANNEL = ""
MESSAGES_PER_PAGE = 200
MAX_MESSAGES = 1000
SLACK_TOKEN = ""
client = slack_sdk.WebClient(token=SLACK_TOKEN)
# get first page
page = 1
print("Retrieving page {}".format(page))
response = client.conversations_history(
channel=CHANNEL,
limit=MESSAGES_PER_PAGE,
)
assert response["ok"]
messages_all = response['messages']
# get additional pages if below max message and if they are any
while len(messages_all) + MESSAGES_PER_PAGE <= MAX_MESSAGES and response['has_more']:
page += 1
print("Retrieving page {}".format(page))
sleep(1) # need to wait 1 sec before next call due to rate limits
response = client.conversations_history(
channel=CHANNEL,
limit=MESSAGES_PER_PAGE,
cursor=response['response_metadata']['next_cursor']
)
assert response["ok"]
messages = response['messages']
messages_all = messages_all + messages
It isn't possible to change what is returned from the conversations.history method. If you'd like to convert user IDs to usernames, you'll need to either:
Call the users.info method and retrieve the username from the response.
or
Call the users.list method and iterate through the list and create a local copy (or store in a database) and then have your code look it up.
I'm using peewee to store participants in a telegram channel. How do I get only new participants, i.e. those who have not been previously added?
Maybe we can offset by time? or offset by those who are already in the database?
Not so sure how to perform offsets in GetParticipantsRequest
from telethon import TelegramClient
from telethon.tl.functions.channels import GetParticipantsRequest
from telethon.tl.types import ChannelParticipantsSearch
from time import sleep
from schema import channel_users as cudb
from datetime import datetime
import json
from dotenv import load_dotenv
load_dotenv()
import os
api_id = os.getenv('API_ID')
api_hash = os.getenv('API_HASH')
PHONE = os.getenv('PHONE')
USERNAME = os.getenv('USERNAME')
# Remember to use your own values from my.telegram.org!
client = TelegramClient('anon', api_id, api_hash)
async def main():
# Getting information about yourself
me = await client.get_me()
my_channel = 'https://t.me/some_channel_url'
offset = 0
limit = 100
all_participants = []
while True:
participants = await client(GetParticipantsRequest(
my_channel, ChannelParticipantsSearch(''), offset, limit,
hash=0
))
if not participants.users:
break
all_participants.extend(participants.users)
offset += len(participants.users)
all_user_details = []
for participant in all_participants:
now = datetime.now()
date_added = now.strftime("%d/%m/%Y, %H:%M:%S")
channel_user_id, created = cudb.get_or_create(
id = participant.id,
defaults = {'first_name' : participant.first_name,
'last_name' : participant.last_name,
'username' : participant.username,
'phone' : participant.phone,
'is_bot' : participant.bot,
'date_added' : date_added}
)
if (created):
print(f'successfully created channel_usersID = {channel_user_id}')
else:
print(f'did not create anything, user information found in channel_usersID {channel_user_id}')
with client:
client.loop.run_until_complete(main())
ok I've sort of solved it with this. Problem is - Now trying to figure out how to update every time new user joins
while True:
participants = await client(GetParticipantsRequest(
my_channel, ChannelParticipantsSearch(''), offset, limit,
hash=0
))
number_of_participants = len(participants.users)
print(f'{len(participants.users)} length')
max_cudb = cudb.select(fn.MAX(cudb.channel_usersID)).scalar()
if max_cudb == len(participants.users):
print('id is same as number of participants in group, hence nothing new')
break
if not participants.users:
break
# calculate the difference between number of participants and last user added to DB
number_to_add = number_of_participants - max_cudb
# adds missing users chronologically from oldest to most recent
print(f'number_to_add = {number_to_add}')
for i in range(number_to_add-1,-1,-1):
print(f'i = {i}')
participant = participants.users[i]
now = datetime.now()
date_added = now.strftime("%d/%m/%Y, %H:%M:%S")
channel_user_id, created = cudb.get_or_create(
id = participant.id,
defaults = {'first_name' : participant.first_name,
'last_name' : participant.last_name,
'username' : participant.username,
'phone' : participant.phone,
'is_bot' : participant.bot,
'date_added' : date_added}
)
# Prints status of DB addition
if (created):
print(f'successfully created channel_usersID = {channel_user_id}')
else:
print(f'did not create anything, user information found in channel_usersID {channel_user_id}')
https://docs.telethon.dev/en/stable/quick-references/events-reference.html?highlight=chataction#chataction here you are the docs for chataction, exactly what you need just make sure to filter the event.
Is there any method to send stickers using the id attribute of event.file? The documentation points out to send it using the id and the access_hash of a particular sticker set and then finally using index with sticker_set to send the sticker. Since there's unique id for particular sticker stored in telegram servers, I was wondering if there's any method of using that to send stickers?
from telethon.tl.functions.messages import GetAllStickersRequest
sticker_sets = await client(GetAllStickersRequest(0))
# Choose a sticker set
from telethon.tl.functions.messages import GetStickerSetRequest
from telethon.tl.types import InputStickerSetID
sticker_set = sticker_sets.sets[0]
# Get the stickers for this sticker set
stickers = await client(GetStickerSetRequest(
stickerset=InputStickerSetID(
id=sticker_set.id, access_hash=sticker_set.access_hash
)
))
# Stickers are nothing more than files, so send that
await client.send_file('me', stickers.documents[0])
You must send the sticker as an InputDocument, specifying the sticker id, access_hash and file_reference.
from telethon import types
# some code here
await event.reply(
file = types.InputDocument(
id = YOUR_STICKER_ID,
access_hash = YOUR_STICKER_ACCESS_HASH,
file_reference = YOUR_STICKER_FILE_REFERENCE
)
)
# more code
For example, reply to "/sticker" new message:
from telethon import events, types
# Reply to new message /sticker
#client.on(events.NewMessage(pattern=r'/sticker'))
await event.reply(
file = types.InputDocument(
id = YOUR_STICKER_ID,
access_hash = YOUR_STICKER_ACCESS_HASH,
file_reference = YOUR_STICKER_FILE_REFERENCE
)
)
The code below retrieves the latest email in the thread. How do I retrieve the latest 2 emails in the thread? Thanks in advance.
messages = service.users().threads().list(userId='me').execute().get('threads', [])
for message in messages:
if search in message['snippet']:
# add/modify the following lines:
thread = service.users().threads().get(userId='me', id=message['id'], fields='messages(id,internalDate)').execute() #.get( [])
last = len(thread['messages']) - 1
message_id = thread['messages'][last]['id']
# non-modified code:
full_message = service.users().messages().get(userId='me', id=message_id, format="raw").execute()
msg_str = base64.urlsafe_b64decode(full_message['raw'].encode('ASCII'))
mime_msg = email.message_from_bytes(msg_str)
y = re.findall(r'Delivered-To: (\S+)', str(mime_msg))
print(y[0])
The line last = len(thread['messages']) - 1 specifies that you want to retrieve the last message from a thread
Consequently, to retrieve the prelast message, you need to specify prelast = len(thread['messages']) - 2
And respectively prelast_message_id = thread['messages'][prelast]['id']
Now, you can push both last and prelast message Ids into an array and perform your # non-modified code in a for loop on both message ids.
I was wondering if i can make input() using TeleBot dependency.
e.g. console way:
POL = float(input("Enter your POL: ))
Is there a way to do using Telebot, like:
bot.send_message(message.chat.id, "Enter your POL")
## Get message.text into POL variable.
From what I understand, there isn't a direct way of doing this, but you can look at the message that the user has replied to from
replied_message = message.reply_to_message.message_id
If it matches the id of the message that you sent then that would be the reply to your message. You can get the id of your sent message from
sent_message = bot.send_message(message.chat.id, "Enter your POL")
sent_message_id = sent_message.message_id
import telebot
TELEGRAM_TOKEN = '<TOKEN>'
bot = telebot.TeleBot(TELEGRAM_TOKEN)
user_register_dict = {}
#bot.message_handler(commands=['start'])
def start(message):
bot.reply_to(message , 'now send your name')
user_register_dict[message.chat.id] = {}
bot.register_next_step_handler(message , start_step2)
def start_step2(message):
user_register_dict[message.chat.id]['name'] = message.text
bot.reply_to(message , 'now send your age')
bot.register_next_step_handler(message , start_step3)
def start_step3(message):
user_register_dict[message.chat.id]['age'] = message.text
bot.reply_to(message , 'your name is {} and you are {} years old!'
.format(user_register_dict[message.chat.id]['name'] ,
[message.chat.id]['age'] ))
start(message = message)
Create a dict for handling the data, which is important because if you use lists (eg.) maybe 2 people starts to register in same time and data gonna crash!
Difference between create bot.register_next_step_handler (line 13 for example) with connect directly for example start(message = message) in end line is in register_next_step_handler bot waits for new message and when received puts it in message and start defection but in direct start defection bot doesn't wait for user message, and start defection with current message start(message = message)