the post sent by the bot telegram is not deleted for all users - telegram-bot

I have a function which allows to send a message to all users who clicked the start button.
#dp.message_handler(commands=['Yes'], state=Post.send_post)
async def process_name(message: Message, state: FSMContext):
for admin in admins:
if message.from_user.id == admin:
async with state.proxy() as data:
data['send_post'] = message.text
conn = sqlite3.connect('data.db')
cur = conn.cursor()
cur.execute(f'SELECT * FROM users')
result = cur.fetchall()
await state.finish()
print(result)
try:
for z in range(len(result)):
print(result[z][0])
await dp.bot.send_photo(chat_id=result[z][0], photo=data['photo'], caption=data['CAPTHION'], reply_markup=kb)
print(z)
test = message.message_id + 1
await dp.bot.send_message(chat_id=result[z][0], text=f'id поста {test}')
except BotBlocked:
print('Пользователь заблокировал бота')
except ChatNotFound:
print('Пользователь не запускал бота')
Also, there is a function that allows you to delete messages by id. The administrator enters the deleted command, after which the bot asks to enter its id. When the Administrator enters an id, the bot deletes messages through a loop, iterating over the id. But for some reason, it only deletes a post from one user, then it throws an error
aiogram.utils.exceptions.MessageToDeleteNotFound: Message to delete not found
Please help me I can't figure out why
#dp.message_handler(commands=['deleted'], state=None)
async def send_id(message: Message):
for admin in admins:
if message.from_user.id == admin:
await Post.Sen_id.set()
await dp.bot.send_message(chat_id=admin, text='Введите ID поста, который нужно удалить.')
await Post.next()
#dp.message_handler(state=Post.del_mess)
async def deleted_post(message: Message, state: FSMContext):
for admin in admins:
if message.from_user.id == admin:
async with state.proxy() as data:
data['sen_id'] = message.text
try:
conn = sqlite3.connect('data.db')
cur = conn.cursor()
cur.execute(f'SELECT * FROM users')
result = cur.fetchall()
#message_ids = int(data['sen_id'])
for z in range(len(result)):
print('/////////////deleted/////////////')
print(result)
print(z)
await dp.bot.delete_message(chat_id=result[z][0], message_id=data['sen_id'])
print('Сообщение удалено')
#chat_id = message.chat.id
#await dp.bot.delete_message(message.chat.id, message_ids)
await dp.bot.send_message(chat_id=admin, text='пост удален')
except BotBlocked:
print('Пользователь заблокировал бота')
except ChatNotFound:
print('Пользователь не запускал бота')

This is a code that does what you wish for - deleting message with given message_id in every chat where that message exist. Later I'll explain why this is actually not a good solution.
The problem is with the placing of the try-except block. In your code, if deleting the message fails for a single user, for all users that are past him in the database the deletion will not be even attempted. Solution would be to place the try-except block in the for loop.
...
if message.from_user.id == admin:
async with state.proxy() as data:
data['sen_id'] = message.text
conn = sqlite3.connect('data.db')
cur = conn.cursor()
cur.execute(f'SELECT * FROM users')
result = cur.fetchall()
#message_ids = int(data['sen_id'])
for z in range(len(result)):
try:
print('/////////////deleted/////////////')
print(result)
print(z)
await dp.bot.delete_message(chat_id=result[z][0], message_id=data['sen_id'])
print('Сообщение удалено')
#chat_id = message.chat.id
#await dp.bot.delete_message(message.chat.id, message_ids)
await dp.bot.send_message(chat_id=admin, text='пост удален')
except BotBlocked:
print('Пользователь заблокировал бота')
except ChatNotFound:
print('Пользователь не запускал бота')
except Exception as e:
print(e)
...
However, after testing this approach, I believe you will realise that there is a problem: if you send a "post" to multiple users, it may have a different message_id for different users! So you would have to use a different approach.

Related

Telethon "DestroySessionRequest" method not work

I try destoy every new session.
I run main script, save all exist session to variable
all_session = await client(functions.account.GetAuthorizationsRequest())
hash_list = [x.hash for x in all_session.authorizations]
after i run and search for new session
if i got new session - i try destroy it
while True:
await asyncio.sleep(15)
all_new = await client(functions.account.GetAuthorizationsRequest())
new_hashes = [x.hash for x in all_new.authorizations]
for h in new_hashes:
if h not in hash_list:
logger.debug(f"have a new hash {h}")
try:
result = await client(functions.DestroySessionRequest(
session_id=-h
))
logger.debug(f"DROP RESULT IS: {result.stringify()}")
except Exception as e:
logger.debug(
f"error - {e}")
Every time then i try i got as response
DestroySessionNone(
session_id=3806172788422661047
)
i also tried use this method without "-", same result
try:
result = await client(functions.DestroySessionRequest(
session_id=-h
))
logger.debug(f"DROP RESULT IS: {result.stringify()}")
except Exception as e:
logger.debug(
f"error - {e}")

