Discord.py check if input is int - python

I am trying to write a raffle command for my bot using discord.py and want it so the user can do the following command to start a raffle:
!raffle time winners title EG: !raffle 60 1 Pie
The issue I am having is creating validation to check that the first two inputs are numbers and that the title isn't blank. Currently this is the code I have for the command:
#bot.command(pass_context=True)
async def raffle(ctx, time, winners, title):
if time != int or winners != int or title != "":
await bot.say("{} raffle has been started for {} seconds and there will be {} winner(s)!".format(title, time, winners))
else:
await bot.say("Seems you went wrong! Raffle format is: !raffle time winners title")
return
However I am having no luck and am getting the following error:
Ignoring exception in command raffle
Traceback (most recent call last):
File "C:\Users\kairj\AppData\Local\Programs\Python\Python36-32\lib\site-packages\discord\ext\commands\bot.py", line 846, in process_commands
yield from command.invoke(ctx)
File "C:\Users\kairj\AppData\Local\Programs\Python\Python36-32\lib\site-packages\discord\ext\commands\core.py", line 367, in invoke
yield from self.prepare(ctx)
File "C:\Users\kairj\AppData\Local\Programs\Python\Python36-32\lib\site-packages\discord\ext\commands\core.py", line 345, in prepare
yield from self._parse_arguments(ctx)
File "C:\Users\kairj\AppData\Local\Programs\Python\Python36-32\lib\site-packages\discord\ext\commands\core.py", line 304, in _parse_arguments
transformed = yield from self.transform(ctx, param)
File "C:\Users\kairj\AppData\Local\Programs\Python\Python36-32\lib\site-packages\discord\ext\commands\core.py", line 212, in transform
raise MissingRequiredArgument('{0.name} is a required argument that is missing.'.format(param))
discord.ext.commands.errors.MissingRequiredArgument: time is a required argument that is missing.
Any help would be great as I am sure its a simple mistake somewhere!
Thanks in advance

What you are defining is actually two checks. The first is that you want to ensure there are 3 arguments to your command, and the second is to ensure that the first two are ints.
The first one is actually handled by ext.commands internally. To catch it, you will need to define an on_command_error event method.
#bot.event
def on_command_error(exc, ctx):
if isinstance(exc, commands.errors.MissingRequiredArgument):
# Send a message here
return
# If nothing is caught, reraise the error so that it goes to console.
raise exc
The second is checking the ints, which as #Luke McPuke said is simply
if not isinstance(time, int)

Try using isinstance instead:
if not isinstance(time, int)

Related

Nextcord: How to pass unknown number of variable to subcommand

I'm trying to make a discord bot using subcommand,
it works fine when I do like below:
#admin.subcommand(description="Publish annoucement embed message")
async def annoucement(self, interaction: nextcord.Interaction, announce: str):
print(announce)
But since I want to input unknown number of variable to this function,
I changed my code as below:
#admin.subcommand(description="Publish annoucement embed message")
async def annoucement(self, interaction: nextcord.Interaction, *annouce):
for i in annouce:
print(i)
but after that, it shows error as below:
Ignoring exception in command <nextcord.application_command.SlashApplicationSubcommand object at
0x0000023604828D90>:
Traceback (most recent call last):
Python\Python310\site-packages\nextcord\application_command.py", line 848, in invoke_callback_with_hooks await self(interaction, *args, **kwargs)
Python\Python310\site-packages\nextcord\application_command.py", line 606, in call
return self.callback(self.parent_cog, interaction, *args, **kwargs)
TypeError: Admin_CMD.annoucement() got an unexpected keyword argument 'annouce'
The above exception was the direct cause of the following exception:
nextcord.errors.ApplicationInvokeError: Command raised an exception: TypeError: Admin_CMD.annoucement() got an unexpected keyword argument 'annouce'
I already found a workaround by passing whole string with split character and split them in the
function(ex:str1&str2&str3&...).
But I still want to know what's wrong with my code, and is there a way to pass unkown number of
variable to the subcommand function?

Read a specific line in a file (Python)

