discord.py - on_message spam - jump_url - discord.py

I'm working on a logging bot. To do this I'm using on_message with jump_url to detect links, however the bot just spams it, I'm guessing this is because it reads its own message.
I have tried to stop it by checking if the message author is the user, however that didn't fix it. Whenever I type anything it logs it and has the link even though I didn't put in any link.
This is in a cog.
#commands.Cog.listener()
async def on_message(self, message):
embed=discord.Embed(title="Message from {} contains a link ".format(message.author.name), description="", color=0x607d8b)
embed.set_thumbnail(url="https://cdn.discordapp.com/avatars/9005083965732483134/14fcc0c2d369d9f4d742d9e8471d8536.webp?size=1024")
embed.add_field(name="Message:" ,value=message.jump_url, inline=True)
The code works; it's just that the bot spams the link. There is some code missing like channel.send as I'm connected to a database to log the channels people picked to log stuff.

There are a few ways you can combat this, I will show you two possible methods to avoid your problem.
Method 1 involves checking if the author of the message, message.author, is a bot through its attributes. This method ensures that if the user is a bot, then your bot will ignore the message.
Method 2 will only ignore your own bot. You can do this using self.bot, which you may have defined in your __init__. With this, you can compare if the message.author is your bot, and if it's True you may ignore it.
Do view the methods below as explained above.
#commands.Cog.listener()
async def on_message(self, message):
# Method 1
if message.author.bot:
return
# Method 2
if message.author == self.bot:
return
# Please note: You do not need to use both methods!

Related

How do I make it so that ctx is not of type 'interaction' (nextcord slash commands)?

I'm trying to create a music bot using nextcord slash commands and interactions. The command isn't fully finished yet, as I am having trouble getting it to even join the voice channel. I don't exactly know how interactions work yet but I'm assuming it's a similar concept as ctx. Below is my music.py cog:
import nextcord
from nextcord.ext import commands
from nextcord import Interaction
class Music(commands.Cog):
def __init__(self, client):
self.client = client
guild_ids = ["Guild Ids Go Here"]
#slash commands go under here
#nextcord.slash_command(name="play", description="plays music in vc", guild_ids = guild_ids)
async def play(self, interaction : Interaction, query: str):
channel = interaction.author.voice.channel #ERROR IS HERE
try:
await channel.connect()
await interaction.response.send_message("The bot has joined vc.")
except:
await interaction.response.send_message("Failed to find voice channel.")
def setup(client):
client.add_cog(Music(client))
I'm getting an error that says "'Interaction' object has no attribute 'author'. It occurs on line 15 in 'play' when it says 'channel = interaction.author.voice.channel'. I think this means that this isn't the right way to go about getting the author's voice channel. If this is the case, is there a better, working method?
In nextcord interaction, message author is interaction.user,
channel is interaction.channel.
You also can send interaction message by interaction.send instead
of interaction.response.send_message. It's much shorter and easier
to read.
If you want to send a normal message without using interaction, try
interaction.channel.send. It's similar to ctx.channel.send in application command

Sending a user specified message into a specified channel

This bot is only going to be for personal use, so I don't need to make it customizable from discord itself. I was wondering if I can use ctx.send and channel.send somehow together if this makes sense. Here is my code to help you understand what I mean:
client = commands.Bot(command_prefix='!')
channel = client.get_channel(883389016819511296)
#client.command(name='say')
async def say(ctx, *, content):
await ctx.send(content) # here I want to send it to the channel I already defined
channel.send would be an option, but I also want to send the message, so if I am right I need to use ctx.
No, you need to use channel.send as you are sending the content to the specified channel. If you use ctx.send it will just send in the same channel as the command was executed in. And theres an easier way to do this if you wanna see and example i have one here
#client.command() async def say(ctx, channel: discord.TextChannel, *, message: str): await channel.send(message)
That is an easier way and you can "#" the text channel so for example if you want to send a message in general for your bot it would be: !say #general hello
However if you only wish to do that and not use my example then you should do it like this:
#client.command(name='say') async def say(ctx, *, content): channel = client.get_channel(883389016819511296) await channel.send(content)

Trying to make a suggestion but channel id gives an error for the command