telethon :A wait of 16480 seconds is required (caused by ResolveUsernameRequest)

i'm trying to use telethon to send messages to telegram groups. after some times runing, it reruens:
A wait of 16480 seconds is required (caused by ResolveUsernameRequest).
the code is:
async def main():
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))
config = configparser.ConfigParser()
config.read("seetings.ini",encoding= 'utf-8')
message = config['Customer']['message']
internal = config['Customer']['internal']
count = 0
excel_data = pandas.read_excel('tg_groups.xlsx', sheet_name='Groups')
for column in excel_data['GroupUsername'].tolist():
try:
if str(excel_data['GroupUsername'][count]) == 'None':
count += 1
continue
else:
chat = await client.get_input_entity(str(excel_data['GroGroupUsernameupID'][count]))
await client.send_message(entity=chat, message=message)
except Exception as e:
print(e)
time.sleep(int(internal))
count = count + 1
continue
time.sleep(int(internal))
count = count + 1
if __name__ == '__main__':
if proxytype == 'HTTP':
print('HTTP')
client = TelegramClient('phone'+phone, api_id, api_hash, proxy=(socks.HTTP, 'localhost', int(proxyport))).start()
if proxytype == 'socks5':
print('SOCKS5')
client = TelegramClient('phone'+phone, api_id, api_hash, proxy=(socks.SCOKS5, 'localhost', int(proxyport))).start()
myself = client.get_me()
print(myself)
freqm = config['Customer']['freq']
print(int(freqm))
while True:
with client:
client.loop.run_until_complete(main())
time.sleep(int(freqm))`
`
from the 'Entity' guide, it says get_input_entity method will search the user info from session file cache, why it it still call the 'ResolveUsernameRequest'to get the user info? anything i missed?
thanks for any advice.
'Entity' guide, it says get_input_entity method will search the user info from session file cache, why it it still call the 'ResolveUsernameRequest'to get the user info? anything i missed or the session file didn't keep the user info cache?

Having trouble running multiple functions in Asyncio

I'm a novice programmer looking to build a script that reads a list of leads from Google Sheets and then messages them on telegram. I want to separate out the first and second message by three days thats why im separating the methods.
import asyncio
from telethon import TelegramClient
from telethon.errors.rpcerrorlist import SessionPasswordNeededError
import logging
from async_class import AsyncClass, AsyncObject, task, link
from sheetdata import *
logging.basicConfig(format='[%(levelname) 5s/%(asctime)s] %(name)s: %(message)s',
level=logging.WARNING)
api_id = id
api_hash = 'hash'
phone='phone'
username='user'
client = TelegramClient(username, api_id, api_hash)
#already been touched once
second_touch_array=[]
#touched twice
third_touch_array=[]
async def messageCount(userid):
count = 0
async for message in client.iter_messages(userid):
count+=1
yield count
async def firstMessage():
#clear prospects from array and readData from google sheet
clearProspects()
readData(sheet)
#loop through prospects and send first message
for user in prospect_array:
#check if we already messaged the prospect. If we haven't, execute function
if(messageCount(user.id) == 0):
await client.send_message(user.id, 'Hi')
second_touch_array.append(prospect(user.name, user.company, user.id))
print("First Message Sent!")
else:
print("Already messaged!")
async def secondMessage():
for user in second_touch_array:
if(messageCount(user.id) == 1):
await client.send_message(user.id, 'Hello')
third_touch_array.append(prospect(user.name, user.company, user.id))
print("Second Message Sent!")
else:
print("Prospect has already replied!")
async def main():
# Getting information about yourself
me = await client.get_me()
await firstMessage()
await secondMessage()
for user in second_touch_array:
print(user.name, user.company, user.id)
with client:
client.loop.run_until_complete(main())
Anyways, when I run my code i'm successfully getting the "Already Messaged!" print statement in my terminal from the firstMessage function.
This is good - it's detecting I've already messaged the one user on my Google Sheets list; however, my second function isn't being called at all. I'm not getting any print statement and every time I try to print the contents of the second array nothing happens.
If you have any advice it would be greatly appreciated :)

Warn command discord.py postgres sql error

