Discord.py: Why do the welcome and goodbye messages repeat? - python

Problem: I am trying to have it so that the bot sends a single message in general, but the messages continuously repeat, seemingly increasing each time this occurs. Also, if I switch the message to something else, the repeated parts are of the old message.
Code:
import discord
from discord.ext import commands
client=commands.Bot(command_prefix = '.')
#client.event
async def on_ready():
print('ok')
#client.event
async def on_member_join(member):
channel=discord.utils.get(member.guild.channels, name="general")
await channel.send("Hi {}".format(member))
#client.event
async def on_member_remove(member):
channel=discord.utils.get(member.guild.channels, name="general")
await channel.send("Bye")
client.run(token)

Since the code is under the function variable then you have to end each function.

It might be due to multiple instances of the application are running. Check your task manager and search for python process, End it if there are multiple and re-run the script.

Related

Sending messages in discord.py #tasks.loop()

Goal:
I am simply trying to send a message to a discord channel from a #tasks.loop() without the need for a discord message variable from #client.event async def on_message. The discord bot is kept running in repl.it using uptime robot.
Method / Background:
A simple while True loop in will not work for the larger project I will be applying this principle to, as detailed by Karen's answer here. I am now using #tasks.loop() which Lovesh has quickly detailed here: (see Lovesh's work).
Problem:
I still get an error for using the most common method to send a message in discord using discord.py. The error has to have something to do with the await channel.send( ) method. Neither of the messages get sent in discord. Here is the error message.
Code:
from discord.ext import tasks, commands
import os
from keep_alive import keep_alive
import time
token = os.environ['goofyToken']
# Set Up Discord Client & Ready Function
client = discord.Client()
channel = client.get_channel(CHANNEL-ID)
#client.event
async def on_ready():
print('We have logged in as {0.user}'.format(client))
#tasks.loop(count=1)
async def myloop(word):
await channel.send(word)
#client.event
async def on_message(message):
msg = message.content
if msg.startswith('!'):
message_to_send = 'Hello World!'
await channel.send(message_to_send)
myloop.start(message_to_send)
keep_alive()
client.run(token)
Attempted Solutions:
A message can be sent from the on_message event using the syntax await message.channel.send('Hello World!). However, I just can't use this. The code is kept running online by uptimerobot, a free website which pings the repository on repl.it. When the robot pings the repository, the message variable is lost, so the loop would stop scanning my data in the larger project I am working on which is giving me this issue.
When using any client.get_* method the bot will try to grab the object from the cache, the channel global variable is defined before the bot actually runs (so the cache is empty). You should get the channel inside the loop function:
#tasks.loop(count=1)
async def myloop(word):
channel = client.get_channel(CHANNEL_ID)
await channel.send(word)

How can I make discord.Client in a class correctly and run as a task in my loop?

I'm working with Discord.py and I need to make discord.Client run in my own loop, because I want it to run multiple times (for more bots, so I don't have to make more and more files just so they run both at the same time).
This is the easiest example I could make:
import discord
import asyncio
from discord.ext import commands
token = "token"
class Client(discord.Client):
#commands.Cog.listener()
async def on_ready():
print(self.user.id)
#commands.command()
async def testing(ctx):
await ctx.send("hello")
loop = asyncio.get_event_loop()
client = Client(command_prefix="!")
loop.create_task(client.start(token))
loop.run_until_complete
It doesn't return anything at all; it just closes itself. I know I have errors there, but I don't know which and why. How can I fix them?
First, you're mixing discord.Client and commands.Bot/commands.Cog
class Client(discord.Client):
should be
class Client(commands.Cog):
And trying to run multiple bots by looping it is not going to go well. I intensely encourage you to just make multiple files.
Also, it should be:
def setup(client):
client.add_cog(Client(client))
If you're making it a cog, then you have to load it in another file.
If you just want a singular file then it should look like:
class Client(commands.Bot):
#bot.event
async def on_ready():
print(self.user.id)
#bot.command()
async def testing(ctx):
await ctx.send("hello")
client = Client(command_prefix="!")
client.run(token)

discord.py bot isn't answering when mentioned from phone app

