how to make amount thing in discord.py - discord.py

alrighty so basically i had a spam ping command that i made and i wanted to make it with an amoutn like this
#commands.command(
name="ping",
description="boom boom boom",
usage="<user> <amount>",
)
#commands.has_permissions(manage_roles=True)
async def ping(self, ctx, member: discord.Member, amount=15):
if amount is None:
await ctx.send('listen here bud your lucky this exists but your the reason that theres instuctions on conditioner bottles, specify a user')
else:
await ctx.send(f"{member.mention}"+amount)
butthat doesnt work and i know i messed up cause i cant code
also the indents may be of on here :3 anyone knowhow to fix?

The + amount will not do anything. It will just enter #user 4 if the number they gave in was 4. If you wanted to do it so that it spammed the user via mentions in 4 seperate messages, this is how you should go through with it:
#commands.command(
name="ping",
description="boom boom boom",
usage="<user> <amount>",
)
#commands.has_permissions(manage_roles=True)
async def ping(self, ctx, member: discord.Member, amount=15):
if amount is None:
await ctx.send('listen here bud your lucky this exists but you\'re the reason that there\'s instuctions on conditioner bottles, specify a user')
else:
for i in range(amount):
await ctx.send(f'Pinging {member.mention} for the {i} time.')
In the end, this should send something a bit like this:
Me: .ping #user 5
Bot: Pinging #user for the 1 time
Pinging #user for the 2 time
Pinging #user for the 3 time
Pinging #user for the 4 time
Pinging #user for the 5 time

Related

'AsyncTeleBot' object has no attribute 'register_next_step_handler'

Trying to create simple ask, answer, remember telegram bot with pyTelegramBot.
Everything were normal, when TeleBot were used. TeleBot.register_next_message_handler helped me a lot.
Example:
...
#bot.message_handler(func=lambda msg: msg.text is not None and '/start' in msg.text)
def send_welcome(msg):
global cur_user
cur_user = msg.from_user.id
keyboard = types.InlineKeyboardMarkup()
keyboard.add(types.InlineKeyboardButton('Да', callback_data='old'),
types.InlineKeyboardButton('Нет', callback_data='new'))
keyboard.add(types.InlineKeyboardButton('Пора остановиться', callback_data='stop_bot'))
greet = 'Бла...бла...бла\nМы знакомы?'
bot.send_message(msg.chat.id, greet, reply_markup=keyboard)
...
#bot.callback_query_handler(func=lambda call: True)
def query_processing(call):
global user
global cur_user
if call.data == 'new':
user = dict.fromkeys(user, None)
nxt = bot.send_message(call.message.chat.id, 'Как звать?')
bot.register_next_step_handler(nxt, get_name_ask_goal)
...
Still I need my bot to be asynchronous because of sleep time till message to be send from bot and with simultaneous possibility for user to send messages.
Tried to use AsyncTeleBot, but there is no register_next_step_handler function. I did't find out how to make bot wait user for the name typing and it is almost impossible to me to add register_next_step_handler function into particular files. Although found issue in gitHub and no solution from 2017.
Tried
...
bot = AsyncTeleBot(os.getenv('token2'))
...
async def beep(chat_id) -> None:
"""Send the beep message."""
await bot.send_message(chat_id, text='Beep!')
aioschedule.clear(chat_id)
async def scheduler():
global chat_id
aioschedule.every(5).seconds.do(beep, chat_id).tag(chat_id)
while True:
await aioschedule.run_pending()
await asyncio.sleep(1)
async def main():
await asyncio.gather(scheduler(), bot.polling(non_stop=True))
if __name__ == "__main__":
asyncio.run(main(), debug=True)
...
Result:
TypeError: An asyncio.Future, a coroutine or an awaitable is required
I'm wondering:
is there other appropriate libraries for my task?
is there any simple solution to save user's message?
is it possible to use asyncio with TeleBot that made Thread-style?
Hoping for any help.

Delete multiple messages