So i made a warn command from a youtube tutorial for my discord bot from https://www.youtube.com/channel/UCBwVvFWzp01YMD9ibqhSkEg
and i got this error
data = await self.bot.db.fetchrow("SELECT * FROM warnlogs WHERE
guild_id = $1 AND member_id = $2", guild_id, member_id)
AttributeError: 'Connection' object has no attribute 'fetchrow'
code:
import datetime
import discord
import asyncpg
from discord.ext import commands
class Warn(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.bot.loop.run_until_complete(self.create_db_pool())
#commands.Cog.listener()
async def on_ready(self):
await self.db.execute(
"CREATE TABLE IF NOT EXISTS warnlogs (guild_id BIGINT, member_id BIGINT, warns TEXT[], times DECIMAL[])")
print("warn system ready")
async def create_db_pool(self):
self.db = await asyncpg.create_pool(database="warn", user="postgres", password="")
#self.bot.db = await asyncpg.create_pool(database_url, ssl="require") when hosting the bot
async def warn_log(self, guild_id, member_id):
data = await self.bot.db.fetchrow("SELECT * FROM warnlogs WHERE guild_id = $1 AND member_id = $2", guild_id, member_id)
if not data:
return []
return data
async def warn_entry(self, guild_id, member_id, reason, times):
data = await self.warn_log(guild_id, member_id)
if data == []:
await self.bot.db.execute("INSERT INTO warnlogs (guild_id, member_id, warns, times) VALUES ($1, $2, $3, $4)", guild_id, member_id, [reason], [times])
return
warns = data[2]
times = data[3]
warns.append(reason)
times.append(times)
await self.bot.db.execute("UPDATE warnlogs SET times = $1, warns = $2 WHERE guild_id = $3 AND member_id = $4", times, warns, guild_id, member_id)
#commands.command()
async def warn(self, ctx, member: discord.Member, *, reason="No reason provided"):
if member == ctx.author or member == self.bot.user:
return await ctx.send("You cant mute yourself or the bot.")
await self.warn_entry(ctx.guild.id, member.id, reason, ctx.message.created_at.timestamp())
await ctx.send(f"{ctx.author.name} has warned {member.name} \nReason: {reason}")
data = await self.warn_log(ctx.guild.id, member.id)
count = len(data[3])
embed = discord.Embed(title=f"Warned by {ctx.author.name}", colour=discord.Colour.red(), timestamp=datetime.datetime.utcnow())
embed.add_field(name="Reason", value=reason)
embed.add_field(name="Total warns", value=f"**{count}** warns\n More than 5 warns a week can have serious consequences.")
embed.set_thumbnail(url=ctx.author.avatar_url)
try:
await member.send(embed=embed)
except:
pass
def setup(bot):
bot.add_cog(Warn(bot))
so is there any way to fix this error if so can you please send the rewritten code it would be very helpful.🙏 And thank you for your time.😊
From what I can see you create connection pool into 'self.db'.
self.db = await asyncpg.create_pool(database="warn", user="postgres", password="")
But then you are calling fetchrow function on 'self.bot.db', which doesn't contain your connection pool. You have to call 'self.db.fetchrow' instead of 'self.bot.db.fetchrow'.
Change this:
data = await self.bot.db.fetchrow("SELECT * FROM warnlogs WHERE guild_id = $1 AND member_id = $2", guild_id, member_id)
For this:
data = await self.db.fetchrow("SELECT * FROM warnlogs WHERE guild_id = $1 AND member_id = $2", guild_id, member_id)
And you should change 'self.bot.db.execute' to 'self.db.execute'.
Once you are hosting bot you will have to uncomment this part:
#self.bot.db = await asyncpg.create_pool(database_url, ssl="require") when hosting the bot
And use 'self.bot.db' instead of 'self.db'.

telethon how to request call with code for login

Since I am writing a client, my friends from the USA noticed that the code does not go through SMS, but only through a call. but I don’t understand how to do it, how to request a call(
await client.connect()
code_settings = types.CodeSettings(
current_number=True,
allow_flashcall=False,
allow_app_hash=False
)
result = await client(functions.auth.SendCodeRequest(
phone_number=phone,
api_id=api_id,
api_hash=api_hash,
settings=code_settings
))
# time.sleep(10)
result = await client(functions.auth.ResendCodeRequest(
phone_number=phone,
phone_code_hash=result.phone_code_hash
))
# time.sleep(20)
result = await client(functions.auth.ResendCodeRequest(
phone_number=phone,
phone_code_hash=result.phone_code_hash
))
# result = await client(SentCodeTypeCall(5))
# result = await client(functions.auth.)
while not isinstance(result.type, SentCodeTypeCall):
# time.sleep(10)
result = await client(functions.auth.ResendCodeRequest(
phone_number=phone,
phone_code_hash=result.phone_code_hash
))
# time.sleep(20)
# await client(functions.auth.SendCodeRequest(
# phone_number=phone,
# api_id=api_id,
# api_hash=api_hash,
# settings=code_settings
# ))
def code_callback():
code = input('Please enter the code you received: ')
return code
time.sleep(5)
await client.start(phone=phone, code_callback=code_callback)
I assume this is not the correct code.
can I tell the SendCode Request method to call immediately without sending SMS?