I'm trying to create a telegram bot with telethon that uses inline buttons and can't seem to figure out how to edit my messages after a button is pressed. I have something like this to start:
#bot.on(events.NewMessage(pattern='/start'))
async def send_welcome(event):
await bot.send_message(event.from_id, 'What food do you like?', buttons=[
Button.inline('Fruits', 'fruit'),
Button.inline('Meat', 'meat')
])
#bot.on(events.CallbackQuery(data='fruit'))
async def handler(event):
await bot.edit_message(event.from_id, event.id, 'What fruits do you like?', buttons=[
Button.inline('Apple', 'apple'),
Button.inline('Pear', 'pear'),
...
])
After clicking on the Fruits button, nothing happens. Would love some help on this!
Like this u can edit
message = await client.send_message(chat, 'hello')
await client.edit_message(chat, message, 'hello!')
# or
await client.edit_message(chat, message.id, 'hello!!')
# or
await client.edit_message(message, 'hello!!!')
from the official documentation of telethon
May I suggest a solution.
It implements the exact idea of mr. Snowman's question. But it might be useful to place conditions inside the handler.
from telethon import TelegramClient, sync, events, Button
api_id = xxx
api_hash = 'xxx'
bot = TelegramClient('session', api_id, api_hash)
#bot.on(events.NewMessage(pattern='/start'))
async def send_welcome(event):
await bot.send_message(event.sender_id,
'What food do you like?',
buttons=[
Button.inline('Fruits', 'fruit'),
Button.inline('Meat', 'meat')
]
)
#bot.on(events.CallbackQuery(data='fruit'))
async def handler(event):
await bot.edit_message(event.sender_id, event.message_id,
'What fruits do you like?',
buttons=[
Button.inline('Apple', 'apple'),
Button.inline('Pear', 'pear')
]
)
bot.start()
bot.run_until_disconnected()
Related
Hello I began a discord bot but I can't give the message's content. I managed to get all the other things about message but the content return nothing. here is the code(ps: sorry if my english isn't very good, i'm French) :
import discord
class MyClient(discord.Client):
async def on_ready(self):
print('Logged in as')
print(self.user.name)
print(self.user.id)
print('------')
async def on_message(self, message: discord.message.Message):
# we do not want the bot to reply to itself
print(message.id)
if message.author.id == self.user.id:
return
if message.content.startswith('!hello'):
print('ok')
await message.channel.send('Hello {0.author.mention}'.format(message))
defIntents = discord.Intents.default()
defIntents.members = True
client = MyClient(intents=defIntents)
client.run('token')
You have to enable the Message Content Intent of your application from Discord Developer Portal and in your code you have to set the message_content intent to True like this.
defIntents = discord.Intents.default()
defIntents.members = True
defIntents.message_content = True
client = MyClient(intents=defIntents)
I have a loop that creates cards from videos I've pulled from a site. I've added inline buttons to these cards that let you watch videos, comment, and learn more. I need to create a callback_handler for each inline button (I've settled on the "Перегляд" - "View" button for now) and then capture the selection in the state to then select a possible video player and quality. Since the id is created automatically, manually writing handlers for a million possible videos is unrealistic, so I want to know if it is possible to somehow automate this process, or please offer a more concise solution. I tried to create a callback_handler inside another handler, but when I try to click the view button, I get a response only from the last card.
example
I'm sorry if I submitted an incorrect question. Write, I will explain the idea better.
from aiogram import types
from loader import dp
from states import Search
from aiogram.dispatcher import FSMContext
from keyboards.inline_commands.inline_commands import get_video_from_site
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
#dp.callback_query_handler(text='search')
async def send_message(call: types.CallbackQuery):
await call.message.answer(f'Введи назву аніме, наприклад: \"Сайтама\" 🦸')
await Search.name.set()
#dp.message_handler(state=Search.name)
async def state1(message: types.Message, state: FSMContext):
# name_anime = call.message.text
name_anime = message.text
await state.update_data(name=name_anime)
data = await state.get_data()
videocards = await get_video_from_site(data.get('name'))
for i in range(0, len(videocards['img'])):
link_id = videocards["link"][i].split("/")[3].split("-")[0]
await message.answer_photo(photo=videocards['img'][i],
caption=f'<b>{videocards["name"][i]}</b>'
f'\n\n'
f'{"".join(videocards["desc"][i][0:170])}....',
reply_markup=InlineKeyboardMarkup(row_width=2,
inline_keyboard=[
[
InlineKeyboardButton(text=f'Перегляд id={link_id}',
callback_data=f'{link_id}-watch'),
InlineKeyboardButton(text='Коменти',
callback_data=f'{link_id}-comm')
],
[
InlineKeyboardButton(text='Більше',
callback_data=f'{link_id}-more')
]
]))
# await message.answer('Тепер вибери аніме, яке хочеш')
# await Search.choose_button.set()
#dp.callback_query_handler(text=f'{link_id}-watch')
async def get_video(call: types.CallbackQuery, state: FSMContext):
await call.message.answer(videocards["link"][i])
await state.finish()
I'm making a discord bot that worked fine but I wanted to start using cogs because I thought it was a nicer way to write my code but now my on_message doesn't work any more and it doesn't show any error messages I searched how to fix it in the whole internet and all explanations didn't work for me so I decided to ask here. So here is my code:
from discord.ext import commands
TOKEN = 'my token'
bot = commands.Bot(command_prefix="$")
class Interactions(commands.Cog):
#commands.Cog.listener()
async def on_message(self, message):
msg = message.content
hi = ["hi", "hello", "hi!", "hello!"]
bye = ["bye", "good bye", "bye!", "good bye!"]
# Messages in english
if str(msg).lower() in hi:
await message.channel.send('Hello!')
if str(msg).lower == 'how are you?':
await message.channel.send("I'm fine")
if str(msg).lower == "what's your favorite food?":
await message.channel.send("Sushi with sweet potato!")
if str(msg).lower == "what do you eat?":
await message.channel.send(
"I don't eat, I'm just a simple bot :pensive:")
if str(msg).lower == "are you fine?":
await message.channel.send("Yes, I am")
if str(msg).lower in bye:
await message.channel.send("Good bye!")
def run():
bot.add_cog(Interactions(bot)
bot.run(TOKEN)
if __name__ == "__main__":
run()
Import:
from discord.ext.commands import command, Cog
Rest of the code:
TOKEN = 'my token'
bot = commands.Bot(command_prefix="$")
class Interactions(commands.Cog):
#commands.Cog.listener()
async def on_message(self, message):
pass
This should work, if not just ping me ;)
I am making a simple bot, all I want it to do is wait for me to type a command with an argument (a vc), so for example when I type !channel general, the bot will return a list of the members in that channel. So if Bob and Jeff are in General the bot will return member_list = ['Bob', 'Jeff'] Any easy way to do that?
Update:
import discord
import os
from discord.ext import commands
client = discord.Client()
bot = commands.Bot(command_prefix='$')
#client.event
async def on_ready():
print('We have logged in as {0.user}'.format(client))
#bot.command()
async def members(ctx, channel: discord.VoiceChannel):
member_list = [i.name for i in channel.members]
print(member_list)
await ctx.send(member_list) # or return member_list whatever you want
client.run(os.getenv('TOKEN'))
Here's my code up above, when I run bot it does not do anything when I type $members general, anyone know what I'm doing wrong?
Use VoiceChannel.members
#bot.command()
async def members(ctx, channel: discord.VoiceChannel):
member_list = [i.name for i in channel.members]
await ctx.send(member_list) # or return member_list whatever you want
I'm running a discord.py bot and I want to be able to send messages through the IDLE console. How can I do this without stopping the bot's other actions? I've checked out asyncio and found no way through.
I'm looking for something like this:
async def some_command():
#actions
if input is given to the console:
#another action
I've already tried pygame with no results but I can also try any other suggestions with pygame.
You can use aioconsole. You can then create a background task that asynchronously waits for input from console.
Example for async version:
from discord.ext import commands
import aioconsole
client = commands.Bot(command_prefix='!')
#client.command()
async def ping():
await client.say('Pong')
async def background_task():
await client.wait_until_ready()
channel = client.get_channel('123456') # channel ID to send goes here
while not client.is_closed:
console_input = await aioconsole.ainput("Input to send to channel: ")
await client.send_message(channel, console_input)
client.loop.create_task(background_task())
client.run('token')
Example for rewrite version:
from discord.ext import commands
import aioconsole
client = commands.Bot(command_prefix='!')
#client.command()
async def ping(ctx):
await ctx.send('Pong')
async def background_task():
await client.wait_until_ready()
channel = client.get_channel(123456) # channel ID to send goes here
while not client.is_closed():
console_input = await aioconsole.ainput("Input to send to channel: ")
await channel.send(console_input)
client.loop.create_task(background_task())
client.run('token')