I'm building a Telegram bot using pyTelegramBotAPI and I'm facing a problem that it's always returning the second function even when I send a text that doesn't exist.
My code is:
import os
import telebot
import requests
from eletronic.light import turnofflight, turnonlight
bot = telebot.TeleBot(os.getenv('BOT_TOKEN'))
#bot.message_handler(commands=["hello"])
def greeting(message):
bot.reply_to(message, "Hello")
#bot.message_handler(func=lambda temp: temp.text is not None and 'weather' or 'Weather' in temp.text)
def verify_weather(message):
blumenau = requests.get('https://wttr.in/Blumenau?format=3')
bot.reply_to(message, 'text'+blumenau.text)
#bot.message_handler(func=lambda on: on.text is not None and 'on' or 'On' in on.text)
def botturnonlight(message):
turnonlight()
bot.reply_to(message, "text")
#bot.message_handler(func=lambda off: off.text is not None and 'off' or 'Off' in off.text)
def botturnofflight(message):
turnofflight()
bot.reply_to(message, "text")
def verify(message):
return True
#bot.message_handler(func=verify)
def answer(message):
text = """
Text"""
bot.reply_to(message.chat.id, text)
bot.infinity_polling()
That's probably something pretty simple there that I can't see what is it. Could someone help?
Thanks!!
This code be fixed removing the is not None from the bot's decorator in each function like:
#bot.message_handler(func=lambda on: on.text == 'on' or 'On' in on.text)
Related
I'm working on a simple dictionary accessible through a telegram bot.
This is my code in Python, what am I wrong?
#!/usr/bin/python3
import telebot
API_TOKEN = 'MY TELEGRAM TOKEN'
bot = telebot.TeleBot(API_TOKEN)
Dizio={'cat': 'blue', 'dog': 'red', 'fly': 'black'}
# Handle all other messages with content_type 'text' (content_types defaults to ['text'])
#bot.message_handler(func=lambda message: True)
def echo_message(message):
if message.text.lower() in Dizio.keys():
res = Dizio.get('translate', {}).get('=')
bot.send_message(message.chat.id, message.text(res))
else:
bot.send_message(message.chat.id, 'not found')
bot.infinity_polling()
There are a couple of problems inside the echo_message function:
You aren't using correctly the dict.get method;
you are calling message.text, this is a string, and you can't call strings;
Here's how i would resolve this problem, we can use the fact that dict.get allows us to provide a default value if the key is missing:
def echo_message(message):
res = Dizio.get(message.text.lower(), "not found")
bot.send_message(message.chat.id, res)
I'm trying to get it so I can add links in text rendered by Textual.
My text may have multiple links, for example:
Hello [#click=hello]World[/] there, how are you?
This is a test of [#click=more] more info[/] being clickable as well.
In this simple sample I made, clicking on the word "World" should hopefully change the background color to red, but it doesn't work.
NOTE: I also bound the "b" key to do pretty much the same thing, so I could see it work
It should change the background color, and the subtitle of the app.
import os
import sys
from rich.console import RenderableType
from rich.panel import Panel
from rich.text import Text
from textual.app import App
from textual.widgets import Header, Footer, ScrollView
from textual.widgets import Placeholder
class MyApp(App):
async def on_load(self) -> None:
await self.bind("b", "color('blue')")
async def on_mount(self) -> None:
await self.view.dock(Header(), size=5, edge="top")
await self.view.dock(Footer(), edge="bottom")
await self.view.dock(ScrollView(Panel("Hello [#click=hello]World[/] more info here")), edge="top")
async def action_color(self, color:str) -> None:
self.app.sub_title = "KEYBOARD"
self.background = f"on {color}"
async def action_hello(self) -> None:
self.app.sub_title = "CLICKED"
self.background = "on red"
MyApp.run(title="Test click", log="textual.log")
I asked this same question in the textual discussions and originally rich discussions, but haven't been able to see how to make this work from the feedback I received there, which was helpful for sure, but I'm missing something here, so thanks for any input.
It seems like #click=action doesn't work in textual (at least I couldn't make it work at all).
After digging up in rich documentation, I stepped upon Text class. That one, has on method, that can create click callback.
It supports __add__, so You can concat multiple Text(s) together with + operator.
Second piece of the puzzle was to find out what to set as a click callback. Again I looked in the source code and found _action_targets in app.py. That contains {"app", "view"} set.
Putting all together, You can create link(s) using Text with on(click="app.callback()"), which will call action_callback method of MyApp Class (instance of textual App). Then creating final panel text by concating other Text(s) and link(s) together.
Here is working example, turning background to red clicking on Hello or green clicking on World.
from rich.panel import Panel
from rich.text import Text
from textual.app import App
from textual.widgets import Header, Footer, ScrollView
class MyApp(App):
async def on_load(self) -> None:
await self.bind("b", "color('blue')")
async def on_mount(self) -> None:
await self.view.dock(Header(), size=5, edge="top")
await self.view.dock(Footer(), edge="bottom")
link1 = Text("Hello").on(click="app.hello()")
link2 = Text("World").on(click="app.world()")
panel_text = link1 + " " + link2 + Text(" more info here")
await self.view.dock(ScrollView(Panel(panel_text)), edge="top")
async def action_color(self, color: str) -> None:
self.app.sub_title = "KEYBOARD"
self.background = f"on {color}"
async def action_hello(self) -> None:
self.app.sub_title = "CLICKED Hello"
self.background = "on red"
async def action_world(self) -> None:
self.app.sub_title = "CLICKED World"
self.background = "on green"
MyApp.run(title="Test click", log="textual.log")
I know it's not ideal solution, but it's closest I could get to what You want.
You can also make a text with different properties with Text.assemble():
async def on_mount(self) -> None:
await self.view.dock(Header(), size=5, edge="top")
await self.view.dock(Footer(), edge="bottom")
panel_text = Text.assemble(
"Hello ",
Text("World","dark_blue u").on({"#click" : "app.hello()"}),
" more ",
Text("info","dark_blue u").on({"#click" : "app.color('blue')"}),
" here")
await self.view.dock(ScrollView(Panel(panel_text)), edge="top")
I'm currently coding a quizz bot and I came up with this code:
class answers(nextcord.ui.View):
def __init__(self, ans1, ans2, ans3):
super().__init__(timeout=None)
self.ans1 = ans1
self.ans2 = ans2
self.ans3 = ans3
self.value = False
#nextcord.ui.button(label = '1', custom_id="1", style = nextcord.ButtonStyle.red)
async def reaction(self, button: nextcord.ui.Button, interaction: nextcord.Interaction):
await interaction.response.send_message('ans1')
self.value = True
self.stop()
#nextcord.ui.button(label='2', custom_id='2' )
async def reaction(self, button: nextcord.ui.Button, interaction: nextcord.Interaction):
await interaction.response.send_message('ans2')
self.value = True
self.stop()
#nextcord.ui.button(label='3', custom_id='3')
async def reaction(self, button: nextcord.ui.Button, interaction: nextcord.Interaction):
await interaction.response.send_message('ans3')
self.value = True
self.stop()
This is the class that should display 3 buttons. However it displays only the third one. I do not get any errors.
How can I write this code so it does display all three?
You'll need to use different method names for each of the buttons. Changing the names to reaction1, reaction2, reaction3 would fix your issue.
The reason is the ui.button decorator doesn't store the button info elsewhere, instead it attaches the relevant info onto the method and returns the method back. So having the same name for the three method, you're actually reassigning answers.reaction every time you define a button, and only the last one gets kept. discord.py only evaluates all of the components from a view at runtime, so the last button is all it sees—thus it only displays the last button.
So I'm working on a command called "Catjam" where it repeats what the user just said, with catjam emojis in between. Here's my code:
#client.command()
async def catjam(ctx, *, text):
await ctx.send(f"<a:catjam:799725698595946526>{text}<a:catjam:799725698595946526>")
This is what the command looks like in action:
That is fine, but I want it to look like this:
Not sure how to accomplish that, any tips?
Here's a way:
>>> message = "whatever"
>>> new_message = ""
>>>
>>> for char in message:
... new_message += f"✅{char}"
...
>>>
>>> new_message += "✅"
>>> new_message
'✅w✅h✅a✅t✅e✅v✅e✅r'
after trying so many thing I came up with the idea to ask you intelligent people out there! I want to blacklist 3 roles for a single command. But everything I tried failed.
Here's the code I wrote:
member = ctx.message.author
roleA = get(member.guild.roles, name="Rote Birdys")
roleB = get(member.guild.roles, name="Grüne Birdys")
roleC = get(member.guild.roles, name="Blaue Birdys")
if commands.has_any_role(roleA, roleB, roleC):
return
Nothing worked, I tried some more things but they didn't work either. May I'm really stupid but I need to finish this projekt in a few weeks and I'm stuck here.
I hope you can help me :)
This is just the has_any_role check but backwards. I also created a new error like MissingAnyRole:
from discord.ext.commands import check, CheckFailure
import discord.utils
class HasForbiddenRole(CheckFailure):
def __init__(self, forbidden_roles):
self.forbidden_roles = forbidden_roles
forbidden= ["'{}'".format(role) for role in forbidden_roles]
if len(missing) > 2:
fmt = '{}, or {}'.format(", ".join(forbidden[:-1]), forbidden[-1])
else:
fmt = ' or '.join(forbidden)
message = "You have at least one of the forbidden roles: {}".format(fmt)
super().__init__(message)
def lacks_every_role(*items):
def predicate(ctx):
if not isinstance(ctx.channel, discord.abc.GuildChannel):
raise NoPrivateMessage()
getter = functools.partial(discord.utils.get, ctx.author.roles)
if not any(getter(id=item) is not None if isinstance(item, int) else getter(name=item) is not None for item in items):
return True
raise HasForbiddenRole(items)
return check(predicate)
Usage would be like any of the other checks:
#lacks_every_role("Rote Birdys", "Grüne Birdys", "Blaue Birdys") # You could also use role ids
#bot.command()
async def comm(ctx):
...