Bot discord with python - python-3.x

How can I make it so that when someone who is not an administrator and runs the 'cls' command gives him a message like for example you are not an administrator, sorry
Python code
#bot.command()
#commands.has_permissions(manage_messages=True)
async def cls(ctx, Quantity= 10000):
if manage_messages == False:
await ctx.send('You are not an administrator, you cannot run this command.')
await ctx.channel.purge(limit = Quantity)
Help I don't know how to do it.

import discord
import asyncio
from discord.ext.commands import Bot
client = Bot(description="My Cool Bot", command_prefix="!", pm_help = False, )
#client.event
async def on_ready():
print("Bot is ready!")
return await client.change_presence(game=discord.Game(name='My bot'))
#client.command(pass_context = True)
async def whoami(ctx):
if ctx.message.author.server_permissions.administrator:
msg = "You're an admin {0.author.mention}".format(ctx.message)
await client.send_message(ctx.message.channel, msg)
else:
msg = "You're an average joe {0.author.mention}".format(ctx.message)
await client.send_message(ctx.message.channel, msg)
client.run('Your_Bot_Token')

This is how I would do it to check if the author of the message has admin permissions in your case.
if ctx.message.author.guild_permissions.administrator:
await ctx.channel.purge(limit=Quantity)
await ctx.send('Deletion success! Deleted ' + Quantity + ' messages.')
else:
await ctx.send('You are not an administrator, you cannot run this command.')

Related

Why does my on_message event doesn't work (discord.py)

I'm making a discord bot that worked fine but I wanted to start using cogs because I thought it was a nicer way to write my code but now my on_message doesn't work any more and it doesn't show any error messages I searched how to fix it in the whole internet and all explanations didn't work for me so I decided to ask here. So here is my code:
from discord.ext import commands
TOKEN = 'my token'
bot = commands.Bot(command_prefix="$")
class Interactions(commands.Cog):
#commands.Cog.listener()
async def on_message(self, message):
msg = message.content
hi = ["hi", "hello", "hi!", "hello!"]
bye = ["bye", "good bye", "bye!", "good bye!"]
# Messages in english
if str(msg).lower() in hi:
await message.channel.send('Hello!')
if str(msg).lower == 'how are you?':
await message.channel.send("I'm fine")
if str(msg).lower == "what's your favorite food?":
await message.channel.send("Sushi with sweet potato!")
if str(msg).lower == "what do you eat?":
await message.channel.send(
"I don't eat, I'm just a simple bot :pensive:")
if str(msg).lower == "are you fine?":
await message.channel.send("Yes, I am")
if str(msg).lower in bye:
await message.channel.send("Good bye!")
def run():
bot.add_cog(Interactions(bot)
bot.run(TOKEN)
if __name__ == "__main__":
run()
Import:
from discord.ext.commands import command, Cog
Rest of the code:
TOKEN = 'my token'
bot = commands.Bot(command_prefix="$")
class Interactions(commands.Cog):
#commands.Cog.listener()
async def on_message(self, message):
pass
This should work, if not just ping me ;)

Discord Poll Bot

