How do i await cogs in discord.py - python-3.x

I was trying to create a discord bot in python that will play music from YouTube. But when i run this script, it shows the bot is online but if i enter a command then it says command not found. gives me this warning everytime i run the script.
/bin/python3 "/home/r1d0m/Python/Discord Music Bot/main.py"
/home/r1d0m/Python/Discord Music Bot/main.py:15: RuntimeWarning: coroutine 'BotBase.add_cog' was never awaited
bot.add_cog(help_cog(bot))
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
/home/r1d0m/Python/Discord Music Bot/main.py:16: RuntimeWarning: coroutine 'BotBase.add_cog' was never awaited
bot.add_cog(music_cog(bot))
And this is what i coded in main.py
import discord
from discord.ext import commands
from help_cog import help_cog
from music_cog import music_cog
intents = discord.Intents.all()
intents.message_content = True
bot = commands.Bot(command_prefix="/", intents = intents)
bot.remove_command("help")
bot.add_cog(help_cog(bot))
bot.add_cog(music_cog(bot))
with open('/home/r1d0m/Python/Discord Music Bot/token.txt') as redk:
contents = redk.read()
bot.run(contents)
I don't know what to do. please help.
I even tried to add this,
await bot.add_cog(help_cog(bot))
But it gives me error.

Try reading up on async-await for python. This is a good starting point.
Async IO in Python
await should always reside inside an async function.
eg snippet:
import discord
from discord.ext import commands
from help_cog import help_cog
from music_cog import music_cog
async def main():
...
await bot.add_cog(help_cog(bot))
await bot.add_cog(music_cog(bot))
with open('/home/r1d0m/Python/Discord Music Bot/token.txt') as redk:
contents = redk.read()
...
if __name__ == "__main__":
import asyncio
asyncio.run(main())

Related

How do I create commands in Discord?

import discord
from discord.ext import commands
bot = commands.Bot(command_prefix='<', intents=None)
#bot.command()
async def normal(ctx):
await ctx.send("The normal command")
bot.run("MTA1MjU0ODMzNTY4NjQwMjEwOQ.G0umvR.iElF5nzDjjJcvIvKfZQa0Lfelglh7sXPapuFHc")
When I type "<normal" it does not show me any result as if the bot is not working but ERORR does not appear
1
2
What can I do?
You forgot to run a bot. Just add at the end of the code bot.run("TOKEN"). Where "TOKEN" is a token bot that can be reached here (I think you already know exactly where the button is to get token)
Code:
import discord
from discord.ext import commands
bot = commands.Bot(command_prefix='<', intents=None)
#bot.command()
async def normal(ctx):
await ctx.send("The normal command")
TOKEN = 'OTM4NTgwOTczMDU3MDkzNzAy.GnG96L.afrgSpK7OowwxQkkTnR3Sx9p76rbdRetHIChN0'# This token is not true, it's just a set of random characters
bot.run(TOKEN)

How do i make a discord bot receive text after a command

I want to become a fake discord bot, so i can use: !!send or something like that.
I have the token ready and i tried some repl.it templates but i have no idea of what to do.
here is the code i tried:
import discord
import os
import time
import discord.ext
from discord.utils import get
from discord.ext import commands, tasks
from discord.ext.commands import has_permissions, CheckFailure, check
os.environ["TOKEN"] = "no-token-for-you-to-see-here"
#^ basic imports for other features of discord.py and python ^
client = discord.Client()
client = commands.Bot(command_prefix = '!!') #put your own prefix here
#client.event
async def on_ready():
print("bot online") #will print "bot online" in the console when the bot is online
#client.command(pass_context=True)
async def send(ctx,*,message):
await client.say(message)
client.run(os.getenv("TOKEN")) #get your bot token and create a key named `TOKEN` to the secrets panel then paste your bot token as the value.
#to keep your bot from shutting down use https://uptimerobot.com then create a https:// monitor and put the link to the website that appewars when you run this repl in the monitor and it will keep your bot alive by pinging the flask server
#enjoy!
It was online, but the command didn't work.
The command send should be
#client.command()
async def send(ctx, *, message: str):
await ctx.send(message)
Also, you're defining two client(s). You need only one.
client = commands.Bot(command_prefix = '!!')
You're also importing some useless modules that you don't need right now.
Your final code should look like this:
import discord
from discord.ext import commands
client = commands.Bot(command_prefix="!!")
#client.event
async def on_ready():
print("The bot is online")
#client.command()
async def send(ctx, *, message: str):
await ctx.send(message)
client.run("token-of-the-bot")
Please tell me if it works or not. Have a great day :)

