I'm making an economy bot and this is the first time I've used Cogs.
For some reason, every time I trigger a command it sends more than one message. I've also seen a pattern where for every command the amount of messages sent is one more than the previous command.
Here is my code:
import discord
from discord.ext import commands
import json
class currencyCog(commands.Cog):
def __init__(self, bot):
self.bot = bot
global currency
with open('cogs/data/currency.json') as f:
currency = json.load(f)
def _save(self):
with open('cogs/data/currency.json', 'w+') as f:
json.dump(currency, f)
async def new_user(self, id:int):
currency[str(id)] = {
"cash": 100,
"multi": 1,
"upgrades": {
"click_max": 100
},
"items": {
"beginner-crate": 1
}
}
self._save()
user = self.bot.get_user(id)
await user.send('message')
#commands.Cog.listener()
async def on_command(self, ctx):
id = ctx.author.id
if str(id) in currency:
pass
else:
await self.new_user(id)
#commands.command()
async def test(self, ctx):
await ctx.send('beep')
Note: I have no other instances of the bot running. I'm using Sublime text 3's python build to run my code.
Output:
Click here
Related
I'm trying to make a discord.py bot with the help of nextcord and i've come far enough to make the code work in theory but nothing happens when i try to kick / ban, it just throws an
nextcord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'Context' object has no attribute 'ban'
and i have no idea why it does so, i want it to work as inteded.
Note, the command(s) are class commands so the main bot loads in the command from another file.
Main Bot Script
# import nextcord
from nextcord.ext import commands
# import asyncio
import json
# Import all of the commands
from cogs.ban import ban
from cogs.hello import hello
from cogs.help import help
from cogs.info import info
from cogs.kick import kick
from cogs.test import test
#Define bot prefix and also remove the help command built in.
bot = commands.Bot(command_prefix=json.load(open("config.json"))["prefix"])
bot.remove_command("help")
#bot.event
async def on_ready():
print(f'Logged in as {bot.user}')
bot.add_cog(hello(bot))
bot.add_cog(help(bot))
bot.add_cog(info(bot))
bot.add_cog(test(bot))
bot.add_cog(ban(bot))
bot.add_cog(kick(bot))
bot.run(json.load(open("config.json"))["token"])
Problematic command
import discord
from nextcord.ext import commands
from nextcord.ext.commands import has_permissions, CheckFailure
bot = commands.bot
class ban(commands.Cog):
def __init__(self, client):
self.client = client
self._last_member = None
#commands.Cog.listener()
async def on_ready(self):
print('ban Cog Ready')
#commands.command()
#has_permissions(ban_members=True)
async def ban(ctx, user: discord.Member = None, *, Reason = None):
if user == None:
await ctx.send("Could you please enter a valid user?")
return
try:
await user.ban(reason=Reason)
await ctx.send(f'**{0}** has been banned.'.format(str(user)))
except Exception as error:
if isinstance(error, CheckFailure):
await ctx.send("Looks like you don't have the permissions to use this command.")
else:
await ctx.send(error)
You are doing:
user: discord.Member
You need to use nextcord instead.
user: nextcord.Member
#commands.command()
#has_permissions(ban_members=True)
async def ban(ctx, user: nextcord.Member = None, *, Reason = None):#
#The rest of your code here
You can do the following
For Normal bot
#client.command(name="ban", aliases=["modbancmd"], description="Bans the mentioned user.")
#commands.has_permissions(ban_members=True)
async def ban(self, ctx, member: nextcord.Member, *, reason=None):
# Code for embed (optional)
await member.ban(reason=reason)
# (optional) await ctx.send(embed=banembed)
You can do the following
For Cogs
#commands.command(name="ban", aliases=["modbancmd"], description="Bans the mentioned user.")
#commands.has_permissions(ban_members=True)
async def ban(self, ctx, member: nextcord.Member, *, reason=None):
# Code for embed (optional)
await member.ban(reason=reason)
# (optional) await ctx.send(embed=banembed)
Well, here are the problems:
Your command is in a cog therefore you need to say (self, ctx, and so on)
You need to change the discord to nextcord
You should change the commands.bot to commands.Bot()
And if I'm correct, you should change the self.client to self.bot since your commands.Bot() is defined as bot
And uhh yeah it should work perfectly after you fix those.
import discord
from discord.ext import commands
class AntiCog(commands.Cog):
def __init__(self, client):
self.client = client
#commands.Cog.listener()
async def on_message(self, message):
if message.author.id == 1234567891234567:
mention = f'<#!1234567891234567>'
if message.content == mention:
await message.channel.send("grow up")
user = message.author
print(str(user))
print(str(message.content))
muted_role = discord.utils.get(message.guild.roles, name="Muted")
await user.add_roles(muted_role)
else:
return
await self.client.process_commands(message)
def setup(client):
client.add_cog(AntiCog(client))
This's a working code for muting a person if they ping another person, however, I would like to make it a timed mute for 5 min. All of the resources I found were on_command timed mute, however, this's an auto one, how can I do so. thank you!
All you would have to do is add asyncio.sleep, and then remove the role, so:
import discord
from discord.ext import commands
import asyncio
class AntiCog(commands.Cog):
def __init__(self, client):
self.client = client
#commands.Cog.listener()
async def on_message(self, message):
if message.author.id == 1234567891234567:
mention = f'<#!1234567891234567>'
if message.content == mention:
await message.channel.send("grow up")
user = message.author
print(str(user))
print(str(message.content))
muted_role = discord.utils.get(message.guild.roles, name="Muted")
await user.add_roles(muted_role)
await asyncio.sleep(300) # you can change the time here
await user.remove_roles(muted_role)
else:
return
await self.client.process_commands(message)
def setup(client):
client.add_cog(AntiCog(client))
Be sure to import asyncio!
i write bot on discord py with cogs.
main:
intents = discord.Intents.all()
client = discord.Bot(command_prefix = '$', intents = intents)
for files in os.listdir('./cogs'):
if files.endswith('.py'):
client.load_extension(f'cogs.{files[:-3]}')
token = os.environ.get('token')
client.run(token, bot=True)
and cog:
class textCommands(commands.Cog):
def __init__(self, client):
self.client = client
#commands.command()
async def ping(self, ctx):
await ctx.send(f'Pong! {round(self.client.latency * 1000)}ms')
def setup(client):
client.add_cog(textCommands(client))
And my bot send two messages if i send 'ping', i changed my token, but problem still have.
so, I found the answer. I remove await self.client.process_commands(message) from my code and twices messages lose
I want to know in which text channels admin want to enable my bot functions. But in this case my code is not working.
The main idea was when admin typing !enable in text-chat, bot reacts to it and add text-chat id, guild id(ctx.channel.id) to the list, then bot responds in chat with bot has been enabled.
code where this command is not working:
channel = []
#bot.command()
async def enable(ctx):
global channel
print("Debug")
await ctx.send('Restriction bot has been enabled for this text channel.')
channel.append(ctx.channel.id)
full bot code:
import discord
from discord.ext import commands
bot = commands.Bot(command_prefix='!')
#bot.event
async def on_ready():
print(f'We have logged in as {bot.user.name}.')
channel = []
#bot.command()
async def enable(ctx):
global channel
print("Debug")
await ctx.send('Restriction bot has been enabled for this text channel.')
channel.append(ctx.channel.id)
#bot.event
async def on_message(ctx):
if ctx.author == bot.user:
return
#if ctx.channel.id != [for channnels in channel]:
# return
if ctx.attachments[0].height:
await ctx.author.send('Your media file is restricted!')
await ctx.delete()
The channel variable is initialized in your program so each time you will restart your bot, it will be emptied. One way you can solve your problem is by storing them in a file. The easiest way to do it would be to use the json library. You'll need to create a channels.json file.
The code :
from json import loads, dumps
def get_data():
with open('channels.json', 'r') as file:
return loads(file.read())
def set_data(chan):
with open('channels.json', 'w') as file:
file.write(dumps(chan, indent=2))
#bot.command()
async def enable(ctx):
channels = get_data()
channels.append(ctx.channel.id)
set_data(channels)
await ctx.send('Restriction bot has been enabled for this text channel.')
The channels.json file :
[]
I have a problem with the discord.py Python library. I'm getting an error, every time someone reacts to messages.
Python do not show me, where the error comes from, but I think it's an error in the discord.py.
Last week the code worked but now its not working anymore. I'm becoming a headache about it. Can someone help my please?
Here is my code:
import discord
from emojis import emojis
import msg
from discord.utils import get
from discord.ext import commands
import json
from uuid import uuid4
shop_channels = []
orders = {}
cmd_prefix = "dsb!"
def check_perms(user):
for role in user.roles:
if role.name == "𝗢𝘄𝗻𝗲𝗿":
return True
return False
def check_command(message, command):
if message.startswith(cmd_prefix + command):
return True
else:
return False
def save_settings():
settings = {}
settings["shop_channels"] = shop_channels
settings["orders"] = orders
with open("data.json", "w") as file:
json.dump(settings, file)
def load_settings():
global shop_channels
global orders
with open("data.json") as file:
settings = json.load(file)
orders = settings["orders"]
shop_channels = settings["shop_channels"]
print(shop_channels)
class MyClient(discord.Client):
async def on_ready(self):
self.msg = msg.Msg(True, "DiShoBo")
print('-------')
print('Logged in as')
print('Username:', self.user.name)
print('ID:', self.user.id)
print('------', end="\n\n")
load_settings()
print("Settings loaded!\n\n")
async def on_reaction_add(self, reaction, user):
print("hello")
if shop_channels is None or reaction.message.channel.id not in shop_channels:
return
try:
if reaction.emoji == emojis["shopping_cart"]:
order_id = uuid4()
item = reaction.message.content.partition('\n')[0]
amount = reaction.message.content.partition('\n')[2]
self.msg.debug("Got new order from user {0} for Item: {1}! OrderID: {2}".format(
user, item, order_id))
if user.dm_channel == None:
await user.create_dm()
message = await user.dm_channel.send("You ({2}) added the Item: '{0}' for {1} to your shopping cart!\nClick on :white_check_mark: to finish your order then go back to Angels 2B2T shop, or if you want to keep shopping, just go back to the shop and add more items.\nIf you want to clear your shopping cart, click the {3} below.\n\nYour OrderID is: {4}".format(item, amount, user.mention, emojis["cross_mark"], order_id))
# await message.add_reaction(emojis["check_mark_box"])
# await message.add_reaction(emojis["cross_mark"])
if not message.author in orders:
orders.update(
{message.author: {"user": message.author, "ID": order_id, "items": []}})
print(orders[message.author]["items"])
orders[message.author]["items"].append({item, amount})
print(orders[message.author]["items"])
if not reaction.me and reaction.count > 1:
await reaction.remove(user)
else:
await reaction.remove(user)
except:
pass
# * CONNECT
client = MyClient()
client.run('TOKEN')
This was a bug on the hand of the discord.py library but was fixed in the update 1.3.2.