Hi i am trying to make a poll bot but ive encountered a problem here is the code ignore the other commands other than + poll
import discord
import os
import requests
import json
import random
pollid = 0
emoji1 = '\N{THUMBS UP SIGN}'
emoji2 = '\N{THUMBS DOWN SIGN}'
client = discord.Client()
sad_words=["sad","depressed", "unhappy","angry","miserable","depressing"]
starter_encouragements = ["Cheer up", "hang in there.", "You are a great person / bot!"]
def get_quote():
response = requests.get("https://zenquotes.io/api/random")
json_data = json.loads(response.text)
quote = json_data[0]['q'] + " -" + json_data[0]['a']
return[quote]
from discord.utils import get
#client.event
async def on_ready():
print('We have logged in as {0.user}'.format(client))
#client.event
async def on_message(message):
global pollid
#if message.author == client.user:
# return
msg = message.content
if message.content.startswith('+encourage'):
quote=get_quote()
await message.channel.send(quote)
if any(word in msg for word in sad_words):
await message.channel.send(random.choice(starter_encouragements))
if message.content.startswith("+joke"):
from dadjokes import Dadjoke
dadjoke = Dadjoke()
await message.channel.send(dadjoke.joke)
if message.content.startswith("+poll"):
pollid = pollid+1
await message.channel.send(content = msg.split(' ', 1)[1] + ' (number of polls made ' + str(pollid) + ')')
if message.author == client.user:
await message.add_reaction(emoji1)
await message.add_reaction(emoji2)
reaction = get(message.reactions, emoji=emoji1)
#reaction2 = get(message.reactions, emoji=emoji2)
#if (reaction != None and reaction2 != None):
# totalcount = reaction.count + reaction2.count
#if totalcount>=2:
if (reaction != None and reaction.count != 1):
await message.channel.send('The outcome of the poll is yes'+ str(reaction.count))
# await message.channel.send('The outcome of the poll is no')
client.run(os.getenv('TOKEN'))
i am very new to python and the discord api for it ive been trying to set up a poll system where it has a timer on each poll that lasts 24 hrs and after 24 hrs it compares the amount of reactions on the message to see which side wins. Can someone help me with this. Thanks
I would not use on_message events for that but instead use a command.
You can do something like this:
import discord
from discord.ext import commands
#client.command()
async def poll(ctx, *, text: str):
poll = await ctx.send(f"{text}")
await poll.add_reaction("✅")
await poll.add_reaction("❌")
Here we have text as a str so you can add as many text as you want.
If you want to compare it after 24 hours you would also have to build in a cooldown saver if the bot restarts, otherwise we could go with await asyncio.sleep(TimeAmount)
If you want to check the result with a command we could go for this:
from discord.utils import get
import discord
from discord.ext import commands
#client.command()
async def results(ctx, channel: discord.TextChannel, msgID: int):
msg = await channel.fetch_message(msgID)
reaction = get(msg.reactions, emoji='✅')
count1 = reaction.count # Count the one reaction
reaction2 = get(msg.reactions, emoji="❌")
count2 = reaction2.count # Count the second reaction
await ctx.send(f"✅**: {count1 - 1}** and ❌**: {count2 - 1}**") # -1 is used to exclude the bot
The usage of the command would be: results #channel MSGID.
Be aware that fetch is an API call and could cause a ratelimit.

How do I get the discord bot to trigger commands on it's own message using discord.py?

Let's just say the user enters an invalid command, the bot suggests a command with (y/n)? If y, then the bot should trigger the suggested command.
I feel this can be achieved in 2 ways:
If the bot can trigger commands on its own message
If I can call the command from the other cogs
I can't seem to get either of em working.
Here is an example to help you guys help me better:
Let's just say this below code is from a cog called Joke.py:
#commands.command()
async def joke(self,ctx):
await ctx.send("A Joke")
And then there another cog "CommandsCorrection.py" that corrects wrong commands used by the user that are saved on data.json file:
#commands.Cog.listener()
async def on_message(self, message):
channel = message.channel
prefix = get_prefix(self,message)
if message.author.id == bot.id:
return
elif message.content.startswith(prefix):
withoutprefix = message.content.replace(prefix,"")
if withoutprefix in data:
return
else:
try:
rightCommand= get_close_matches(withoutprefix, data.keys())[0]
await message.channel.send(f"Did you mean {prefix}%s instead? Enter Y if yes, or N if no:" %rightCommand)
def check(m):
return m.content == "Y" or "N" and m.channel == channel
msg = await self.client.wait_for('message', check=check, timeout = 10.0)
msg.content = msg.content.lower()
if msg.content == "y":
await channel.send(f'{prefix}{rightCommand}')
elif msg.content == "n":
await channel.send('You said no.')
except asyncio.TimeoutError:
await channel.send('Timed Out')
except IndexError as error:
await channel.send("Command Not Found. Try !help for the list of commands and use '!' as prefix.")
in the above code await message.channel.send(f"Did you mean {prefix}%s instead? Enter Y if yes, or N if no:" %rightCommand) suggests the right command and await channel.send(f'{prefix}{rightCommand}') sends the right command.
So,for example:
user : !jok
bot : Did you mean !joke instead? Enter Y if yes, or N if no:
user : y
bot : !joke **I want to trigger the command when it sends this message by reading its own message or my just calling that command/function
How should I go about this?
One solution would be to separate the logic of your commands from the command callbacks and put it in it's own coroutines. Then you can call these coroutines freely from any of the command callbacks.
So you would turn code like this:
#bot.command()
async def my_command(ctx):
await ctx.send("Running command")
#bot.command()
async def other_command(ctx, arg):
if arg == "command":
await ctx.send("Running command")
Into something like this:
async def command_logic(ctx):
await ctx.send("Running command")
#bot.command()
async def my_command(ctx):
await command_logic(ctx)
#bot.command()
async def other_command(ctx, arg):
if arg == "command":
await command_logic(ctx)
#Patrick Haugh suggested this idea, he was on to something but wasn't really working but I got a way to get it working.
If you use the following method for a cog, you'll be able to read bot commands as well:
import discord
from discord.ext import commands
async def command_logic(self, ctx):
await ctx.send("Running command")
class Example(commands.Cog):
def __init__(self, client):
self.client = client
#commands.command()
async def my_command(self, ctx):
await command_logic(self,ctx)
#commands.Cog.listener()
async def on_message(self, message):
if message.content == '!command':
ctx = await self.client.get_context(message)
await command_logic(self,ctx)
def setup(client):
client.add_cog(Example(client))