How to import functions from different file and use in discord.py

A straight Forward question - How to import a function from a different file and use that in discord.py cuz i tried that and failed for example there is file a and b which looks like
a.py:
async def joke(ctx):
joke = 'Your mama so fat boy'
await ctx.send(joke)
and i want to use the joke function from file a to file b and the code i write was:
from a import joke
from discord.ext import commands
#some discord code
TOKEN = 'My_Secret_Token'
GUILD = 'My_Guild'
client = commands.Bot(command_prefix='!')
#client.command(name='joke', help='This will return a joke')
joke()
client.run(TOKEN)
And the line joke() is returning me error
File "main.py", line 31
joke()
^
SyntaxError: invalid syntax
And i am here confused that why it is returning me error and how can i pass the argument ctx. So please come up with a solution for me.
Edit: After debugging and scratching my head for hours i came up with a solution which is also not working that i modified my b.py a little bit :
from a import joke
from discord.ext import commands
#some discord code
TOKEN = 'My_Secret_Token'
GUILD = 'My_Guild'
client = commands.Bot(command_prefix='!')
#client.command(name='joke', help='This will return a joke')
async def my_function(ctx):
joke(ctx)
client.run(TOKEN)
You can use cogs for this. Docs: https://discordpy.readthedocs.io/en/latest/ext/commands/cogs.html
Here is an Example:
Your main.py
import discord
from discord.ext import commands
import os
client = commands.Bot(command_prefix='!')
for file in os.listdir("cogs"):
if file.endswith(".py"):
name = file[:-3]
client.load_extension(f"cogs.{name}")
client.run(TOKEN)
Make a secound /cogs/joke.py
import discord
from discord.ext import commands
import random
class joke(commands.Cog):
def __init__(self, bot):
self.bot = bot
#commands.command()
async def joke(self, ctx):
jokes = [
'Your mama so fat boy',
'joke2',
'joke3',
'joke4',
'joke5'
]
answer = random.choice(jokes)
await ctx.send(answer)
def setup(bot):
bot.add_cog(joke(bot))

discord bot only seeing itself with command

import discord
import random
from discord.ext import commands, tasks
from itertools import cycle
from random import choice
client = commands.Bot(command_prefix = '.')
intents = discord.Intents.all()
#client.command()
#commands.guild_only()
async def ruser(ctx):
await ctx.send(choice(ctx.guild.members))
This is some code for a discord bot I'm working on. If you type ".ruser", it's supposed to send a message saying the user. The problem is that it is only returning the bots name, and not any of the users.
You didn't actually pass in the intents, you only declared the variable. You're supposed to add them to your bot as well.
intents = discord.Intents.all()
client = commands.Bot(command_prefix='.', intents=intents)

Unable to use discord.py and quarry at the same time

