Discord.py member.timeout() function doesnt work - python

Im trying to make a Discord Bot that is able to Timeout users.
The general idea is that my friends and I can timeout eachother with tickets for about a minute.
But I cant get the discord.Member.timeout() to work.
I looked into the Discord.py doc but I cant find my mistake.
Down below I have put the important code as bold.
The error occures at
print("1")
await member1.timeout(timeout)
print("2")
The program prints "1" and thats it.
The only error message I get is from Discord (This interaction wasnt succesfull)
Please help me.
import discord
from discord.ext import commands
import json
import random
from discord import app_commands
import datetime
member1 = discord.Member
class SelectMenu3(discord.ui.View):
options1 = [
discord.SelectOption(label="Timeouten", value="1", description="Timeout someone"),
discord.SelectOption(label="Enttimeouten", value="2", description="Opposite")
]
#discord.ui.select(placeholder="Options", options=options1)
async def menu_callback3(self, interaction: discord.Interaction, select):
with open("cogs/eco.json", "r") as f:
user_eco = json.load(f)
global member1
member = interaction.user
select.disabled = True
eco_embed = discord.Embed(title="Timeouts", description="", colour=discord.Color.blue())
eco_embed.add_field(name="Amount Timeout:", value=f"{user_eco[str(member.id)]['Timeout']}")
**if select.values[0] == "1":
if user_eco[str(member.id)]['Timeout'] >= 1:
timeout = datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=1, hours=0, weeks=0)
print("1")
await member1.timeout(timeout)
print("2")
else:
await interaction.response.send_message(content="Du hast nicht genug Timeout-Tickets für diese Aktion",
ephemeral=True)
**
elif select.values[0] == "2":
if user_eco[str(member.id)]['Timeout'] >= 1:
pass
else:
await interaction.response.send_message(content="Du hast nicht genug Timeout-Tickets für diese Aktion",ephemeral=True)
**#app_commands.command(name="timeout", description="")
async def timeout(self, interaction: discord.Interaction, member: discord.Member):
global member1
member1 = member
view = SelectMenu3()
await interaction.response.send_message(content="Choose", view=view,
ephemeral=True)
**

I just found the problem, in Discord Roles exist and a User whos Role is lower in the hierarchy cant timeout any users that are higher up.
Therefore I just had to move up my Bots Role to be at the top (still below my own role as a safety measure) and everything is working just fine now.

Related

Discord.py bot won't respond to commands... except it's a leveling system