I own a discord.py bot. I made a few commands that can create a file with a few simple functions. I have a command who let me read the file, but, I want to improve it. I want that the bot read a specific line of the file. Like if i say +file read test txt 9, the bot will read the file test.txt at line 9.
I use a command group in a cog (cogs/owner.py). The command group called "file" who has a False invoke_without_command() (#commmands.group(invoke_without_command=False))
I tried first to just put the "line" variable in the await ctx.send(f.read(line)), but it didn’t worked.
This is the MRE (minimum reproducible example) of the code:
cogs/owner.py
from discord.ext import commands
import discord
class Owner(commands.Cog):
# the init function
#commands.group(invoke_without_command=False)
async def file(self, ctx):
print="‎ ‎"
#file.command()
async def read(self, ctx, filename, extension, line=None):
if line == None:
f = open(f"{filename}.{extension}", "r")
await ctx.send(f.read())
else:
f = open(f"{filename}.{extension}", "r")
await ctx.send(f.read(line))
"""
also tried this:
await ctx.send(f.read(type(Line)))
""""
#setup function
The read function doesn't understand line numbers. You want something like this:
await ctx.send(f.readlines()[line-1])
... the - 1 is because Python arrays like the array of lines returned by readlines start counting from 0, but text file line numbers usually start at 1.
Though that will blow up with an exception if the file doesn't have that many lines, so you may want to add an except clause to handle that case.

AttributeError: 'list' object has no attribute 'expandtabs'

So, to start, I was making a discord bot (using discord.py) and making a help command, but it shows an error when I run the python file
I have no idea what was going on about this... (\n didn't cause the problem)
code (new one):
#client.command(aliases=["commands","cmds"], description="Get command list")
async def help(ctx):
embed = discord.Embed(title="Commands",description="List of the bot's commands",color=0xFF0000)
for commands in client.commands:
embed.add_field(name=commands,value=commands.description)
await ctx.send(embed)
and full error message:
Traceback (most recent call last):
File "C:\Users\Name\Documents\Codes\Python\bot.py", line 19, in <module>
File "C:\Users\Name\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 1262, in decorator
result = command(*args, **kwargs)(func)
File "C:\Users\Name\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 1433, in decorator
return cls(func, name=name, **attrs)
File "C:\Users\Name\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 244, in __init__
self.description = inspect.cleandoc(kwargs.get('description', ''))
File "C:\Users\Name\AppData\Local\Programs\Python\Python39\lib\inspect.py", line 632, in cleandoc
lines = doc.expandtabs().split('\n')
AttributeError: 'list' object has no attribute 'expandtabs'
would be nice if someone could help me
also, this is my first post (and I'm new here) so I don't know much about Stack Overflow
(PS: I have client.help_command = None in my code, thanks Kermit)
The description argument takes a string, not a list. So, it should look like this:
#client.command(aliases=["commands","cmds"], description="Get command list")
Also, make sure you have client.help_command = None somewhere in your code, so that the default help command provided by discord.py can be overridden.
The immediate issue is that the description kwarg of the command decorator is being given a list when it expects a string, which can be found out from the Command documentation.
However more importantly, as it appears you're trying to create your own help command, that is not the recommended way to do so since you forgo the advantages of the existing HelpCommand framework that handles argument parsing for you. If you need help with using it, check out this guide which goes through subclassing and adding it to your bot.
Sidenote: for future questions, please provide the full error message so it's easier for other users to debug.

Python telegram bot's `get_chat_members_count` & avoiding flood limits or how to use wrappers and decorators

I'm checking a list of around 3000 telegram chats to get and retrieve the number of chat members in each chat using the get_chat_members_count method.
At some point I'm hitting a flood limit and getting temporarily banned by Telegram BOT.
Traceback (most recent call last):
File "C:\Users\alexa\Desktop\ico_icobench_2.py", line 194, in <module>
ico_tel_memb = bot.get_chat_members_count('#' + ico_tel_trim, timeout=60)
File "C:\Python36\lib\site-packages\telegram\bot.py", line 60, in decorator
result = func(self, *args, **kwargs)
File "C:\Python36\lib\site-packages\telegram\bot.py", line 2006, in get_chat_members_count
result = self._request.post(url, data, timeout=timeout)
File "C:\Python36\lib\site-packages\telegram\utils\request.py", line 278, in post
**urlopen_kwargs)
File "C:\Python36\lib\site-packages\telegram\utils\request.py", line 208, in _request_wrapper
message = self._parse(resp.data)
File "C:\Python36\lib\site-packages\telegram\utils\request.py", line 168, in _parse
raise RetryAfter(retry_after)
telegram.error.RetryAfter: Flood control exceeded. Retry in 85988 seconds
The python-telegram-bot wiki gives a detailed explanation and example on how to avoid flood limits here.
However, I'm struggling to implement their solution and I hope someone here has more knowledge of this than myself.
I have literally made a copy and paste of their example and can't get it to work no doubt because i'm new to python. I'm guessing I'm missing some definitions but I'm not sure which. Here is the code below and after that the first error I'm receiving. Obviously the TOKEN needs to be replaced with your token.
import telegram.bot
from telegram.ext import messagequeue as mq
class MQBot(telegram.bot.Bot):
'''A subclass of Bot which delegates send method handling to MQ'''
def __init__(self, *args, is_queued_def=True, mqueue=None, **kwargs):
super(MQBot, self).__init__(*args, **kwargs)
# below 2 attributes should be provided for decorator usage
self._is_messages_queued_default = is_queued_def
self._msg_queue = mqueue or mq.MessageQueue()
def __del__(self):
try:
self._msg_queue.stop()
except:
pass
super(MQBot, self).__del__()
#mq.queuedmessage
def send_message(self, *args, **kwargs):
'''Wrapped method would accept new `queued` and `isgroup`
OPTIONAL arguments'''
return super(MQBot, self).send_message(*args, **kwargs)
if __name__ == '__main__':
from telegram.ext import MessageHandler, Filters
import os
token = os.environ.get('TOKEN')
# for test purposes limit global throughput to 3 messages per 3 seconds
q = mq.MessageQueue(all_burst_limit=3, all_time_limit_ms=3000)
testbot = MQBot(token, mqueue=q)
upd = telegram.ext.updater.Updater(bot=testbot)
def reply(bot, update):
# tries to echo 10 msgs at once
chatid = update.message.chat_id
msgt = update.message.text
print(msgt, chatid)
for ix in range(10):
bot.send_message(chat_id=chatid, text='%s) %s' % (ix + 1, msgt))
hdl = MessageHandler(Filters.text, reply)
upd.dispatcher.add_handler(hdl)
upd.start_polling()
The first error I get is:
Traceback (most recent call last):
File "C:\Users\alexa\Desktop\z test.py", line 34, in <module>
testbot = MQBot(token, mqueue=q)
File "C:\Users\alexa\Desktop\z test.py", line 9, in __init__
super(MQBot, self).__init__(*args, **kwargs)
File "C:\Python36\lib\site-packages\telegram\bot.py", line 108, in __init__
self.token = self._validate_token(token)
File "C:\Python36\lib\site-packages\telegram\bot.py", line 129, in _validate_token
if any(x.isspace() for x in token):
TypeError: 'NoneType' object is not iterable
The second issue I have is how to use wrappers and decorators with get_chat_members_count.
The code I have added to the example is:
#mq.queuedmessage
def get_chat_members_count(self, *args, **kwargs):
return super(MQBot, self).get_chat_members_count(*args, **kwargs)
But nothing happens and I don't get my count of chat members. I'm also not saying which chat I need to count so not surprising I'm getting nothing back but where am I supposed to put the telegram chat id?
You are getting this error because MQBot receives an empty token. For some reason, it does not raise a descriptive exception but instead crashes unexpectedly.
So why token is empty? It seems that you are using os.environ.get incorrectly. The os.environ part is a dictionary and its' method get allows one to access dict's contents safely. According to docs:
get(key[, default])
Return the value for key if key is in the dictionary, else default. If default is not given, it defaults to None, so that this method never raises a KeyError.
According to your question, in this part token = os.environ.get('TOKEN') you pass token itself as a key. Instead, you should've passed the name of the environmental variable which contains your token.
You can fix this either rewriting that part like this token = 'TOKEN' or by setting environmental variable correctly and accessing it from os.environ.get via correct name.

How to extract variable from within a function in Python?

I'm making a program which scrapes bus information from a server and sends it to a user via Facebook messenger. It works fine, but I'm trying to add functionality which splits really long timetables into separate messages. To do this, I had to make an if statement that detects really long timetables, splits them and calls the send_message function from my main file, app.py
Here is the part of the function in app with the variable I need to extract:
for messaging_event in entry["messaging"]:
if messaging_event.get("message"): # someone sent us a message
sender_id = messaging_event["sender"]["id"] # the facebook ID of the person sending you the message
recipient_id = messaging_event["recipient"]["id"] # the recipient's ID, which should be your page's facebook ID
message_text = messaging_event["message"]["text"] # the message's text
tobesent = messaging_event["message"]["text"]
send_message(sender_id, fetch.fetchtime(tobesent))
and here is the if statement in fetch which detects long messages, splits them and calls the send_message function from the other file, app.py:
if len(info["results"]) > 5:
for i, chunk in enumerate(chunks(info, 5), 1):
app.send_message((USER ID SHOULD BE HERE, 'Listing part: {}\n \n{}'.format(i, chunk)))
I'm trying to call the send_message function from app.py, but it requires two arguments, sender_id and the message text. How can I go about getting the sender_id variable from this function and using it in fetch? I've tried returning it and calling the function, but it doesn't work for me.
EDIT:error
Traceback (most recent call last):
File "bus.py", line 7, in <module>
print fetch.fetchtime(stopnum)
File "/home/ryan/fb-messenger-bot-master/fetch.py", line 17, in fetchtime
send_message((webhook(),'Listing part: {}\n \n{}'.format(i, chunk)))
File "/home/ryan/fb-messenger-bot-master/app.py", line 30, in webhook
data = request.get_json()
File "/usr/local/lib/python2.7/dist-packages/werkzeug/local.py", line 343, in __getattr__
return getattr(self._get_current_object(), name)
File "/usr/local/lib/python2.7/dist-packages/werkzeug/local.py", line 302, in _get_current_object
return self.__local()
File "/usr/local/lib/python2.7/dist-packages/flask/globals.py", line 37, in _lookup_req_object
raise RuntimeError(_request_ctx_err_msg)
RuntimeError: Working outside of request context.
This typically means that you attempted to use functionality that needed
an active HTTP request. Consult the documentation on testing for
information about how to avoid this problem.

Categories