I am trying to make a discord bot using discord.py that uses the library quarry to interact with a minecraft server.
Unfortunately once I start the discord bot using bot.run() I can't start the reactor for quarry with reactor.run().
I've looked around including aiostream and asyncio but I can't find a solution. I also looked into twisted as quarry uses that.
EDIT: Including current code.
import asyncio
from twisted.internet import asyncioreactor
asyncioreactor.install(asyncio.get_event_loop())
from quarry.net.client import SpawningClientProtocol, ClientFactory
from quarry.net.auth import Profile
from discord.ext import commands
profile = Profile.from_credentials("email", "password")
bot = commands.Bot(command_prefix=">")
async def start():
loop = asyncio.get_event_loop()
loop.create_task(bot.start("token"))
client = MinecraftBotFactory(profile)
client.connect("creative.starlegacy.net", 25565)
class MinecraftBotProtocol(SpawningClientProtocol):
pass
class MinecraftBotFactory(ClientFactory):
protocol = MinecraftBotProtocol
asyncio.get_event_loop().create_task(start())
asyncio.get_event_loop().run_forever()
quarry uses twisted and in order to use it with an asyncio you will need to setup the AsyncioReactor at the start of your application.
import asyncio
from twisted.internet import asyncioreactor
asyncioreactor.install(asyncio.get_event_loop())
After that, you should only need to execute bot.start() since quarry relies on the reactor running, and just start the event loop. You cannot await reactor.run() because it's not a coroutine, so just get rid of that function.
Update: Added example and explanation
I had a chance to go over discord.py code a bit and found that discord.Client._connect() is basically "blocking code" if you await it, but only if you have another task waits for bot.start() to complete with in the same async def. In other words, it's an infinite poller loop that never returns anything, therefore cannot proceed past the await point. To avoid this you could create a Task. This example "should" work (I haven't tried it on a live server since I don't have a Minecraft client on hand). It starts a server and then when clients try to connect, they get a message saying the Minecraft server is down and then get booted. When a user tries to connect, a Discord message is also sent to the channel.
import asyncio
from twisted.internet import asyncioreactor
asyncioreactor.install(asyncio.get_event_loop())
import discord
from quarry.net.server import ServerFactory, ServerProtocol
from twisted.internet import endpoints, reactor
async def start():
loop = asyncio.get_event_loop()
minecraft_server = DowntimeFactory()
minecraft_server_host = "0.0.0.0"
minecraft_server_port = 25565
discord_bot_token = "APP_TOKEN"
discord_channel_id = 0 # CHANNEL ID
# Start a quarry server
quarry_server = endpoints.TCP4ServerEndpoint(
reactor,
port=minecraft_server_port,
interface=minecraft_server_host,
)
try:
await quarry_server.listen(minecraft_server).asFuture(loop)
except Exception as err:
print(err)
loop.stop()
# Start Discord poller
discord_client = discord.Client(loop=loop)
loop.create_task(discord_client.start(discord_bot_token))
#discord_client.event
async def on_ready():
"""
After the Discord client connects, set the discord_channel attribute in the
quarry factory so that server can access Discord functionality.
"""
discord_channel = discord_client.get_channel(discord_channel_id)
if discord_channel:
minecraft_server.discord_channel = discord_channel
await discord_channel.send("hello world")
else:
print("[!] channel no found")
loop.stop()
class DowntimeProtocol(ServerProtocol):
def packet_login_start(self, buff):
buff.discard()
self.close(self.factory.motd)
# The Discord channel might not have been set up yet
if self.factory.discord_channel:
self.factory.loop.create_task(
self.factory.discord_channel.send(
"Someone is trying to access the Minecraft server!"
)
)
class DowntimeFactory(ServerFactory):
motd = "Down for maintenance"
loop = asyncio.get_event_loop()
discord_channel = None
protocol = DowntimeProtocol
asyncio.get_event_loop().create_task(start())
try:
asyncio.get_event_loop().run_forever()
except KeyboardInterrupt:
pass
bot.run() is a blocking call, meaning that it stops the execution of the program until it is done. Try an alternative like await bot.start():
import asyncio
from discord.ext import tasks
async def start_bot():
await bot.start('my_token_goes_here')
#tasks.loop(count=1)
async def login_quarry():
# login to quarry here #
login_quarry.start()
# put any code you need BEFORE this:
asyncio.get_event_loop().run_until_complete(start_bot())
In python 3.7 and up, there is a simpler alternative:
import asyncio
from discord.ext import tasks
async def start_bot():
await bot.start('my_token_goes_here')
#tasks.loop(count=1)
async def login_quarry():
# login to quarry here #
login_quarry.start()
# put any code you need BEFORE this:
asyncio.run(start_bot())

Resources