Edit: I probably should have added that I did all of the following code on repl.it, though I doubt it makes any difference.
Edit 2: I don't know what I did, but now absolutely nothing works. The 'ready' message won't show in the console. It might have to do with the 'keep_alive' file I added in.
So I was going about my day, trying to figure out what the problem is with this snippet of code, until I realized 'Hey, I could try to ask Stack Overflow'!
For context, whenever I run the bot and type in a command (i.e. '!rank'), the bot doesn't seem to recognize the command. The console is just empty of red words, unless I use a nonexisting command. This is the console after I used three commands: '!rank', '!leaderboard', and '!yeet', which purposefully doesn't exist.
In case you're too lazy to open the image, the console goes:
Ignoring exception in command None:
discord.ext.commands.errors.CommandNotFound: Command "yeet" is not found
Here's the code:
from keep_alive import keep_alive
from discord.ext import commands
import discord
import os
import levelsys
cogs = [levelsys]
client = commands.Bot(command_prefix="!", intents = discord.Intents.all())
token = os.environ.get("DISCORD_BOT_SECRET")
client.run(token)
keep_alive()
token = os.environ.get("DISCORD_BOT_SECRET")
client.run(token)
for i in range(len(cogs)):
cogs[i].setup(client)
import discord
from discord.ext import commands
from pymongo import MongoClient
general = [806613968684318720]
level = ["Sperm Whale", "Artillery General", "Commander", "Supreme General",]
levelnum = [1,5,10,15]
cluster = MongoClient("mongodb+srv://[Username]:[Password]#kingdom-kun.lffd9.mongodb.net/Kingdom-kun?retryWrites=true&w=majority")
client = discord.Client
leveling = cluster["discord"]["levelling"]
class levelsys(commands.Cog):
def _init_(self, client):
self.client = client
#commands.Cog.listener()
async def on_ready(self):
print("Kingdom-kun is ready to come!")
#commands.Cog.listener()
async def on_message(self, message):
if message.channel == general:
stats = leveling.find_one({"id" : message.author.id})
if not message.author.bot:
if stats is None:
newuser = {"id": message.author.id, "xp": 100}
leveling.insert_one(newuser)
else:
xp = stats["xp"] +5
leveling.update_one({"id": message.author.id}, {"$set": {"xp"}})
lvl = 0
while True:
if xp < {(50*(lvl**2))+(50*(lvl-1))}:
break
lvl +=1
xp -= {(50*(lvl-1)**2)+(50*(lvl-1))}
if xp == 0:
await message.channel.send(f"Well done {message.author.mention}! You were promoted to **Level: {lvl}**")
for i in range(len(level)):
if lvl == levelnum[i]:
await message.author.add_roles(discord.utils.get(message.author.guild.roles, name=level[i]))
embed = discord.Embed(description=f"{message.author.mention} you have gotten role **{level[i]}**!!!")
embed.set_thumbnail(url=message.author.avatar_url)
await message.channel.send(embed=embed)
#This is rank command
#commands.command()
async def rank(self, ctx):
if ctx.channel.id == general:
stats = leveling.find_one({"id": ctx.author.id})
if stats is None:
embed = discord.Embed(description = "You haven't sent any messages, no rank!!!")
await ctx.channelsned(embed=embed)
else:
xp = stats["xp"]
lvl = 0
rank = 0
while True:
if xp < {(50*(lvl**2))+(50*(lvl-1))}:
break
lvl += 1
xp -= {(50*(lvl-1)**2)+(50*(lvl-1))}
boxes = [(xp/(200*((1/2) * lvl)))*20]
rankings = leveling.find().sort("xp",-1)
for x in rankings:
rank += 1
if stats("id") == x["id"]:
break
embed = discord.Embed(title="{}'s level stats".format(ctx.author.name))
embed.add_field(name="Name", value = ctx.author.mention, inline=True)
embed.add_field(name="XP", value = f"{(xp/(200*((1/2)* lvl)))*20}", inline=True)
embed.add_field(name="Rank", value = f"{rank}/{ctx.guild.member_count}", inline=True)
embed.add_field(name="Progress Bar[lvl]", value = boxes * ":blue_square:" * (20-boxes) * ":white_large_square:", inline=False)
embed.set_thumbnail(url=ctx.author.avatar_url)
await ctx.channel.send(embed=embed)
#This is leaderboard command
#commands.command()
async def leaderboard(self, ctx):
if (ctx.channel.id == general):
rankings = leveling.find().sort("xp",-1)
i=1
embed = discord.Embed(title = "Rankings:")
for x in rankings:
try:
temp = ctx.guild.get_member(x["id"])
tempxp = x["xp"]
embed.add_field(name=f"(i): {temp.name}", value=f"Total XP: {tempxp}", inline=False)
i == 1
except:
pass
if i == 11:
break
await ctx.channel.send(embed=embed)
def setup(client):
client.add_cog(levelsys(client))
(This is the keep_alive file I added on that somehow screwed everything up)
from flask import Flask
from threading import Thread
app = Flask('')
#app.route('/')
def home():
return "OwO mode pog?"
def run():
app.run(host='0.0.0.0',port=8080)
def keep_alive():
t = Thread(target=run)
t.start()
I've tried a lot of things - changing brackets to parentheses then back again, retyping the entire thing... again, and more, yet nothing changes. If anyone could answer this conundrum, I'd be very thankful.
Anyway, have a nice day!

