So basically i have this simple 'World Chat' script that lets people who have my bot and a channel called "world_chat" chat with each other in that channel, they can receive and send messages but the problem here is, every time they create a channel either with a command I gave or manually, they will be able to send messages and others can see it but they won't be able to see what others send till i reset the bot on heroku which I really don't want to do as when the bot gets in a lot of servers it'd be a lot of work.
#This is the script that let's people chat to each other
saki_chans=[]
async def get_saki_chans():
for i in client.servers:
for x in i.channels:
if x.type == discord.ChannelType.text and x.name ==
'world_chat' and x.id not in saki_chans:
saki_chans.append(x.id)
print(saki_chans)
#client.event
async def on_message(message):
if message.server and message.channel.name == 'world_chat' and
message.author.id != client.user.id:
for i in saki_chans:
if i == message.channel.id:
pass
else:
emb=discord.Embed(title='',description='{}'.format(message.content),colour
= discord.Color.gold)
emb.set_author(name= message.author.name)
await client.send_message(discord.Object(id=i),embed=emb)
And this is the script that creates the channel on a command
#client.command(pass_context=True)
async def get_wchat(ctx):
servr = ctx.message.server
await client.create_channel(servr, 'world_chat',
type=discord.ChannelType.text)
I expect when someone says '(prefix)create_wchat' it creates a channel called 'world_chat' but I don't have to restart the bot or script for the person to receive messages others send.
You have to call await get_saki_chans() in your get_wchat command to update your global channels list every time one is created.
Currently you only call it once, on startup, so that's why you have to restart your bot.
However, instead of asking the user to invoke a specific command, I suggest you listen to on_channel_create, on_channel_delete and on_channel_update events so simply creating a channel called #world_chat, or renaming an existing one to this name ; makes it a world_chat channel.
Similarly you would avoid keeping a channel no longer named #world_chat or deleted.
Related
So I made a discord bot that disconnects from a voice-channel whenever it finds itself alone in a call. This is how I do it: (note, I am using cogs)
#commands.Cog.listener("on_voice_state_update")
async def voiceStateUpdate(self, member, before, after):
voiceClient = discord.utils.get(self.bot.voice_clients, guild = member.guild) # Bot "voice_client"
if voiceClient.channel != None:
if len(voiceClient.channel.members) == 1:
await voiceClient.disconnect() # Disconnect
This works very well. But, if I forget to leave the call when I restart my code, I stay in the channel with my bot as it reboots (as expected). The problem arrives when I disconnect myself from the call. The bot stays in it, only outputting this error: (line 37, if voiceClient.channel != None:) AttributeError: 'NoneType' object has no attribute 'channel'
Maybe this is because it doesn't know it's still in the channel?
I'm so confused... Thanks for your time. :-)
You can query the voice channel much easier. Also, you need to request the event differently, even though your ("on_voice_state_update") is correct.
If the bot restarts, it leaves all voice channels immediately or after a few seconds/minutes, so you don't need to worry about that.
Have a look at the following event:
#commands.Cog.listener()
async def on_voice_state_update(self, member, before, after):
voice_state = member.guild.voice_client # Get the member in the channel
if voice_state is not None and len(voice_state.channel.members) == 1: # If bot is alone
await voice_state.disconnect() # Disconnect
Note that you have to enable the members Intent to get the len of channel.members. You can do that in the Discord Developer Portal and need to "import" the Intent(s) into your code.
I'm writing a discord bot for a server which I want to detect when someone has reacted to a message. It's working flawlessly for all messages that were sent while the bot is active. Any messages that were sent before the bot came online, however, are not picked up. Almost as if the bot simply isn't monitoring them.
Here is the code I'm using:
#client.event async def on_reaction_add(reaction, user):
#ensures the message is not from itself and it's in the right channel
if reaction.message.author == client.user or reaction.message.channel.name != 'basement-bets':
return
#calls the appropriate function based on the emoji sent by the mod
if reaction.emoji == '👍':
outPut = betting.bet_won(reaction.message.id)
await client.get_channel(channel).send('{0.author.mention}, '.format(reaction.message) + outPut)
print(outPut)
I've searched the API and I'm struggling to see why this is, or how I widen the scope of the bots view, should that be the issue.
All help greatly appreciated.
Edit: To clarify, I mean that once I turn it on and it's online, it won't monitor the messages sent prior to it being on. Even after coming online.
It Isn't Possible To Let The Bot Be Working While It's Offline. However, There Are Solutions.
Perhaps Try To Host Your Bot on Something Like Heroku, It Will Be Online For about 3/4 of the Month if You Use the Free Plan. (If You Have Trouble Getting It Up, Consider Watching a YouTube Tutorial)
If You Want It To Be Online 24/7 However, Then You Probably Will Need to Pay.
Just use the on_raw_reaction_add(payload) it can see every reaction happening but you have a payload in input see the code below to get the user and the reaction (doesn't work in DM's).
#bot.event
async def on_raw_reaction_add(payload):
if payload.guild_id == None: # payload.guild_id is None when it is in DM's (you can't get DM channel by id)
return
message = await bot.get_channel(payload.channel_id).fetch_message(payload.message_id)
reaction = nextcord.utils.get(message.reactions, emoji=payload.emoji.name)
user = payload.member
(code from Monu Yadav)
So I have a #support channel in which the members of my discord can type =support and the bot will message them to assist them, after that the bot will delete the =support command that the user typed in the channel to keep the channel clean, however in this channel they can also type any message that is not a command and the bot will not delete this, is there a way for the bot to delete a message if it isn't a command?
This can be done using on_message
#bot.event
async def on_message(m):
if m.channel.id == ChannelIDOfSupport Channel:
if m.content.replace(bot.prefix, "") not in [i.name for i in bot.commands]:
await m.delete()
So basically what I did is replace the actual command for a message listener and if it starts with support to do the command, then I restored the commands function. It looks like this:
async def on_message(m):
if m.channel.id == 735866701069025301:
if m.content.startswith('=ticket'):
await m.author.send('Your ticket will be created according to what you choose, use the = before choosing a number and then put the number next to it (Example: =2) \n \n **1. General Support** \n \n **2. Staff Application**')
await m.channel.purge()
else: {
await m.delete()
}
await client.process_commands(m)
The code below was somewhat functional however, all my #client.command or #bot.command if you want, were not functioning properly, not your fault #Poojan, I didn't paste code so you couldn't know if I was using commands instead of events.
The code above works perfectly, thank you for your help, thank you for your help too #Xetera, I followed the code and looked a bit into it and came to that conclusion :)
vvvvvvvvvvvv That answer helped me lots.
So, long story short I was making a bot that's supposed to send a direct message to a user after a command was executed, then wait a bunch of time before deleting it
It works fine and all now, but for a bit of time it didn't, and while I did some testing, my dms with that bot have been flooded with test messages
Is there any command I could add to delete every old messages that this bot sent to my dms ?
You could write a censor command that calls purge_from on the channel it's invoked from.
#bot.command(pass_context=True)
async def censor(ctx, limit: int= 100):
await bot.purge_from(ctx.message.channel,
check=lambda message: message.author == bot.user,
limit=limit)
I am trying to make a command called '!clear' that just removes the bots messages in a specific channel. This seems pretty straight forward using:
Client = discord.Client()
client = commands.Bot(command_prefix = "!")
#client.event
async def on_message(message):
if message.content.lower().startswith("!clear"):
async for x in client.logs_from(message.channel, limit = 100):
if str(message.author.id) == 'insert bots client id':
await client.delete_message(x)
client.run(token)
However, i found it wasn't deleting any messages. So before checking message.author.id i added a simple print(message.author.id) to see what ids it is picking up. It appears that it is spitting out only my client id and not seeing its own messages. The weird thing though is that if i change the author.id check to my client id then it will delete my messages and also the bots messages. So for some reason the bot thinks that its client id is the same as mine so when it is in a server that isn't my test server, it doesn't have the right permissions to delete my messages so it fails, even though I only want it to delete its own messages.
Any help would be great.
Don't you mean
if x.author.id == "bot id here":
await client.delete_message(x)
After all, each message is being put in x each iteration. Using message refers to the message in the async def on_message(message) function. Which would be the person who used the command. aka, you.