Well im creating a discord bot right now and i wanted to add a feature that it deletes messages.
Basically the bot waits for a message to pop up, if this message contains a given command,
in this case "sudo clean (number)", it deletes (number) messages (so if the number is 5 it deletes 5 messages). Well i mean its supposed to do that but yea its not doing what its supposed to do.
I get discord.errors.NotFound: 404 Not Found (error code: 10008): Unknown Message
Thats my code:
elif message.content.lower().startswith("sudo clean"):
userMessage = message.content
message.delete()
for word in userMessage.split():
if word.isdigit():
textToClean = int(word)
for i in range(0, textToClean):
await message.delete()
Whats the Problem?
here is what I use that's a lot easier if you don't want anything fancy
#client.command(name="clear",
brief="Deletes a certain amount of messages ex. .clear 10")
async def clear(ctx, amount=5):
amount += 1
await ctx.channel.purge(limit=amount)
Here is a pretty simple implementation using slash commands, which i currently use.
#commands.slash_command(description='Delete messages from a channel.')
#commands.has_permissions(manage_messages=True)
async def purge(
self,
inter,
amount: int
):
"""Delete a certain amount of messages in the chat
Parameters
----------
amount: The amount of messages you want to delete, can't be greater than 100
"""
if amount > 100:
await inter.send("Wow, take it easy, no more than 100 messages at a time", ephemeral=True)
return
await inter.channel.purge(limit=amount, check=lambda msg: not msg.pinned)
await inter.send('Messages deleted.', ephemeral=True)
Of course, if you don't use slash commands can be easily turned into a regular prefix command
#commands.command()
#commands.has_permissions(manage_messages=True)
async def purge(
self,
ctx,
amount: int
):
"""Delete a certain amount of messages in the chat
Parameters
----------
amount: The amount of messages you want to delete, can't be greater than 100
"""
if amount > 100:
await ctx.send("Wow, take it easy, no more than 100 messages at a time")
return
await ctx.channel.purge(limit=amount, check=lambda msg: not msg.pinned)
await ctx.send('Messages deleted.')
The check is for avoiding Pinned messages

How to change channel permissions without having a message sent first?

