I'm a newbie in discord.py and want to understand some features. How can I execute function without literally running the bot? You see, I'd like to call some bot function from other context. I don't like my bot to read events or smth like that, just to, for example, create a voice channel whenever my program call for that. How can I make such function? Maybe I should look at writing custom handlers for discord API with, for example, requests lib?
Your bot must logged into Discord to do things with the api.
I recomend you to run the bot in a diffrent thread and run the coro from the main tread.
Like this:
This is your file where your bot is in:
from discord.ext.commands import Bot
import threading
import discord
client = Bot(command_prefix="!")
#client.event
async def on_ready():
print("Ready")
async def create_voice(guild_id):
await client.wait_until_ready() # Waits for bot is logged in and the cache is loaded
guild = client.get_guild(guild_id)
await guild.create_voice_channel("Hallo")
print("Done")
thread = threading.Thread(target=client.run, args=["Token"])
thread.start()
main file:
import bot_run
import asyncio
loop = asyncio.get_event_loop()
asyncio.run_coroutine_threadsafe(bot_run.create_voice(guild_id), loop)
Hope this helps :D
Related
I have a slack bot that, for some reason, stopped recognizing certain bot events. I am using the slackeventsapi to import the SlackEventAdapter, and using it to recognize certain bot events, like reaction_added and reaction_removed. Recently that stopped working altogether on my bot, I reset my bot and it still doesn't work. I am unsure as to why.
I have already checked my slack api bot event subscriptions, and I am subscribed to both those events, so I am unsure as to what exactly is causing this to happen. The bot can still post messages to the chat, it just doesn't recognize certain bot events.
Below is an example of some code I am trying to run. the /test works, the reaction_added event never gets called and nothing gets invoked and never prints the payload.
import os
import slack_sdk
from flask import Flask, request, Response
from dotenv import load_dotenv
from pathlib import Path
from slackeventsapi import SlackEventAdapter
env_path = Path('.') / '.env'
load_dotenv(dotenv_path=env_path)
app = Flask(__name__)
slack_event_adapter = SlackEventAdapter(os.environ['SIGNING_SECRET'],'/slack/events', app)
client = slack_sdk.WebClient(token=os.environ['SLACK_TOKEN'])
#app.route('/test', methods=['POST'])
def test():
print("recognized a test command was sent!")
return Response(), 200
#slack_event_adapter.on("reaction_added")
def reaction(payLoad) -> None:
print(payLoad)
if __name__ == "__main__":
app.run(debug=True, port=8088)
I am running everything on an ngrok server. to better clarify, when I use the /test command on the bot I get a HTTP request POST with return of 200. when I add a reaction to something I do not get an HTTP request, I am unsure as to why.
I want when I say
$script
to output just any message for now in this below example 'pong'.
I have my token in a separate .env file so I don't need to worry about it
import discord
import os
from discord.ext import commands
intents = discord.Intents.all()
client = discord.Client(intents=discord.Intents.default())
bot = commands.Bot(command_prefix='$', intents=intents)
#client.event
async def on_ready():
print('We have logged in as {0.user}'.format(client))
#bot.command(name="script")
async def getscript(ctx):
await ctx.channel.send("pong")
client.run(os.getenv('TOKEN'))
this is the code below, but upon saying $script, nothing happens the bot is online and it works if I just send a message, but I'm not sure why this isn't working can someone help me out here? I have look at the "do any of these posts answer your question?" section and nothing helps.
Well yes it doesn't work because you're not running it. You have both a Client and a Bot. Your Bot has the $script command, but you're running the Client...
# You have both a Client and a Bot
client = discord.Client(...)
bot = commands.Bot(...)
# The command is registered to the Bot
#bot.command(...)
# You're running the Client
client.run()
Either use a Bot or a Client, but you can't use both. Get rid of your Client and use the Bot for everything instead. commands.Bot is a subclass of discord.Client so it can do everything a Client can do.
There's 0 reason to have both.
I want to ask a discord client to execute a specific function WITHOUT being triggered by an on message, or on ready or having a LOOP that repeats itself.
Basically, I want a function notify(msg) and make the discord client send a message to a channel
I have tried with the following without success
async notify(message, client):
await client.wait_until_ready()
channel = client.get_channel(os.getenv('CHANNEL_ID'))
await channel.send(message)
client.run(os.getenv('CLIENT_TOKEN'))
# Notice that I try to run the task after the client run
# Because I may call notify multiple times after the client has been created
client.loop.create_task(notify())
I want to invoke this function after the client has been created and without looping indefinitely.
Tried also to run
asyn def main():
await client.connect()
await client.log(client.run(os.getenv('CLIENT_TOKEN')))
await notify('My message', client)
# then
if __name__ = "__main__":
asyncio.run(main())
This just doesnt run ... having errors with http requests and so on.
client.loop.create_task(notify(*args))
That pass the function to be executed in the client's loop and will be called only once whenever you want to.
What I was looking for are webhooks.
The role of the client is to act on predefined events (like on start, on message received ... etc).
If we want to trigger something externally, Discord provides webhooks:
https://discordpy.readthedocs.io/en/stable/api.html?highlight=webhooks#discord.TextChannel.webhooks
Basically webhooks are unique urls for discord channels to which we can send data, the minimal data is of the form {'content': "my message}
which sends a simple message. You can improve this further by including embeds.
Here is an basic example using aihttp
from discord import Webhook, AsyncWebhookAdapter
import aiohttp
async def foo():
async with aiohttp.ClientSession() as session:
webhook = Webhook.from_url('url-here', adapter=AsyncWebhookAdapter(session))
await webhook.send('Hello World', username='Foo')
And here another example using Requests library
import requests
from discord import Webhook, RequestsWebhookAdapter
webhook = Webhook.partial(123456, 'abcdefg', adapter=RequestsWebhookAdapter())
webhook.send('Hello World', username='Foo')
I have been running the following code and after various changes the bot still never returns an welcome dm to the user, even after making sure that the permission to message users from the server is enabled.
import os
import discord
from dotenv import load_dotenv
load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')# gets the token of the bot from the .env file
client = discord.Client()# makes and discord client
#client.event #client on the following event:
async def on_ready():
print(f'{client.user} has connected to Discord!')# tells us if the bot is connected
#client.event
async def on_member_join(member):
await member.create_dm()# creates an dm channel
await member.dm_channel.send( # sends the string given as argument to the channel created
f'Hiiiiiiiiiii {member.name}, welcomeeeeeeeee icyyyyyy here'
)
client.run(TOKEN)# runs client for the bot token in TOKEN
And the code successfully returns that the bot is connected to discord and also comes online in the server.
You need to enable dm intents (there are quite a few so I suggest you enabling default intents) and intents.members
intents = discord.Intents.default()
intents.members = True
client = discord.Client(intents=intents)
Don't forget to enable privileged member intents in the developer portal
Also dm_channel can be None if it's not created, here's a better solution
await member.send('whatever')
I've been developing a discord bot for the past month, I've been doing commands using on_message listeners, which according to alot of people online isn't very ideal, so I decided to take it to the next step and do it properly, I looked at the documentation and came up with this basic code:
import discord #import all the necessary modules
from discord import Game
from discord.ext import commands
client = discord.Client() #define discord client
bot = commands.Bot(command_prefix='!') #define command decorator
#bot.command(pass_context=True) #define the first command and set prefix to '!'
async def testt(ctx):
await ctx.send('Hello!!')
#client.event #print that the bot is ready to make sure that it actually logged on
async def on_ready():
print('Logged in as:')
print(client.user.name)
await client.change_presence(game=Game(name="in rain ¬ !jhelp"))
client.run(TOKEN) #run the client using using my bot's token
Before going through the pain of implementing all of my commands to this new way of doing things, I wanted to test it so I know that it works for sure and sadly, it didn't, I went through a bunch of posts and documentation again but I couldn't spot what I did wrong, the bot logs in fine to the proper user and I just can't seem to figure out and understand what the problem is, I am probably missing something obvious yet again
Could anyone help, that would be great, thank you!
By saying client = discord.Client() you make an discord client which will be online of course (If it isn't even online tell me) and you made an discord bot with bot = commands.Bot(command_prefix='!'). The discord bot won't run, only the discord client will because you only did run the client with client.run(TOKEN). So a quick preview of what your code should be and would hopefully work:
import discord #import all the necessary modules
from discord import Game
from discord.ext import commands
bot = commands.Bot(command_prefix='!') #define command decorator
#bot.command(pass_context=True) #define the first command and set prefix to '!'
async def testt(ctx):
await ctx.send('Hello!!')
#bot.event #print that the bot is ready to make sure that it actually logged on
async def on_ready():
print('Logged in as:')
print(bot.user.name)
await bot.change_presence(game=Game(name="in rain ¬ !jhelp"))
bot.run(TOKEN) #run the client using using my bot's token