I've got an issue but I am getting no errors and from the code I just wrote as shown below
#client.commands
async def hello():
channel = int(797915093954199565)
await channel.send('Hey what are you doing?')
I am trying to make a command where the user can talk to the bot, and it responds back with something, its just a starting command but I'm having trouble with these small things, the rest of the bot works but its just this issue i'm having please help!
So assuming the rest of your bot and code works, your "hello" command isn't working because you have
#client.commands #its client.command in this case, as it seems you are not using any cogs, and you must call the client with () these double parentheses
async def hello(): #Here you have not passed ctx
channel = int(793744805615632394) #It seems what you would like to do here is send it to a specific channel, however, in the code below, I have set it so it just sends to the channel it was used in. The correct use is client.get_channel(793744805615632394)
await channel.send('Hey what are you doing?')
Here is the command but fixed:
So assuming the rest of your bot and code works, your "hello" command isn't working because you have
#client.command()
async def hello(ctx):
await ctx.send('Hey what are you doing?')
You should also refer to the py docs to learn more about it: https://discordpy.readthedocs.io/en/latest/

How to implement Patreon-only commands for a discord bot?

So i have seen another post with almost the exact same question however, mine is different.
I am fully aware there is a Patreon bot, however to my knowledge this is only valid on servers.
So lets say someone invites my bot, and tries a command that requires them to be a patron. How could my bot written in python do a check to see if they have become a patron for my product? And then set a role for them accordingly. Which i can then do the check on to allow them access to the command or not.
So essentially, it should do what the Patreon bot does, however would work on its own. Examples are such as the Dank Memer bot: which can be invited to any server and if one becomes a patron can use specific commands, otherwise you can't
I've looked around this topic for a while now and haven't been able to find any info on how to check if the user has become a patron or not.
Many thanks in advance!
If you know the patreons. just give them a role [patreons] or any name!
after giving them the role. copy the role id and paste it in patreons_role_id
ok, what this command does is, just it check for the [patreons] role in the member roles! if the [patreons] role is present! it will execute the #your code else it sends a custom message!
#client.event()
async def on_message(message):
if message.content == '!test':
is_patreon = False
for user_roles in message.author.roles:
if user_roles.id == patreons_role_id:
is_patreon = True
break
if is_patreon == True:#your code
else: await message.channel.send('THIS COMMAND IS ONLY AVAILABLE FOR PATREON!')
Let's assume you have a role for your patreons.
#client.command()
#commands.has_roles("PatreonRole")
async def commandname(ctx, args):
#do stuff
There is a way out, but its probably not the right one, so, If you know who your patreons are and you know their discord IDs as well, you can declare an if statement in the command similar to this -
#client.command()
async def your_command_name():
if member.id == #Your 1st Patreon's Discord ID:
#Your Code
elif member.id == #Your 2nd Patreon's Discord ID:
#Your code
else:
await ctx.send("You cannot use that command as you are not a patreon!")
But again this is probably not right way if you have a lot of patreons or you dont know their Discord IDs, but anyways this way was the only way I could come up with.
I hope that helped. :)

Bot wont properly print member_count

So I'm new to Python and I decided to take the plunge and make a Discord bot for personal use in my server. I like the idea of having full control over what features my bot will have so I'm slowly building the bot. Currently I want my bot to show the current number of members in the server when called with a command
import discord
from discord.ext import commands
#botbot.command()
async def server(ctx):
guild = discord.Guild.member_count
await ctx.send(guild)
I know I'm most likely way off with my code here.
While the bot is sending a message into the chat, its formatted as:
<property object at 0x046036C0>
While I would like to have it say something like "This server has {some number} members."
Any advice is really appreciated!
Thank you for your time.
Edit: botbot is the name for my bot, just so thats clear.
discord.Guild is the class. You want to get the guild the command is in from the invocation context:
#botbot.command()
async def server(ctx):
await ctx.send(f"This server has {ctx.guild.member_count} members.")
The method member_count is not really what you want in this occasion, the guild object has a list called members, so it's as easy as getting the length of that list like so:
#botbot.command()
async def server(ctx):
guild = len(discord.guild.members)
await ctx.send(guild)
EDIT: And indeed you have a typo with using "Guild" instead of "guild"

Resources