TypeError: on_message() missing 1 required positional argument: 'message'

Hello I tried to make a bot with Discord.py and I tried implementing this to my code but I get the error in the title. I don't know a lot of Python yet and I'm very new so I don't know what may cause this error. Any help would be great, thanks!
import discord
import os
import requests
import json
import random
from keep_alive import keep_alive
import asyncio
client = discord.Client()
basura = ["rezero"]
verdad = [
"es una mierda",
"no debería existir",
"VIVA K-ON",
]
def get_quote():
response = requests.get("https://zenquotes.io/api/random")
json_data = json.loads(response.text)
quote = json_data[0]['q'] + " - " + json_data[0]['a']
return (quote)
#client.event
async def on_ready():
print ('We logged in as {0.user}'.format(client))
#client.event
async def on_message(self,message):
if message.author.id == self.user.id:
return
if message.content.startswith('Hola'):
await message.channel.send('Sup nerd')
if message.content.startswith('Inspirame'):
quote = get_quote()
await message.channel.send(quote)
if any(word in message.content for word in basura):
await message.channel.send(random.choice(verdad))
if message.content.startswith('^Guess'):
await message.channel.send('Adivina un numero del 1 al 10')
def is_correct(m):
return message.content.author == message.author and m.content.isdigit()
answer = random.randint(1,10)
try:
guess = await self.wait_for('message',check=is_correct,timeout=5.0)
except asyncio.TimeoutError:
return await message.channel.send('Se acabó el tiempo, la respuesta era {}.'.format(answer))
if int(guess.content) == answer:
await message.channel.send('Acertaste')
else:
await message.channel.send('Fallaste, la respuesta era {}.'.format(answer))
keep_alive()
client.run(os.getenv('TOKEN'))
Giving the full error log and the exact code run is good practice here.
This error indicates that the 'on_message' function was not given its 'message' argument. In this case, I would presume that you forgot to delete the 'self' argument when extracting this method from an object to make a stand-alone function out of it.

cooldown for on_message in discord.py

I have made a Leveling system but i can't figure out to make a cooldown in on_message
i want to add a BucketType.member cooldown and as im using MondoDB for database so i can't afford to store the last time they send message instead im looking for a cooldown for on_message which works similar to commands cooldown so it can automatically take any action
This is the code so far
#commands.Cog.listener()
async def on_message(self , message):
if message.channel.id in talk_channels:
stats = leveling.find_one({"id":message.author.id})
if not message.author.bot:
if stats is None:
new_user = {"id" : message.author.id, "xp" : 0}
leveling.insert_one(new_user)
else:
xp = stats["xp"] + 5
leveling.update_one({"id" : message.author.id}, {"$set" : {"xp" : xp}})
lvl = 0
while True:
if xp < ((50*(lvl**2))+(50*lvl)):
break
lvl += 1
xp -= ((50*((lvl-1)**2))+(50*(lvl-1)))
if xp == 0:
await message.channel.send(f"Congo you leveled up {message.author.mention} to **level: {lvl}**")
for i in range(len(level_role)):
if lvl == levelnum[i]:
await message.author.add_roles(discord.utils.get(message.author.guild.roles, name=level_role[i]))
embed = discord.Embed(title="LEVEL UP", description=f"You have reached a mile stone of {lvl} and has got role **{level_role[i]}**", color=0x00ffff)
embed.set_thumbnail(url=message.author.avatar_url)
await message.channel.send(embed=embed)
You should use CooldownMapping.from_cooldown to add cooldowns to the on_message event, example:
import typing
import discord
from discord.ext import commands
class SomeCog(commands.Cog):
def __init__(self, bot):
self.bot = bot
self._cd = commands.CooldownMapping.from_cooldown(1, 6.0, commands.BucketType.member) # Change accordingly
# rate, per, BucketType
def get_ratelimit(self, message: discord.Message) -> typing.Optional[int]:
"""Returns the ratelimit left"""
bucket = self._cd.get_bucket(message)
return bucket.update_rate_limit()
#commands.Cog.listener()
async def on_message(self, message):
if "check something":
# Getting the ratelimit left
ratelimit = self.get_ratelimit(message)
if ratelimit is None:
# The user is not ratelimited, you can add the XP or level up the user here
else:
# The user is ratelimited

