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
Related
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.
im working on a discord bot that responds to keywords with some text and an image, as you can imagine this would create a lot of opportunities to use the bot to spam and I would like to create a system in the code that allows the program to stop accepting all inputs once spamming is detected, I managed to create a system to detect the spam using time stamps but so far it does nothing, as I cannot figure out the code for what I need to do.
this is my code so far:
import os
import discord
import datetime
import time
from keep_on import keep_on
bot_token = os.environ['TOKEN']
client = discord.Client()
#client.event
async def on_ready():
print('{0.user} is online'.format(client))
print('###########################################')
enabled = True
time_storage = int(datetime.datetime.utcnow().timestamp())
#client.event
async def on_message(message):
global enabled
global time_storage
sentWord = message.content
CSentWord = sentWord.upper()
if message.content == "!start":
enabled = True
await message.channel.send("Having Trouble?")
await message.channel.send(file=discord.File('Having trouble.png'))
elif message.content == "!stop":
enabled = False
await message.channel.send("Ok Ill Stop.")
await message.channel.send(file=discord.File('Joey will stop.png'))
elif enabled == True:
if message.author == client.user:
return
if "SORRY" in CSentWord:
time.sleep(0.5)
time_delay = int(datetime.datetime.utcnow().timestamp())
time_difference = time_delay - time_storage
print('time since last stored:',time_storage)
print('time now:',time_delay)
print('time difference:',time_difference)
print('###########################################')
if time_difference < 5:
await message.channel.send("You are moving too fast")
await message.channel.send(file=discord.File('Bruh what.png'))
time.sleep(2)
return
await message.channel.send("'We're Very Sorry' - Joey Tribbiani")
await message.channel.send(file=discord.File('Joey Is Sorry.png'))
time_storage = int(datetime.datetime.utcnow().timestamp())
keep_on()
client.run(os.getenv('TOKEN'))
You can add cooldowns to commands using
#commands.cooldown(1, 10, commands.BucketType.user)
For example here the user can use a command once every 10 seconds
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!
I'd like to know how I could make this script send the result (won or lost) on the specific user's direct message, here is a simple example of this:
from discord.ext import commands
import discord
import os
from random import *
client = commands.Bot(command_prefix = '-')
#client.event
async def on_ready():
print('Bot Is Ready')
#client.command() #The command in order to execute the script first
async def dm(ctx):
rand_num = (randint(1, 3))
win_num = 1
if rand_num == win_num:
print("number was:", rand_num)
print("won")
#client.event
async def on_win():
dmessage.send.user("You won!") #Send the won result message via direct message on discord automatically
elif rand_num != win_num:
print("number was:", rand_num)
print("lost")
#client.event
async def on_lost():
dmessage.send.user("You lost") #Send the lost result message via direct message on discord automatically
client.run('TOKEN')
If you want to send prive message(direct message) you can use member.create_dm and you can't use something like on_win or on_lost.
#client.command()
async def dm(ctx):
rand_num = (randint(1, 3))
win_num = 1
pm_channel = await ctx.author.create_dm()
if win_num == rand_num:
await pm_channel.send("You won!")
else:
await pm_channel.send("You lost")
So in this code, member when member writes prefix + dm, it'll check the rand_num and win_num then it'll send the result to the user.
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?