How to detect number in certain range - discord.py

Trying to get bot to send a message when the person sends a message in range
async def on_message(message):
if 0 < Message < 100 in message.content:
await bot.message.send(message.channel, "you are in Bronze 1")

Ok first of all. Please don't code on mobile. Especially not python. That will mess things up way too much.
Second, please define your variables properly. Message is not a defined variable. It will return an error.
So, as you said, you wanted two ways to do this. The number should be the message itself, or within the message.
For the first example, all you have to do is cast the message.content to int. Then you can check if it's in the range.
if 0 < int(message.content) < 100:
...
For the second example, you will have to do something similar, however, you should split the entire message.content string and convert the number ones into integers. I'm assuming that the number will not be within a word and it will be by itself.
for word in message.content.split():
if word.isnumeric():
num = int(word)
if 0 < num < 100:
... # return and send message to avoid spamming

Related

Catch multiple exceptions with specific error messages leading to one exit command

I'm trying to create a program that prompts the user for their weight in pounds as a float, when entered I need to check the entry to ensure that it is not a string or below the value of 10. It needs to be done in an if statement and not a loop, as well I need to be able to end multiple exceptions with one quit() statement instead of multiple quit() statements for each exception and then continue the program further if the user entered the input in the correct parameters.
This is what I have so far:
isvalid = float,int
try:
weight_pounds = float(input("Enter your weight in pounds: ")
if weight_pounds != isvalid:
print("Cannot be alphabetical.")
elif weight_pounds < 10:
print("Cannot be less than 10.")
else:
input("Press enter to exit...")
quit()
I am still learning basic functions of python and I may be missing something simple here but I've tried many ways to get this to work and I can't seem to get it working without either a dead end or ValueErrors.

How to make bot reply in a single message?

I want to make my bot respond in a single message, but because of the for loop it replies 10 times in 10 different messages. My code is:
#bot.command(name='translate', help='- Translates text to a random language!')
async def translating(ctx, thing):
translator = Translator()
for i in range(0, 10):
translation = translator.translate(thing, dest=str(random.choice(list_language_unicodes)))
await ctx.reply(translation.text)
The code takes a string and translates it to 10 random different languages if somebody was interested. My problem is only with the bot NOT replying in a SINGLE message. I'm a beginner so i probably won't understand much but still.
Solution: I concatenated the strings and reset at the end of the loop because the translations kept stacking:
for i in range(0, 10):
translation = translator.translate(thing, dest=str(random.choice(list_language_unicodes)))
finalny_tekst = finalny_tekst + translation.text + "\n"
await ctx.reply(finalny_tekst)
finalny_tekst = ""
Thanks for assistance!

message.reaction.count Discord py

I'm trying to make a simple bot that would only react to messages with attachments. Then after a certain time, it would make a link to the message and send it on a moderation channel if it got 2 or more reactions.
#client.event
async def on_message(message):
if message.channel.id == 828579458167996420:
if message.attachments or "http" in message.content:
msgID = message.id
await message.add_reaction("<:uut:828580756384120912>")
await asyncio.sleep(200)
x = int
if message.reactions.count(x) >= 3:
link = 'https://discord.com/channels/11223345678900/828579458167996420/' + str(msgID)
channel = client.get_channel(892065611876823100)
x = x - 1
await channel.send("this post " + str(link) + "is liked " + str(x) + "times." )
the bot reacts to the messages i want, but it doesn't post anything in the moderation channel
I'm a beginner, sry for the messy codes :\
If you are not getting any kinds of errors, the issue lays right here, the if statement never gets triggered:
x = int
if message.reactions.count(x) >= 3:
message.reactions will return a list, your statement would count how many times x is in that list (which is always zero).
What you wanna do instead is just to get the total length of that list, like this:
if len(message.reactions) >= 3:
Also other small improvement tip: You can get the URL of a message with message.jump_url
EDIT:
Sorry, what you actually need to do to get the reaction count is to either search the emoji you want to count, or the shortcut would be to just get the first reaction in that list, since your bot should be the first to react to that message anyways:
#this will return a list of reactions that match the emoji you want
emoji = [x for x in message.reactions if str(x.emoji) == '😂'] #replace the emoji with the one you want
print(emoji[0].count) #counts the first (and only) emoji in the new list
"Shortcut" version, just gets the first reaction count:
print(message.reactions[0].count)

How do I prevent multiple discordrb bot activations being processed out of sequence?

I have a Ruby Discord (discordrb) bot written to manage D&D characters. I notice when multiple players submit the same command, at the same time, the results they each receive are not independent. The request of one player (assigning a weapon to their character) ends up being assigned to other characters who submitted the same request at the same time. I expected each request to be executed separately, in sequence. How do I prevent crossing requests?
bot.message(contains:"$Wset") do |event|
inputStr = event.content; # this should contain "$Wset#" where # is a single digit
check_user_or_nick(event); pIndex = nil; #fetch the value of #user & set pIndex
(0..(#player.length-1)).each do |y| #find the #player pIndex within the array using 5 char of #user
if (#player[y][0].index(#user.slice(0,5)) == 0) then pIndex = y; end; #finds player Index Value (integer or nil)
end;
weaponInt = Integer(inputStr.slice(5,1)) rescue false; #will detect integer or non integer input
if (pIndex != nil) && (weaponInt != false) then;
if weaponInt < 6 then;
#player[pIndex][1]=weaponInt;
say = #player[pIndex][0].to_s + " weapon damage has be set to " + #weapon[(#player[pIndex][1])].to_s;
else;
say = "Sorry, $Wset requires this format: $Wset? where ? is a single number ( 0 to 5 )";
end;
else
say = "Sorry, $Wset requires this format: $Wset? where ? is a single number ( 0 to 5 )";
end;
event.respond say;
end;
To avoid race conditions in multithreaded code like this, the main thing you want to look for are side effects.
Think about the bot.message(contains:"$Wset") do |event| block as a mini program or a thread. Everything in here should be self contained - there should be no way for it to effect any other threads.
Looking through your code initially, what I'm searching for are any shared variables. These produce a race condition if they are read/written by multiple threads at the same time.
In this case, there are 2 obvious offenders - #player and #user. These should be refactored to local variables rather than instance variables. Define them within the block so they don't affect any other scope, for example:
# Note, for this to work, you will have to change
# the method definition to return [player, user]
player, user = check_user_or_nick(event)
Sometimes, making side effects from threads is unavoidable (say you wanted to make a counter for how many times the thread was run). To prevent race conditions in these scenarios, a Mutex is generally the solution but also sometimes a distributed lock if the code is being run on multiple machines. However, from the code you've shown, it doesn't look like you need either of these things here.

Printing in while loop, clearing previous iteration prints

I have the following code:
print("Hi there!")
def inputyournumber():
while True:
num = input("your number is?:")
if int(num) <100:
break
return
The output is:
Hi there!
your number is?: 101
your number is?: 1002
your number is?: 100
your number is?: 99
i just want the initial prints: and the final output until a correct input is entered:
Hi there!
your number is?: 99
Erasing the initially wrong inputs, but keeping the prints prior the loop. Is it possible? Or do i have to reprint them? My issue in just clearing everything then reprint the prior texts together with the correct input is that it may consume more time for more complex part of the code with similar problem.
Do you mean it only print out the number you entered when the number you enter is 100?
First, the input you get, will be a string, so the comparison won't work.
maybe this is what you wanted?
def printnum():
while True:
print('Hi there!')
num = input("your number is: ")
if num != '100':
continue
break
print(num)
printnum()

Resources