I have tried making a bot in discord.py and i cant figure out how to use discord.ext.
The part that doesn't work is this:
bot = commands.Bot(command_prefix='.')
#bot.command()
async def test(ctx, arg):
await ctx.channel.send(arg)
When I type .test whatever in discord nothing happens
Is it because of the api update?
If so what do I need to change
This is the entire code:
import os
import discord
import asyncio
from dotenv import load_dotenv
from discord.ext import commands
from discord.ext import bot
bot = commands.Bot(command_prefix='$')
#bot.command()
async def test(ctx, arg):
await ctx.channel.send(arg)
load_dotenv()
token = os.getenv("TOKEN")
client = discord.Client()
class MyClient(discord.Client):
async def on_ready(self):
print('Logged on as {0}!'.format(self.user))
async def on_message(self, message):
f = open("muteMsg.txt", "r")
muteMsg = f.read()
f.close()
print('Message from {0.author}: {0.content}'.format(message))
id = message.author.id
if id == 0:
await message.delete()
if muteMsg == "1":
await message.channel.send(f"stfu {message.author.mention}")
elif message.content.startswith('good bot') or message.content.startswith('Good bot'):
await message.channel.send(':)')
elif message.content.startswith('bad bot') or message.content.startswith('Bad bot'):
await message.channel.send(':(')
elif message.content.startswith('.rickroll'):
await message.channel.send('https://www.youtube.com/watch?v=dQw4w9WgXcQ')
elif message.content.startswith('.help'):
await message.channel.send('commands list:\n.help: shows this\n.rickroll: well youll have to try yourself\n')
elif message.content.startswith('.togglemutemsgs'):
if muteMsg == "0":
f = open("muteMsg.txt", "w")
f.write("1")
f.close()
await message.channel.send('mute messages on')
elif muteMsg == "1":
f = open("muteMsg.txt", "w")
f.write("0")
f.close()
await message.channel.send('mute messages off')
client = MyClient()
client.run(token)
The core issue here is that while you do instantiate discord.ext.commands.Bot on line 9 you never actually use it, instead calling .run() on your subclass of discord.Client which does not interact with your defined method in any way.
The simplest way of getting your command to work is to change your last line from client.run(token) to
bot.run(token)
but your handlers of on_ready and on_message events will not work anymore - you should learn more to figure out why and how to solve it.
As a side note: you really shouldn't be putting any complex logic in on_message handler and you definitely should not be opening files there.
Well, If you want to take input from user ,you need to use async def test(ctx, *, arg), Try using the code below:
#bot.command()
async def test(ctx, *,arg):
await ctx.channel.send(arg)
And also beware of the command_prefix properly. Thank you :)
To use commands extension, you need to define a bot via commands.Bot because discord.Client doesn't have any infrastructure to make commands.
So you should change your inheritance in class MyClient, it should directly inherit from the commands.Bot. And you should pass the args/kwargs to your MyClient class, then you should run that classes instance rather than discord.Client.
Related
I've never coded before so I'm pretty new and I'm trying python on replit, I've searched a lot and this is what I did so far but it isn't working. (ignore the reverse part)
import os
import discord
from keep_alive import keep_alive
client = discord.Client(intents=discord.Intents.default())
#client.event
async def on_ready():
print("I'm in")
print(client.user)
#client.event
async def on_message(message):
if message.content.startswith("!reverse"):
await message.channel.send(message.content[::-1])
my_secret = os.environ['DISCORD_BOT_SECRET']
client.run(my_secret)
keep_alive()
my_secret = os.environ['DISCORD_BOT_SECRET']
client.run(my_secret)
async def on_message(message):
echo = message.content.split(" ", 1)[1]
if message.content.startswith("!say"):
await message.channel.send(echo)
I want the bot to be like this:
me:!say blah blah blah
bot: blah blah blah
thanks to anyone that answers
There's a lot of problems here
Intents.default() doesn't include the message contents intent, so you won't be able to read messages. For more info on intents and how to enable them, read the docs: https://discordpy.readthedocs.io/en/stable/intents.html
You've got two on_message functions, which doesn't work. You can't have multiple functions with the same name. Combine them into one instead.
Never put any code underneath client.run() - it'll never get executed.
You've got two client.run()'s. Why?
The on_message at the bottom is missing the #client.event decorator, so even if you wouldn't have 2 of them it still wouldn't be invoked.
Why don't you use a Bot with commands instead of manually parsing everything in on_message? https://discordpy.readthedocs.io/en/stable/ext/commands/index.html
Replit isn't made to run bots on and will cause you a lot of trouble. Consider hosting it on an actual VPS (or during the development phase - just locally).
Ok, there's some other changes to make first.
You're not using commands, and are instead looking for messages(technically nothing wrong with that, but it can cause unnecessary issues)
I'll modify the code, and hopefully, it works.
import os
import discord
from keep_alive import keep_alive
client= commands.Bot(command_prefix='!', intents=discord.Intents.default())
#client.event
async def on_ready():
print("I'm in")
print(client.user)
#client.command()
async def reverse(ctx,*,message):
await ctx.message.delete()
await ctx.channel.send(message[::-1])
my_secret = os.environ['DISCORD_BOT_SECRET']
client.run(my_secret)
keep_alive()
my_secret = os.environ['DISCORD_BOT_SECRET']
client.run(my_secret)
#client.command()
async def say(ctx, *, message):
await ctx.message.delete()
await ctx.channel.send(message)
This isn't something most people want, but I do.
Code:
#imports
import discord
import os
from keep_alive import keep_alive
from discord.ext.commands import has_permissions, MissingPermissions
from discord.ext import commands
from discord.utils import get
#client name
client = discord.Client()
#log-in msg
#client.event
async def on_ready():
print("Successfully logged in as")
print(client.user)
#prefix and remove default help cmd
client = commands.Bot(command_prefix='H')
client.remove_command("help")
#client.command(pass_context=True)
async def ere(ctx, *, args=None):
await ctx.send("hi")
if discord.utils.get(ctx.message.author.roles, name="MEE6") != None:
if args != None:
await ctx.send("mee6 just spoke!")
else:
await ctx.send("nope")
#client.event
async def on_message(message):
print(message.author)
if "Here" in message.content:
if discord.utils.get(message.author.roles, name="MEE6") != None:
channel = await client.fetch_channel(870023245892575282)
await channel.send("yes")
await client.process_commands(message)
I figured adding "await client.process_commands(message)" to the bottom of on_message would process commands sent by other bots such as MEE6 but no luck. It appears by default on_message can hear bots but commands can not. Any way to get around this?
Any help would be greatly appreciated!
It is a feature of the Bot class to ignore other bot's messages, but #Daniel O'Brien solved it in this thread. The solution is to subclass the bot and override the function which ignores other bots, like this:
class UnfilteredBot(commands.Bot):
"""An overridden version of the Bot class that will listen to other bots."""
async def process_commands(self, message):
"""Override process_commands to listen to bots."""
ctx = await self.get_context(message)
await self.invoke(ctx)
Use ID
for commands:
# from discord.ext import commands as cmds
def is_mee6():
def predicate(ctx: cmds.Context):
return ctx.message.author.id == 159985870458322944:
# 159985870458322944 is ID of MEE6
return cmds.check(predicate)
# Use like it:
# #cmds.command()
# #is_mee6()
# async def ...
for events:
# from discord.ext import commands as cmds
mee6_id = 159985870458322944
# and use it for checks. for Example
#cmds.event
async def on_message(message):
if message.author.id == mee6_id:
# ANY
I am making a Discord bot with Python.
I would like to add a feature in where, there is a channel called "chatbot", and any text typed there would be replied to by Cleverbot
I am currently trying with the cleverbotfree library, but it doesn't work and I can't find good documentation on it. My problem is that I am trying to run this async command:
#CleverbotAsync.connect
async def async_chat(bot, message, user_input, bot_prompt):
"""Example code using cleverbotfree async API with decorator."""
reply = await bot.single_exchange(user_input)
await message.channel.send(f'{0}'.format(reply))
await bot.close()
However, I can't do this in on_message, because it needs to be run in this snippet of code:
if chnl == 'chatbot':
#whatever running that command
So, I'm not sure how do it.
And yes, I have looked into and tried Selenuim, but it appears that whenever I click the accept button, nothing loads. (This must be a way for Cleverbot to make people actually pay for their API, which I can't do).
Here is my full code(I know it's not the best):
import discord
from discord import channel
from discord.flags import MessageFlags
from webserver import keep_alive
import os
from discord.ext import commands
import youtube_dl
import time
import asyncio
from cleverbotfree import CleverbotAsync
from cleverbotfree import Cleverbot
requests = []
def send(message,user_input,bot_prompt):
asyncio.run(async_chat(message,user_input,'Cleverbot:'))
client = commands.Bot(command_prefix="!")
#client.command()
async def request(ctx, request: str,member: discord.Member):
requests.append('{0}: {1}'.format(member,request))
await ctx.send(f'Thanks {member.metion} for the request, my dev will (hopefully) get right to work!')
#client.command(description="See what my dev is working on")
async def workingon(ctx):
ctx.send("My Dev is currently working on adding a feature in where, in a channel called 'chatbot', it will respond like a human.(though he has spent hours on it, it still doesn't work)")
#client.event
async def on_ready():
#confirming login
print('Logged on as {0.user}'.format(client))
#client.event
async def on_member_join(member):
print(f'Greetings {member}, welcome to server')
#CleverbotAsync.connect
async def async_chat(bot, message, user_input, bot_prompt):
"""Example code using cleverbotfree async api with decorator."""
reply = await bot.single_exchange(user_input)
await message.channel.send(f'{0}'.format(reply))
await bot.close()
#client.event
async def on_message(message):
#getting variables
usrnm = str(message.author).split('#')[0]
msg = str(message.content)
chnl = str(message.channel.name)
if usrnm != str(client.user).split('#')[0] and msg.lower() == 'hello bot':
await message.channel.send(f'Hello {usrnm}, how do you do?')
return
if str(msg).split(' ')[0].lower() == 'im':
print(str(msg).split(' ')[0].lower())
await message.channel.send(f'Hi, {msg}, im a dad!')
if msg.lower() == '!newfeatures':
await message.channel.send(f'{message.author.mention}, The newest feature added to the bot is that if a new member joins, it will greet them')
if msg.lower() == '!help':
await message.channel.send(f'{message.author.mention}, Type !help for help. \n\n - Typing "Hello Bot" will make the bot answer\n - typing "im" before anything will make the bot answer\n - Typing !newfeatures will tell you the newest feature added to the bot.')
if chnl == 'chatbot':
send(message,str(message.content),'Cleverbot:')
#muting system
keep_alive()
TOKEN = os.environ.get("DISCORD_BOT_SECRET")
client.run(TOKEN)
Any help would be appreciated!
I'm fairly new at making a discord bot. I have created a method to get a list of all the members in the server the bot is connected to. This method works fine. However, I am also trying to get the bot to accept commands. I am having a lot of trouble with this and I keep seeing that I should use commands.Bot for this instead of Client. I can't figure out how to make my original method work with commands.Bot though. Any help would be appreciated!
import os
import discord
import csv
from collections import defaultdict
from discord.ext import commands
intents = discord.Intents.all()
client = discord.Client(intents=intents)
outP = open("giveawayList.txt", "w")
bot = commands.Bot(command_prefix='!')
#client.event
async def on_message(message):
if message == "!test":
await message.channel.send("you failed the test")
#client.event
async def on_ready():
for guild in client.guilds:
if guild.name == GUILD:
break
print(
f'{client.user} is connected to the following guild: \n'
f'{guild.name} (id: {guild.id})'
)
count = 0
for guild in client.guilds:
for member in guild.members:
print(member)
if 'Bots' not in str(member.roles):
print(member.name, ' ')
outP.write(member.name)
outP.write("\n")
count += 1
print('Number of members: ' + str(count))
It is good to use commands.bot instead of Client because it is an extended version, as it inherits all the functionalities from Client.
I see you have tried to migrate from the use of Client to using commands.bot, but have a few things in mind:
You do not want to use both at the same time, so this is wrong:
client = discord.Client(intents=intents)
bot = commands.Bot(command_prefix='!')
You should keep only the bot one.
Apart from that, you gotta replace the client from the decorators and the calls inside the function. Your corrected code should look something like this:
import os
import discord
import csv
from collections import defaultdict
from discord.ext import commands
intents = discord.Intents.all()
outP = open("giveawayList.txt", "w")
bot = commands.Bot(command_prefix='!', intents=intents)
#bot.event
async def on_message(message):
if message == "!test":
await message.channel.send("you failed the test")
await bot.process_commands(message)
#bot.event
async def on_ready():
for guild in bot.guilds:
if guild.name == GUILD:
break
print(
f'{bot.user} is connected to the following guild: \n'
f'{guild.name} (id: {guild.id})'
)
count = 0
for guild in bot.guilds:
for member in guild.members:
print(member)
if 'Bots' not in str(member.roles):
print(member.name, ' ')
outP.write(member.name)
outP.write("\n")
count += 1
print('Number of members: ' + str(count))
So, regarding your questions, i am gonna answer them one by one :
1- client and bot are not diffrent at all, that means you shouldn't have any problem using the same functions on both(and neither are better than each other, meaning both will do the same stuff)
2- now to get your bot to receive/accept commands, you can use the await function, which basically waits for a command to be trigerred and will give out the output.
For example :
#Client.command()
async def botping(ctx):
await ctx.send(f"The bot's ping is {round(Client.latency*1000)} ms")
This command here (for example):
We are defining a command called "botping" and we are passing the ctx wich is the context the bot is writing, the you have the await wich will trigger the command when you type "prefix"botping in chat.
Hopefully this helped you a little bit about the concept of taking commands and that there is no diffrence between client and bot
For further information, i suggest that you check out the discord.py documentation:
https://discordpy.readthedocs.io/en/latest/index.html
I am trying to create a python script that would mute the users of a specific voice channel when executed. Till now I am able to mute everyone by typing the command in the discord text channel, but I would like to mute everyone when another python script tells the bot to. Below is my attempt to do that.
bot.py is the python discord bot:
import discord
from discord.ext import commands
from time import sleep
client = commands.Bot(command_prefix="./")
#client.event
async def on_ready():
print("Bot is online. ")
#client.command()
async def play_music_test():
channel = await client.get_channel(voice_channel_number)
voice = await channel.connect()
await voice.play(
discord.FFmpegPCMAudio(executable="C:/Users/USER/ffmpeg/bin/ffmpeg.exe",
source="C:/Users/USER/Desktop/song.mp3"))
client.run(TOKEN)
abc.py is the other python script trying to call a function:
from bot import play_music_test
import asyncio
print("")
asyncio.run(play_music_test())
I ran the bot.py first and then tried to execute the abc.py next, bot came online but when executing abc.py, it didn't print or do anything at all. I just started to learn discord.py so if this is a silly question, forgive me.
Instead of running the python file you can import it, or making it a cog
heres an example:
importing: bot.py
import discord
from discord.ext import commands
from time import sleep
from abc import *
client = commands.Bot(command_prefix="./")
#client.event
async def on_ready():
print("Bot is online. ")
#client.command(name = "play_music", aliases = ["you can asign aliases like this", "multiple ones too"])
async def play_music_test(ctx, channel): # If the python file doesn't know what channel is, it can be asigned when calling the function in discord, think of it like sys.argv or argparse
if channel == None: channel = ctx.channel # This sets the current channel you are in if none was provided when executing it in discord
# channel = await client.get_channel(channel) now you don't need this line
voice = await channel.connect()
await voice.play(
discord.FFmpegPCMAudio(executable="C:/Users/USER/ffmpeg/bin/ffmpeg.exe",
source="C:/Users/USER/Desktop/song.mp3"))
client.run(TOKEN)
importing: abc.py
remove asyncio.run(play_music_test())
use it in discord instead! ex. play_music_test #general
Making it a cog: bot.py
import discord
from discord.ext import commands
from time import sleep
import os
client = commands.Bot(command_prefix="./")
#client.event
async def on_ready():
print("Bot is online. ")
for filename in os.listdir("./"):
if filename == "bot.py": continue
else: client.load_extension(f"cogs.{filename[:-3]}")
client.run(TOKEN)
Making it a cog: abc.py
from bot import play_music_test
import asyncio
class Mycog(commands.Cog):
def __init__(self, client):
self.client = client
#client.command(name = "play_music", aliases = ["you can asign aliases like this",
"multiple ones too"])
async def play_music_test(ctx, channel): # If the python file doesn't know what
channel is, it can be asigned when calling the function in discord, think of it like sys.argv or argparse
if channel == None: channel = ctx.channel # This sets the current channel you are in if none was provided when executing it in discord
# channel = await client.get_channel(channel) now you don't need this line
voice = await channel.connect()
await voice.play(
discord.FFmpegPCMAudio(executable="C:/Users/USER/ffmpeg/bin/ffmpeg.exe",
source="C:/Users/USER/Desktop/song.mp3"))
def setup(client):
client.add_cog(Mycog(client))
This anwser is not the best but hope this helps!
i'm not sure, if i really understand, what you try to do, but to open a script from another script, i use subprocess.Popen()
but i think, in your case it fits more, to change the way you try to solve your problem. maybe you should take a look into the on_message event and use message.content
?
You can importing your client variable (from bot import play_music_test, client) and then client.loop.create_task(play_music_test())
(Although I do not understand why you would do such a thing)