I made recently a discord bot for small server with friends. It is designed to answer when mentioned, depending on user asking. But the problem is, when someone mention bot from a phone app, bot is just not responding. What could be the problem?
Code:
import discord
from discord.ext import commands
from discord.ext.commands import Bot
import asyncio
bot = commands.Bot(command_prefix = '=')
reaction = "🤡"
#bot.event
async def on_ready():
print('Bot is ready.')
#bot.listen()
async def on_message(message):
if str(message.author) in ["USER#ID"]:
await message.add_reaction(emoji=reaction)
#bot.listen()
async def on_message(message):
mention = f'<#!{BOT-DEV-ID}>'
if mention in message.content:
if str(message.author) in ["user1#id"]:
await message.channel.send("Answer1")
else:
await message.channel.send("Answer2")
bot.run("TOKEN")
One thing to keep in mind is that if you have multiple functions with the same name, it will only ever call on the last one. In your case, you have two on_message functions. The use of listeners is right, you just need to tell it what to listen for, and call the function something else. As your code is now, it would never add "🤡" since that function is defined first and overwritten when bot reaches the 2nd on_message function.
The message object contains a lot of information that we can use. Link to docs
message.mentions gives a list of all users that have been mentioned in the message.
#bot.listen("on_message") # Call the function something else, but make it listen to "on_message" events
async def function1(message):
reaction = "🤡"
if str(message.author.id) in ["user_id"]:
await message.add_reaction(emoji=reaction)
#bot.listen("on_message")
async def function2(message):
if bot.user in message.mentions: # Checks if bot is in list of mentioned users
if str(message.author.id) in ["user_id"]: # message.author != message.author.id
await message.channel.send("Answer1")
else:
await message.channel.send("Answer2")
If you don't want the bot to react if multiple users are mentioned, you can add this first:
if len(message.mentions)==1:
A good tip during debugging is to use print() So that you can see in the terminal what your bot is actually working with.
if you print(message.author) you will see username#discriminator, not user_id

Why can't I use command prefixes?

Every I try to use the commands.Bot(command_prefix=''), the program reads it as an error. For example, with the code below, it comes out with
Ignoring exception in command None: discord.ext.commands.errors.CommandNotFound: Command "-ping" is not
found Ignoring exception in command None:
discord.ext.commands.errors.CommandNotFound: Command "ping" is not
found
and is repeated a few times before what i wanted the bot to say (Pong!), is sent 2 or more times in the server...
\I think it might be looping? I'm not sure, but I got it to work once, but the longer I waited, every time used the command it sent more responses? -it sent 16 'Pong's last time I tried... Is there anything I can do about this?\
How can i fix this?
from discord.ext import commands
client = commands.Bot(command_prefix='-')
#client.event
async def on_ready():
print("Bot is ready for use...")
#client.command()
async def ping(ctx):
await ctx.send('Pong')
client.run('TOKEN')
The problem doesn't come from you prefix, you just forgot parentheses after your client.command decorator:
from discord.ext import commands
client = commands.Bot(command_prefix='-')
#client.event
async def on_ready():
print("Bot is ready for use...")
#client.command()
async def ping(ctx):
await ctx.send('Pong')
client.run('TOKEN')
The client.event decorator doesn't have any arguments so you don't need parentheses but client.command() can have arguments like name=, brief=, description=, aliases, ... so you need parentheses. ^^

Discord bot commands execute multiple times

It worked at first, but then somewhy it started to give the answers 4-5 times at once, any idea why?
import discord
from discord.ext import commands
client = commands.Bot(command_prefix = '.')
#client.event
async def once_ready():
print('Bot is ready.')
#client.event
async def on_member_join(member):
print(f'{member} has joined the server.')
#client.event
async def on_member_remove(member):
print(f'{member} has left the server.')
#client.command()
async def ping(ctx):
await ctx.send('Pong!')
client.run('my token here')
So, the problem was that I couldn't shut down the already running bots in Atom.
If you add the code that I wrote down there (that only the owner can
use) will shut down the already running bots (write /shutdown in
discord server or whatever your prefix is).
However, you may need a PC restart after saving the bot with this code.
#client.command()
#commands.is_owner()
async def shutdown(ctx):
await ctx.bot.logout()
So every time if you want to edit your command, you write /shutdown
and edit it, after that, you can start it again.
I hope this works for you and that I could help if you had the same problem.

Categories