How to loop a task in discord.py

I am experimenting with making my own little discord bot that can get information from Twitch, but I'm stumped on how to make the bot loop and check for a condition.
I want the bot to loop a section of code every few seconds that checks if the specified twitch channel is live.
Code
import discord
from discord.ext import commands, tasks
from twitch import TwitchClient
from pprint import pformat
client = TwitchClient(client_id='<twitch token>')
bot = commands.Bot(command_prefix='$')
#bot.event
async def on_ready():
print('We have logged in as {0.user}'.format(bot))
#bot.command()
async def info(ctx, username):
response = await ctx.send("Querying twitch database...")
try:
users = client.users.translate_usernames_to_ids(username)
for user in users:
print(user.id)
userid = user.id
twitchinfo = client.users.get_by_id(userid)
status = client.streams.get_stream_by_user(userid)
if status == None:
print("Not live")
livestat = twitchinfo.display_name + "is not live"
else:
livestat = twitchinfo.display_name + " is " + status.stream_type
responsemsg = pformat(twitchinfo) + "\n" + livestat
await response.edit(content=responsemsg)
except:
await response.edit(content="Invalid username")
bot.run("<discord token>")
I want the bot to run the following code every 10 seconds, for example:
status = client.streams.get_stream_by_user(<channel id>)
if status == None:
print("Not live")
livestat = twitchinfo.display_name + "is not live"
else:
livestat = twitchinfo.display_name + " is " + status.stream_type
I've tried using #tasks.loop(seconds=10) to try and make a custom async def repeat every 10 seconds but it didn't seem to work.
Any ideas?
The newer version of discord.py doesn't support client.command()
To achieve the same I used the following snippet
import discord
from discord.ext import tasks
client = discord.Client()
#tasks.loop(seconds = 10) # repeat after every 10 seconds
async def myLoop():
# work
myLoop.start()
client.run('<your token>')
This can be done like so:
async def my_task(ctx, username):
while True:
# do something
await asyncio.sleep(10)
#client.command()
async def info(ctx, username):
client.loop.create_task(my_task(ctx, username))
References:
asyncio.create_task()
asyncio.sleep()
This is the most proper way to implement background tasks.
from discord.ext import commands, tasks
bot = commands.Bot(...)
#bot.listen()
async def on_ready():
task_loop.start() # important to start the loop
#tasks.loop(seconds=10)
async def task_loop():
... # this code will be executed every 10 seconds after the bot is ready
Check this for more info
I struggled with this as well. The problem I ran into is that none of the examples online were complete. Here is one I came up with that uses #tasks.loop(seconds=10).
import discord
import os
from discord.ext import tasks
from dotenv import load_dotenv
intents = discord.Intents.all()
client = discord.Client(command_prefix="!", intents=intents)
load_dotenv()
token = os.getenv("DISCORD_TOKEN")
CHANNEL_ID = 1234
#client.event
async def on_ready():
print(f"We have logged in as {client.user}")
myloop.start()
#client.event
async def on_message(message):
if message.author == client.user:
return
if message.content.startswith("hi"):
await message.channel.send("Hello!")
#tasks.loop(seconds=10)
async def myloop():
channel = client.get_channel(CHANNEL_ID)
await channel.send("Message")
client.run(token)

Get a single response from all commands

How to make bot send a specific message when users use any commands. so when user use !ping or any command it should send a default message. cozz for sometime i need to stop bot responding to all command except 1 command.
#bot.command(pass_context=True)
async def ping(ctx):
msg = "Pong {0.author.mention}".format(ctx.message)
await bot.say(msg)
You can do this in the on_message event. Example code below.
from discord.ext import commands
bot_prefix = '!'
client = commands.Bot(command_prefix=bot_prefix)
#client.event
async def on_ready():
print('client ready')
#client.command(pass_context=True)
async def ping(ctx):
msg = "Pong {0.author.mention}".format(ctx.message)
await bot.say(msg)
#client.event
async def on_message(message):
if message.startswith(bot_prefix):
await client.send_message(message.channel, 'Processing commands')
await client.process_commands(message)
client.run('TOKEN')

Resources