So I am creating a simple bot that detects when somebody joins a server and when somebody leaves the server.
I added a command to show people's avatars, but any time I do it, or when somebody joins or leaves, it sends the message more than once.
I've searched and I can't find the problem.
Can you guys help me?
Here's my code
import discord
from discord.ext import commands
client = commands.Bot(command_prefix="?")
#client.event
async def on_ready():
print("Ready")
#client.event
async def on_member_join(member):
channel = discord.utils.get(member.guild.text_channels, name="entradas")
await channel.send(f"{member} is new on the server, everyone say hi")
show_avatar = discord.Embed(color = discord.Color.blue())
show_avatar.set_image(url="{}".format(member.avatar_url))
await channel.send(embed=show_avatar)
#client.event
async def on_member_remove(member):
channel = discord.utils.get(member.guild.text_channels, name="saidas")
await channel.send(f"{member} left the server, press F to pay respects")
#client.command()
async def avatar(ctx, member: discord.Member):
show_avatar = discord.Embed(color = discord.Color.blue())
show_avatar.set_image(url="{}".format(member.avatar_url))
await ctx.send(embed=show_avatar)
You should check if you are running 2 bots.
If you are running your bot on Linux with screen, simply check with
screen -ls
on windows, just check the task-manager and look under something like Python.
It's btw possible to have the same bot running twice.
Related
I would like to be able to asynchronously send inputs to my python terminal and have my bot output them, whilst also keeping my other event running.
import nextcord
import botToken #contains the string of my bot token
from nextcord.ext import commands
client = commands.Bot(command_prefix="!")
#client.event
async def on_ready():
general = client.get_channel(925388635304521859)
while True:
inp = input("->")
if len(inp) < 4001:
await general.send(inp)
else:
await general.send(inp[0: 1500])
#client.event
async def on_message(message): #its supposed to react to each message with a buffalo emoji
print(message.content)
channel = message.channel
if "<#!308022163330564099>" in message.content:
await message.delete()
await channel.send("🐃")
await message.add_reaction("🐃")
client.run(botToken.TOKEN)e
Currently the on_ready() event only loads when it starts which is good, but i would like it to be asyncronic if thats a possibility. I don't know much about nextcord so I have no ideas. I would love any ideas for this.
The tasks extension in Nextcord may help for what you are trying to do
https://nextcord.readthedocs.io/en/latest/ext/tasks/index.html
It allows you to execute code in the background using a loop.
from nextcord.ext import tasks
#tasks.loop(seconds=1.0)
async def my_task_loop():
print("Hello!")
#my_task_loop.before_loop
async def before_my_task_loop():
print('waiting for ready')
await self.bot.wait_until_ready()
my_task_loop.start()
So, what I want to do is stop a specific role from speaking in a channel on discord using discord.py.
Here's what I have so far.
import discord
import os
from keep_alive import keep_alive
client = discord.Client()
#client.event
async def on_ready():
print('We have logged in as {0.user}'.format(client))
#client.event
async def on_message(message):
countingBotGuildSave = ['test']
if any(word in message.content for word in countingBotGuildSave):
await message.channel.set_permissions(discord.utils.get(message.guild.members, name='Foo'), send_messages=False)
await message.channel.send('**An admin/moderator has locked this channel. Please wait for an admin to unlock this channel with `+unlock`.**')
print(f'{message.author} locked channel {message.channel}')
keep_alive()
client.run(os.getenv('TOKEN'))
This doesn't cause any errors when I run the bot, but when I say test in discord it says: target parameter must be either Member or Role. I don't understand because I made a role named Foo.
Can you pls help?
Tysm.
The error itself tells you what went wrong. Your await function does not make any sense in that case. You are looking for guild.members with the name Foo but what you want is the role.
Have a look at the following code:
#client.event
async def on_message(message):
countingBotGuildSave = ['test']
if any(word in message.content for word in countingBotGuildSave):
await message.channel.set_permissions(discord.utils.get(message.guild.roles, name='Foo'), send_messages=False) # Get the role
await message.channel.send('**An admin/moderator has locked this channel. Please wait for an admin to unlock this channel with `+unlock`.**')
print(f'{message.author} locked channel {message.channel}')
Here we are looking for a role in the guild named Foo. You can also just use the ID to change the name to whatever you want to without editing the code (id=RoleID).
The output:
i have a problem with my discord bot, whenever i run the code below using apraw to get the titles of the recent submissions on a subreddit the bot doesn't appear online anymore but still returns the titles in CMD :
Bot is not online when i execute this but still asks for subreddit name & prints the titles of the new posts of the subreddit in CMD:
import asyncio
import apraw
from discord.ext import commands
bot = commands.Bot(command_prefix = '?')
#bot.event
async def on_ready():
print('Bot is ready')
await bot.change_presence(status=discord.Status.online, activity=discord.Game('?'))
#bot.command()
async def online (ctx):
await ctx.send('Bot is online !')
reddit = apraw.Reddit(client_id = "CLIENT_ID",
client_secret = "CLIENT_SECRET",
password = "PASSWORD",
user_agent = "pythonpraw",
username = "LittleBigOwl")
#bot.event
async def scan_posts():
xsub = str(input('Enter subreddit name : '))
subreddit = await reddit.subreddit(xsub)
async for submission in subreddit.new.stream():
print(submission.title)
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(scan_posts())
bot.run('TOKEN')
But is online when i execute this but obviously doesn't ask for sub name... :
import asyncio
import apraw
from discord.ext import commands
bot = commands.Bot(command_prefix = '?')
#bot.event
async def on_ready():
print('Bot is ready')
await bot.change_presence(status=discord.Status.online, activity=discord.Game('?'))
#bot.command()
async def online (ctx):
await ctx.send('Bot is online !')
bot.run('TOKEN')
So reddit is the problem here. But what exaclty do i ahve to change in order to make my bot apear online whilst still being able to retreive the titles of new submissions on a given subreddit? The code doesn't return any error:/
the #bot.event that you put above async def scan_posts(): should be changed to #bot.command(). It triggers by itself because you have this in your code:
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(scan_posts())
this is what causes the scan_posts to run automatically. You should remove this as you want scan_posts to be a bot command and not something that happens automatically. The bot also doesn't come online because of this code. What this does is check if this file has been run and then runs scan_posts. The rest of the code won't be triggered.
Also, you shouldn't change presence in on_ready as Discord has a high chance to completely disconnect you during the on_ready event and there is nothing you can do to prevent it. Instead you can use the activity and status kwargs in commands.Bot like:
bot = commands.Bot(command_prefix = '?', status=discord.Status.online, activity=discord.Game('?'))
i'm trying this code but it is not working
from discord.ext import commands
#commands.command(pass_context=True)
async def myid(ctx):
print(ctx.guild.member_count)
client.run(my token)
can you provide me right code
I found a solution for the problem statement, if we need to find name of total members of our servers. then use this code.
import discord
client = discord.Client()
token = 'your token'
#client.event
async def on_ready():
users = client.users
print(users)
#or
guilds = client.get_guild
for guild in client.guilds:
print(guild.name)
for member in guild.members:
print(member)
client.run(token)
As what Patrick Haugh said, you did not define your client yet. Also, pass_context is no longer needed in discord rewrite.
The most basic code would look something like this:
from discord.ext import commands
client = commands.Bot(command_prefix = 'PREFIX')
#client.command()
async def myid(ctx):
print(ctx.guild.member_count)
client.run('TOKEN')
Where PREFIX is whatever command prefix you want and TOKEN is your bot token
I suggest reading the discord.py documentation for more information
#bot.command()
async def members(ctx):
embedVar = discord.Embed(title=f'There Are {ctx.guild.member_count} Members In This Server', color=0xFF0000)
await ctx.send(embed=embedVar)
This also works but sends in server, not console.
Discord.py, how to set a command, without Prefix, only with certain word to which bot replies, and also bot replies to that command while Dm with the bot.
Remember about the errors for example, bot object has no attribute on_message, etc, errors.
You can write a function to pass to command_prefix that will check for one prefix in servers and another (or none) in private messages:
from discord.ext import commands
def command_prefix(bot, message):
if message.guild is None:
return ''
else:
return '$'
bot = commands.Bot(command_prefix=command_prefix)
#bot.command(name='hello')
async def hello(ctx):
await ctx.send("Hello")
bot.run("TOKEN")
If you are using this in a cog.
#commands.Cog.listener()
async def on_message(self,message):
await message.send("Hello!")
or in the main.py
#bot.event
async def on_message(message):
await message.send("Hello!")
Please reply back if you have an error with this.
message.guild will return None if the message is in dms.