I have a program that changes what channel members can see at certain times of the day. To do this, I can either change the roles that every member has, or change the permissions of each channel. However, I have looked all over the web and all of the ways for either method require a message to be sent so that the data from that message can be read and put into the function, such as:
#client.command()
async def perm(ctx):
await ctx.channel.set_permissions(ctx.guild.default_role, send_messages=False
Change the permissions of a discord text channel with discord.py
or
async def addrole(ctx):
member = ctx.message.author
role = get(member.server.roles, name="Test")
await bot.add_roles(member, role)
Discord.py | add role to someone
My current program looks like this:
import discord
client = discord.Client()
import datetime
async def live_day(schedule):
current_place = "the void"
while True:
current_time = str((datetime.datetime.now() -datetime.timedelta(hours=7)).time())
int_time = int(current_time[:2] + current_time[3:5])
for x in range(len(schedule)):
try:
start_time = schedule[x][1]
end_time = schedule[x + 1][1]
except IndexError:
end_time = 2400
if current_place != schedule[x][0] and int_time >= start_time and int_time < end_time:
current_place = schedule[x][0]
#Change the channel permissions of the current place to allow viewing
#Change the channel permissions of the last channel to disallow viewing
#client.event
async def on_ready():
print("{0.user} has arrived for duty".format(client))
client.loop.create_task(live_day([
("Home", 0),
("Work", 900),
("Home", 1700),
("Nightclub", 2000),
("Home", 2200),
]))
client.run(my_secret)
Never mind the badly written code, how would I do this or where should I go to figure this out? Any help is appreciated. Thanks!
Edit: I could get the channels individually by using this,
channel1=client.get_channel(channelid)
discord.py, send message by channel id without on_message() event?
but then I can't use this for more than one server. How can I get channels by name?
Note on on_ready():
This function is not guaranteed to be the first event called. Likewise, this function is not guaranteed to only be called once. This library implements reconnection logic and thus will end up calling this event whenever a RESUME request fails.
Using this function may crash the bot.
Instead create background tasks and use wait_until_ready().
You can find examples in https://github.com/Rapptz/discord.py/blob/v1.7.3/examples/background_task.py
If you want to change only one channel's permissions (per guild) this might fit your needs:
#changing "Home" channel visibility, every day at 5 pm.
#client.event
async def on_ready():
while True:
await asyncio.sleep(1)
current_time = datetime.datetime.now()
five_pm = current_time.replace(hour=17, minute=0, second=0)
if current_time == five_pm:
for guild in client.guilds: #looping through all the guilds your bot is in
channel = discord.utils.get(client.get_all_channels(), name="Home") #getting channel by name by using "discord.utils"
await channel.set_permissions(guild.default_role, view_channel=True) #changing permissions
By using the on_ready() event you can loop through the time check without sending any message.
Remember to import discord.utils.

Discord.py Cooldown

I made a discord economy bot. I want to include a loan function, where the user can ask for a loan. There would be a command cooldown. However, if they don't pay after the command cooldown has ended, the bot should automatically take the money.
#bot.command()
#commands.cooldown(1, 60*60*24*7, commands.BucketType.user)
async def loan(ctx, amount : int):
loan_available = int(client.get_user_bal(Devada, testbot)['cash'])
if int(amount) <= loan_available:
time.sleep(1)
await ctx.channel.send('You have been given ' + ''.join(str(amount) + ". You will have to pay " + str((int(amount)+int(amount)*0.1)) +" baguttes within 2 weeks."))
client.change_user_bal(str(ctx.guild.id), str(ctx.author.id), cash=0, bank=amount, reason='loan')
client.change_user_bal(str(ctx.guild.id), testbot, cash=-amount, bank=0, reason='loan')
must_pay.update({ctx.author.name:str(amount)})
else:
time.sleep(2)
await ctx.channel.send("You Can only request a loan within "+str(loan_available))
Is there any way to detect when the cooldown is over?
The #commands.cooldown attribute is used to add a cooldown to a command, so users can't spam that same command. Instead, they need to wait for a certain amount of time ( 60*60*24*7 seconds, in this case ) before being able to re-use the command.
However, if you want the bot to wait for 604800 seconds and then take the money back, you should use the asyncio module to wait for that amount of time without disturbing or stopping the other commands of the program. Here is how you can re-adjust your code:
import asyncio
#bot.command()
#commands.cooldown(1, 60*60*24*7, commands.BucketType.user)
async def loan(ctx, amount : int):
loan_available = int(client.get_user_bal(Devada, testbot)['cash'])
if int(amount) <= loan_available:
time.sleep(1)
await ctx.channel.send('You have been given ' + ''.join(str(amount) + ". You will have to pay " + str((int(amount)+int(amount)*0.1)) +" baguttes within 2 weeks."))
client.change_user_bal(str(ctx.guild.id), str(ctx.author.id), cash=0, bank=amount, reason='loan')
client.change_user_bal(str(ctx.guild.id), testbot, cash=-amount, bank=0, reason='loan')
must_pay.update({ctx.author.name:str(amount)})
else:
time.sleep(2)
await ctx.channel.send("You Can only request a loan within "+str(loan_available))
# New asyncio code
await asyncio.sleep(60*60*24*7) # Wait for 60*60*24*7 seconds
# Here, just add the code to take the money away after 60*60*24*7 seconds
Note that if you restart your bot between the time, the bot won't execute the code after
60*60*24*7 seconds. So you must keep the bot online without restarting it.
The correct way of checking if a command's cooldown has finished is either checking if Command.is_on_cooldown is false or even checking the time left on the command by using Command.get_cooldown_retry_after. You would need to check this every certain amount of time, so you could create a Task that would call any of those functions and then evaluate the result to do whatever you want.

How to make a restart command for my discord.py bot

so far what I've got is:
def restart_program():
python = sys.executable
os.execl(python, python, * sys.argv)
#bot.command()
async def restart(ctx):
message = await ctx.send("Restarting... Allow up to 5 seconds")
restart_program()
This works, however I'm wondering how I can make it edit the "Restarting... Allow up to 5 seconds" message to say something like "Bot is back up" after it's restarted. Is this possible, and if so, how could I do this?
I would use Client.logout() and Client.login() to restart a bot instead of doing it with os.execl, but if you really need to do it this way, here is a how you can send a message every time it is started:
#client.event
async def on_ready():
# First get the channel where the message should be sent
channel = discord.utils.get(client.get_all_channels(), name='general')
await channel.send("Bot is back up!")

Resources