Discord Bot doesnt respond to Commands

My Discord Bot doesnt respond to Commands, but it logs the User ID when someone writes something. Why is this the Case? What have i done wrong? Is there something missing in the on_message listener? The last thing i added to my Code was the Rank System which i am working on, but even when i comment it out, the Bot still doesnt respond to commands like +macarena. Here is the Code:
import os
import discord
from dotenv import load_dotenv
from discord.ext import commands
from user import User
############## Init Variables #############
load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')
GUILD = os.getenv('DISCORD_GUILD')
DATA = os.getcwd() + '\\data\\'
bot = commands.Bot(command_prefix='+')
bot.remove_command('help')
rank_list = []
############## Main Code #############
#bot.event
async def on_ready():
for guild in bot.guilds:
if guild.name == GUILD:
break
print(
f'{bot.user} is connected to the following guild:\n'
f'{guild.name}(id: {guild.id})'
)
if(os.path.isfile(DATA + 'database.txt')):
print('Database File for Rank System exists and is ready for processing!')
else:
print('Database File doesnt exist and will be created....')
create_file()
print('File is created and ready for use!')
#bot.event
async def on_message(message):
#rank_system(message)
pass
#bot.command(name='help')
async def help_command(ctx):
embed = discord.Embed(
title = "Bot Commands",
description = "Hier werden alle Commands von diesem Bot aufgelistet. Alle nachfolgenden Commands müssen mit dem Präfix '+' aufgerufen werden.",
color = discord.Color.blue()
)
embed.add_field(name="Algorithmen", value="Lexikon", inline=True)
embed.add_field(name="Datenstrukturen", value="Lexikon", inline=True)
embed.add_field(name="macarena", value="Fun Commands", inline=True)
await ctx.send(embed=embed)
#Rank System
def rank_system(message):
author = str(message.author)
userid = str(message.author.id)
time = str(message.created_at)
channel = str(message.channel)
user = search_user(userid)
if user == None:
rank_list.append(User(author,userid,time,channel))
else:
user.add_xp()
print(userid)
#bot.command(name='rank')
async def get_rank(message):
print("I am Here")
id = str(message.author.id)
user = search_user(id)
response = f"You are Rank {user.get_rank()} and you have {user.get_xp()}."
await message.channel.send(response)
#Lexikon Commands
#bot.command(name='Algorithmen')
async def algo_command(message):
response = "Es gibt viele verschiedene Algorithmen hier eine kurze Auflistung von den bekanntesten:\n\n- Bubble Sort\n- Quick Sort\n- Merge Sort"
await message.channel.send(response)
#bot.command(name='Datenstrukturen')
async def datenstrukturen_command(message):
response = "Es gibt viele verschiedene Datenstrukturen hier eine kurze Auflistung von den bekanntesten:\n\n- Stack\n- Queue\n- List"
await message.channel.send(response)
#Vote Commands
#Fun Commands
#bot.command(name='macarena')
async def makarena_command(message):
print("Funktioniert")
response = "Hast du ernsthaft so viel Langeweile, dass du diesen Command ausprobierst....Schäm dich ;)"
await message.channel.send(response)
#Sound Board
#Helper Class
def create_file():
open(os.path.join(DATA, "database.txt"), "x")
def read_file():
pass
def write_file(text):
pass
def search_user(id):
for x in rank_list:
print("Loop User %s",x.get_userID())
if x.get_userID() == id:
return x
return None
bot.run(TOKEN)
Thanks for the Help in advance :) I am really confused and cant figure out what i am doing wrong
You need to use process_commands() at the end of on_message events to make other commands work. Read more
#bot.event
async def on_message(message):
#some code if you want, if you want to pass then don't make on_message event
await bot.process_commands(message)
Try and change your command names like this
#bot.command()
async def macarena(message):
#code
It will run when using {prefix}macarena

