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)
Related
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)
So I was trying to make my own custom help command
main.py (get_prefix is another function I defined, but that shouldn't be the problem):
bot = commands.Bot(command_prefix = get_prefix, case_insensitive = True, intents = discord.Intents.all())
bot.remove_command("help") # remove the default help command to add a custom one
#bot.group(invoke_without_command = True) # custom help command
async def help(ctx):
await ctx.send(await help_embed(ctx.message))
customhelp.py:
import discord
import typing
async def create_help(cmd: str, desc: str, syntax: typing.List[str], prefix: str, examples: typing.List[str] = None, thumbnail_url: str = None, fields: typing.Dict[str, str] = None):
embed = discord.Embed(title = cmd, description = desc, color = discord.Color.random())
embed.set_thumbnail(url = thumbnail_url)
embed.add_field(name = "syntax", value = f"`{prefix}{syntax}`")
if examples is not None:
example_str = ""
for ex in examples:
example_str += f"\n`{prefix}{ex}`"
embed.add_field(name = "examples", value = example_str[1:])
if fields is not None:
for field in fields:
embed.add_field(name = field, value = fields[field])
return embed
async def help_embed(prefix: str):
return await create_help("help", f"This is a list of all commands. For more details of each command type `{prefix}help <command>`", ["help", "help <command>"], prefix, thumbnail_url = "https://i1.sndcdn.com/avatars-000378178157-omlzp3-t500x500.jpg")
but then when I tested it out on discord my bot sent this:
<discord.embeds.Embed object at 0x7f1552033820>
What is the cause of this problem? And how can I fix it?
Your issue is with how you are using the ctx.send() method, the definition of this method (from the docs) is
await send(content=None, *, tts=False, embed=None, file=None, files=None, delete_after=None, nonce=None, allowed_mentions=None, reference=None, mention_author=None)
As you can see, what you are currently passing to the command is only the content variable, which is typically what the bot will send, but you are passing to it a discord.embeds.Embed object (returned from the help_embed() and create_help functions. content is expecting to be a string, so that's why you see that as your output, it's just printing the object itself.
Now, what you are looking for is to send an embed, to do so, you will need to specify it in the send() command:
#bot.group(invoke_without_command = True) # custom help command
async def help(ctx):
await ctx.send(embed = await help_embed(ctx.message))
i made an avatar command for my bot but it doest work with mentioions, im trying to not use ' #client.command ' because it causes problems for the rest of the code
if message.content.startswith('+avatar'):
sender = message.author
name = sender.display_name
avatar_url = sender.avatar_url
embedVar = discord.Embed(title="**{}**".format(sender), description="Username: {}".format(name), color=0xec9e36)
embedVar.set_image(url = avatar_url)
await message.channel.send(embed=embedVar)
is what i have written and i cant find any ways of making it work, any kind of help would be appreciated!
I am guessing you are trying to do something like
+avatar #mention
A mention is basically a string marking that contains ID of the user.
import re
def is_mention(s):
'''Check if the string is a valid 'mention' string for Discord'''
try:
return bool(re.match(r'<#!?(\d+)>', s))
except Exception:
return None
def mention_to_id(s):
'''Extract user-id from the mention'''
if is_mention(s):
return int(re.sub(r'[<>!#]', '', s))
return None
You can first extract the mention string using mention_str = message.content.split()[1], and then call mention_to_id function to extract the ID from mention string.
After that, call get_user on your bot (client) object to get the user, which will return a User object which has avatar_url field.
To summarize,
if message.content.startswith('+avatar'):
message_parts = message.content.split()
if len(message_parts) > 1:
mention_str = message.content.split()[1]
if is_mention(mention_str):
user = client.get_user(mention_to_id(mention_str)
# do whatever with user.avatar_url
else:
# Warn about invalid mention
else:
# Whatever you want to do when there's no mention
References:
get_user: https://discordpy.readthedocs.io/en/latest/api.html#discord.Client.get_user
User: https://discordpy.readthedocs.io/en/latest/api.html#discord.User
I used message.mentions to find if someone is mentioned in the message and if mentioned i took the mentioned user's name and avatar_url else i took the sender's name and avatar_url
if message.content.startswith('+avatar'):
if( len(message.mentions) > 0 ): #checking if someone is mentioned
#mesage.mentions[0] is the first mentioned user in the message
name = message.mentions[0].display_name
avatar_url = message.mentions[0].avatar_url
else: #no one is mentioned
name = sender.display_name
avatar_url = sender.avatar_url
embedVar = discord.Embed(title="Username: {}".format(name), color=0xec9e36)
embedVar.set_image(url = avatar_url)
await message.channel.send(embed=embedVar)
I am implementing a chat client gui whith server-push functionality. The messages that will be sent will look like this:
yourMessage = {'name': 'David', 'text': 'hello world'}
I recieve a server-push by a call to the streamHandler
def streamHandler(incomingData):
if incomingData["event"] == "put":
if incomingData["path"] == "/":
if incomingData["data"] != None:
for key in incomingData["data"]:
message = incomingData["data"][key]
handleMessage(message)
else:
message = incomingData["data"]
handleMessage(message)
Then I have the function handleMessage that should retrieve the values of name and text:
def handleMessage(message):
for key in message.values():
printToMessages(key)
But now I get this Error: 'str' object has no attribute 'values' I have tried making message to dict but with no success, any ideas?
Perhaps the message parameter is a json string.
If so you can have:
import json
def handleMessage(text):
message = json.loads(text)
for key in message.values():
printToMessages(key)
Alright, So I am using discord.py and JSON and I am trying to make a ticket counter, the client refuses to use a database so I have to use JSON. But every time the code updates the file it create a second key and then it uses that key instead of the first one. If anyone wants to see it happen in action friend me (Jpac14#8237) and I'll show you what happens. I will also attach my code and the JSON file.
Also do you think I could you Collections Module for this.
Code:
from discord.ext import commands
import discord
import json
class TicketSystem(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.create_ticket_msgs = []
#commands.Cog.listener()
async def on_reaction_add(self, reaction, user):
for create_ticket_msg in self.create_ticket_msgs:
if reaction.message.id == create_ticket_msg.id and user != self.bot.user:
await reaction.message.channel.send(f"{user} reacted")
await reaction.message.remove_reaction("📩", user)
ticket_counter_dict = {}
try:
with open("json/ticket_counter.json", "r") as ticket_counter_json:
ticket_counter_dict = json.load(ticket_counter_json)
except json.JSONDecodeError:
print("JSONDecodeError")
current_ticket_counter = ticket_counter_dict.get(str(reaction.message.guild.id))
if current_ticket_counter == None:
current_ticket_counter = 1
ticket_catergory = discord.utils.get(reaction.message.guild.categories, name="Tickets")
if reaction.message.guild.id == 660156957486874645:
support_team_role = discord.utils.get(reaction.message.guild.roles, name="Staff")
else:
support_team_role = discord.utils.get(reaction.message.guild.roles, name="Support")
ticket_channel_overwrites = {
support_team_role: discord.PermissionOverwrite(read_messages=True),
user: discord.PermissionOverwrite(read_messages=True),
reaction.message.guild.default_role: discord.PermissionOverwrite(read_messages=False)
}
users_ticket_channel = await ticket_catergory.create_text_channel(f"ticket-{current_ticket_counter}", overwrites=ticket_channel_overwrites)
current_ticket_counter += 1
ticket_counter_dict.update({reaction.message.guild.id: current_ticket_counter})
with open("json/ticket_counter.json", "w") as ticket_counter_json:
json.dump(ticket_counter_dict, ticket_counter_json)
embedMessage = discord.Embed(description="Support will be with you shortly.\nTo close the ticket type ?close", color=discord.colour.Colour.green())
embedMessage.set_footer(text=f"Created By Nexus Developments - https://discord.gg/YmdugDf", icon_url="https://i.imgur.com/MRBsIpe.png")
await users_ticket_channel.send(embed=embedMessage)
#commands.command(name="ticketmsg")
async def send_create_ticket_msg(self, ctx, channel: discord.TextChannel):
embedMessage = discord.Embed(title="Create A Ticket", description="To create a ticket react with 📩", timestamp=ctx.message.created_at, color=discord.colour.Colour.green())
embedMessage.set_footer(text=f"Created By Nexus Developments - https://discord.gg/YmdugDf", icon_url="https://i.imgur.com/MRBsIpe.png")
create_ticket_msg = await channel.send(embed=embedMessage)
await create_ticket_msg.add_reaction("📩")
self.create_ticket_msgs.append(create_ticket_msg)
def setup(bot):
bot.add_cog(TicketSystem(bot))
JSON File:
{"665930890039394305": 6, "665930890039394305": 7}
reaction.message.guild.id is an int.
When you write ticket_counter_dict.update({reaction.message.guild.id: current_ticket_counter}), you create a new int key in your dict, which doesn't override the str key that exists from loading the json file.
See this example:
import json
d = {1: 'a', '1': 'b'}
json.dumps(d)
>>> '{"1": "b", "1": "a"}'
The dict can hold both 1 and '1' as keys as they are different objects. But the json serialization will turn both into strings, as json uses strings as keys.
I supposed there is room for improvement in the json module as it doesn't seem to check that the stringified keys are all unique.
You can fix your code by making sure you use a string for the key in your dict:
ticket_counter_dict.update({str(reaction.message.guild.id): current_ticket_counter})