Function to print 4x4 emote grid in a discord chat

New python-enthusiast here.
I am currently making a discord bot that responds with 16 pictures in a 4x4-grid when a specific user types in the chat:
XXXX
XXXX
XXXX
XXXX
This is my current code:
import discord
from secrets import TOKEN
from emotes import *
# user IDs
bonvang_ID = "417010736988946444"
djursing_ID = "124806046568022016"
jonathan_ID = "151788707760832512"
alex_ID = "151745760935936001"
snuffles_ID = "221360712222507009"
# bot = commands.Bot(command_prefix='!')
client = discord.Client()
# prints message in terminal when bot is ready
#client.event
async def on_ready():
print(f"Logged in as {client.user}")
# #client.event
# async def on_member_join(member):
# await message.channel.send(f"""Welcome to the server {member}!\n
# I'm just a simple bot made by Mr.Nofox.\n
# If you want to know more about the commands, ask him or try your luck with the others! :)""")
def member_amount():
# create a variable that contains all the servers
active_servers = client.servers
# create a variable to store amount of members per server
sum = 0
# loop through the servers, get all members and add them up, this includes bots
for s in active_servers:
sum += len(s.members)
return sum
def picture_grid():
return (f"{pic01} {pic02} {pic03} {pic04}\n{pic05} {pic06} {pic07} {pic08}\n{pic09} {pic10} {pic11} {pic12}\n{pic13} {pic14} {pic15} {pic16}\n)
#client.event
async def on_message(message):
# print(f"{message.channel}: {message.author}: \"{message.content}\"")
guild = client.get_all_members()
if "!count()" == message.content:
await client.send_message(message.channel, f"```py\nTotal members: {member_amount()}```")
elif "!report()" == message.content:
online = 0
idle = 0
offline = 0
for member in guild:
if str(member.status) == "online":
online += 1
if str(member.status) == "offline":
offline += 1
if str(member.status) == "idle" or str(member.status) == "dnd":
idle += 1
await client.send_message(message.channel, f"```Online: {online}\nIdle/busy.dnd: {idle}\nOffline: {offline}```")
#TODO: Make a neat function for the pictures in message that responds with 4x4 image in chat when a given user types
if (message.author.id == alex_ID or message.author.id == snuffles_ID):
await client.send_message(message.channel, "DET ER MIN SØN!")
await client.send_message(message.channel, picture_grid())
# add bot-token found on website
client.run(TOKEN)
All the emotes are in a file called "emotes.py" which I import.
Each emote is a string-code, example:
pic01 = '<:1_:543049824644235265>'
The line I am using to get this to work atm. is:
await client.send_message(message.channel, f"{pic01} {pic02} {pic03} {pic04}\n{pic05} {pic06} {pic07} {pic08}\n{pic09} {pic10} {pic11} {pic12}\n{pic13} {pic14} {pic15} {pic16}\n")
This is awful coding practice and therefore I want to make a function that returns:
f"{pic01} {pic02} {pic03} {pic04}\n{pic05} {pic06} {pic07} {pic08}\n{pic09} {pic10} {pic11} {pic12}\n{pic13} {pic14} {pic15} {pic16}\n"
My initial thought was something like:
def picture_grid():
return (f"{pic01} {pic02} {pic03} {pic04}\n{pic05} {pic06} {pic07} {pic08}\n{pic09} {pic10} {pic11} {pic12}\n{pic13} {pic14} {pic15} {pic16}\n")
This does the trick and converts the first code to:
await client.send_message(message.channel, picture_grid())
But merely moves the bad code to another place.. I am currently stuck by what should be a simple task.
Any ideas?

Categories