Title mostly says it, i have tried various ways, i tried making a variable = 1 and appen every message in a list, then after 10 seconds say that list = [], I got help from the pyhton discord server but it didn't work at the end, then i saw on the docs that there is way to delete messages after a certain date but I don't know how to set it to 10 seconds ago so I'm asking if anyone has any idea on how to do it, my code:
#commands.cooldown(rate=1,per=25,type=commands.BucketType.user)
async def king_crimson(ctx):
kingcrimson = discord.utils.get(ctx.guild.roles, id=817441099173199923)
if kingcrimson in ctx.author.roles:
kc_list = []
kc_ability = []
await ctx.channel.purge(limit=1)
kc_embed = discord.Embed(title="King Crimson activated!", colour=discord.Colour(0xb90d0d))
await ctx.author.send(embed=kc_embed)
kc_ability = 1
await asyncio.sleep(10)
kc_ability = 0
kc_embed2 = discord.Embed(title="Time has skipped!", colour=discord.Colour(0xb90d0d))
await ctx.author.send(embed=kc_embed2)
await ctx.channel.purge(after=10)
basically when the command is triggered it will wait 10 seconds and then delete every message in those 10 seconds
When the command is called, store the current time as a datetime object:
import datetime
start_time = datetime.datetime.now()
await asyncio.sleep(10)
now = datetime.datetime.now()
await ctx.channel.purge(before=now, after=start_time, bulk=True)
You should also specify bulk=True so all the messages are deleted at once. You may also want to set a check so that the bots messages aren't deleted. You can find more information about the purge command here.
Related
I have a command called "work". This command has 3 parts, list, apply and regular work. When user runs -work list, available jobs are being listed, I don't want any cooldown for this part. -work apply changes the job of the user, and -work just generates random number. So, I want it like when user runs -work apply and change their job, a 1-day cooldown must be applied. And when user just passes -work I want a 1-hour cooldown. I thought of something like different parts of the command would return different strings, such as work_apply and work_work, and use that information to apply different cooldown lengths. But that isn't possible since I can't apply any cooldown without having the output from the command, and to have some output I must run the command. So I can't apply any cooldown without running it.
I dont really know how your command handler works so i will give you an idea.
you can try making a map and pushing the message author and the time they ran the command. once you done this, the next time the same person runs the code under the time limit, set it so that the command handler looks for the member in the map and if they find it, they check when they last ran the command and if its under the time limit, it returns the function
again i dont know how your command handler works but here is how i did it
PS. If your entire command is in 1 file then the code im gonna show wont work. you should try to edit some parts of the code to make it work to ur liking
// command handler file
const cooldowns = new Map();
let name = command.name;
if (!cooldowns.has(name)) {
cooldowns.set(name, new Discord.Collection());
}
if (!message.member.roles.cache.has('ROLE_ID')) { // role that bypass cooldown
const current_time = Date.now();
const time_stamps = cooldowns.get(name);
const cooldown_amount = (command.cooldown) * 1000;
if (time_stamps.has(message.author.id)) {
const expiration_time = time_stamps.get(message.author.id) + cooldown_amount;
if (current_time < expiration_time) {
message.reply({
content: `Please wait until the cooldown has ended`
});
return;
}
}
time_stamps.set(message.author.id, current_time);
setTimeout(() => time_stamps.delete(message.author.id), cooldown_amount);
}
// command file
module.exports = {
name: 'commandname',
cooldown: 15 // this has to be in seconds | you can type '0' if there r no cooldowns
async execute(YOUR PARAMETERS) {
// command code
}
}
I want to create a member count that excludes all bots.
I've talked to a friend that told me the code looks to be correct. But it only gives me a count of 0. Perhaps you have better eyes than him!
module.exports = async(client) => {
const guild = client.guilds.cache.get('912706237806829598');
setInterval(() => {
const memberCount = guild.members.cache.filter(member => !member.user.bot).size;
const channel = guild.channels.cache.get('959556115383861298');
channel.setName(`╭👥・Members: ${memberCount.toLocaleString()}`);
console.log('Updating Member Count');
console.log(memberCount);
}, 5000);
}
Thanks.
Tried my code and expect a value representing the amount of humans on my server, but only got 0.
There are two potential problems with your code. First, you're not fetching the member collection and are instead interacting with the cache; if I remember correctly the cache usually only shows you online members and not offline ones. Second, the dreaded issue of rate limits.
The first issue is an easy fix. You just need to fetch the members instead of using the cache before all of your setInterval code:
setInterval(async () => {
const memberCount = (await guild.members.fetch()).filter(member => !member.user.bot).size;
const channel = guild.channels.cache.get('959556115383861298');
channel.setName(`╭👥・Members: ${memberCount.toLocaleString()}`);
console.log('Updating Member Count');
console.log(memberCount);
}, 5000);
That was probably causing the issue you were having. However, there's an additional problem here, one you will run into if you use this code. Rate limits. The normal rate limit for most actions in the Discord API is, if I remember correctly, 10,000 requests per 10 mins. However, the rate limit for changing the name of a channel is just 2 requests per 10 mins (last I checked; I don't know if they've increased this limit since last year). Your code is changing the name of a channel every 5 seconds. In just 10-15 seconds, you'll surpass the rate limit.
I have created channels that keep track of server stats for my bots in the past as well, and ran into this issue when I was doing so. Luckily, I brewed up a way to bypass the rate limit issue back when I was creating my own stats system. Though changing channel names has an incredibly low rate limit, fully creating channels has the normal rate limit of 10,000 requests per 10 mins. Therefore, instead of changing the channel name directly, you could instead: a) clone the channel; b) change the clone's name while creating it; c) set the clone's position in the channel list to the same position as the actual channel; d) delete the original channel. The cloned channel will keep all of the perms, settings, etc of the original. This all assumes, of course, that the original channel isn't a text channel with important messages or such inside, as those messages would all disappear with this method. I used voice channels for my system.
Here's how this bypass could look:
setInterval(async () => {
const memberCount = (await guild.members.fetch()).filter(member => !member.user.bot).size;
const channel = guild.channels.cache.get('959556115383861298');
const pos = channel.position;
const clone = await channel.clone({
name: `╭👥・Members: ${memberCount.toLocaleString()}`
});
await clone.setPosition(pos);
console.log('Updating Member Count');
console.log(memberCount);
await channel.delete();
}, 5000);
With this approach, rate limits are no longer an issue. Note that this can still be further improved, however. For example, inside the interval you could check if the member count has changed from the previous count, and only modify the channel name if and only if the count has changed. The entire approach potentially could be changed as well; perhaps you could use guildMemberAdd and guildMemberRemove events to track when the member count increases or decreases, and only modify the name when one of those happens (and only if the member being added/removed is not a bot). But whether to add either of those optional potential improvements is up to you.
Note: Please try this code out on a test channel before using it on the actual channel you are using, just to be safe.
If you wanted to get to all members including the bot you can use memberCount
const totalCount = guild.memberCount
If you wanted to get only the members size
const memberCount = guild.members.cache.filter(member => !member.user.bot).size;
And if you only wanted to get the bot size
const botCount = guild.members.cache.filter(member => member.user.bot).size;
Full code:
const guild = client.guilds.cache.get('912706237806829598')
const memberCount = guild.members.cache.filter(member => !member.user.bot).size;
const botCount = guild.members.cache.filter(member => member.user.bot).size;
const totalCount = guild.memberCount
console.log(memberCount, botCount, totalCount)
#slash.slash(name='spam', description='I will spam your content for times!', options=optionsspam, guild_ids=[847769978308526090])
async def spam(ctx, text: str, times: int="15"):
if bool(times):
Times = 15
else:
Times = times
for i in range(int(Times)):
await ctx.send(text)
await asyncio.sleep(.7)
And the result is:
It keeps replying to the first message that the bot sent. I don’t want the bot to reply. I want it to just send a normal message. How?
An interaction (slash-command) will always require a direct response towards the user. If you do not use ctx.send(str), the interaction will fail.
You've got 2 options to make it seem, like you are not responding to the slash command
Hide the response
You can post a hidden answer ctx.send('ok', hidden=True) and then send the intented message into the channel ctx.channel.send(str).
This will make the initial 'ok' only visible for the invoking users and all other members of the server will neither see the request, nor the first response.
Delete the response
Your second option is to automatically delete the answer after a very short period (ctx.send('ok', delete_after=1)), followed by a normal message into the channel ctx.channel.send(str).
Defering the response
You might need to defer your response if you can't respond within 3 seconds of the invocation. Defering an interaction (ctx.defer(hidden=True) or ctx.defer()) must be called with the same hidden attribute as your future ctx.send().
If you want to hide your respons ctx.send('ok', hidden=True), you need to defer in the same state ctx.defer(hidden=True).
You could get the channel and send message to the channel directly. However, you then must use something like ctx.defer() so that the interaction doesn't get displayed as failed.
#slash.slash(name='spam', description='I will spam your content for times!', options=optionsspam, guild_ids=[847769978308526090])
async def spam(ctx, text: str, times: int="15"):
channel = ctx.channel
if bool(times):
Times = 15
else:
Times = times
for i in range(int(Times)):
if channel != None:
await channel.send(text)
await asyncio.sleep(.7)
await ctx.send("Done")
I've been trying to get this command to check for all the messages sent by the user in the whole server for ages. I came up with a command that checks for the messages sent by a user in 1 channel only.
#client.command(aliases=["m"])
async def messages(ctx, user: discord.Member):
channel = ctx.message.channel
counter = 0
async for message in channel.history():
if message.author == user:
counter += 1
Note that no matter how you do this, if you're using the ENTIRE server history, it will take some time for the bot to go through it all. With that being known, if this is something you still wish to proceed with here is a solution.
#client.command(aliases=["m"])
async def messages(ctx, user: discord.Member):
counter = 0
for channel in guild.channels:
if isinstance(channel, discord.TextChannel):
async for message in channel.history(limit=None):
if message.author.id == user.id:
counter += 1
Also note I'm comparing IDs instead of the member object itself, this is because that object can change, this simply prevents that.
So... To give you a bit of context, I need to tell you what I have done. I have created a discord bot for moderation (mellobot.net) and I need help with a command. I would like to put an -uptime command for the actual bot itself to display the time in DD HH MM, but have no idea what the command line would look like. (I want something like NightBots !uptime that twitch users use for twitch streams) Are there any discord.py nerds that would help me with this predicament?
Store the time your program started, then, do some math. The on_ready() event can and will fire multiple times during the uptime of a bot and bad things usually happen if you do anything more than print a message inside it.
from datetime import datetime
bot = commands.Bot(command_prefix='>')
bot.launch_time = datetime.utcnow()
#bot.command()
async def uptime(ctx):
delta_uptime = datetime.utcnow() - bot.launch_time
hours, remainder = divmod(int(delta_uptime.total_seconds()), 3600)
minutes, seconds = divmod(remainder, 60)
days, hours = divmod(hours, 24)
await ctx.send(f"{days}d, {hours}h, {minutes}m")
I'm not sure but maybe you can use datetime module. When the bot is on_ready, you can take the date, and make a !uptime command like this:
#client.event
async def on_ready():
global startdate
startdate = datetime.now()
#client.command()
async def uptime(ctx):
now = datetime.now()
uptime = startdate - now
uptime = uptime.strftime('%d/%h/%M')# I don't remember the date's well, might be the lowercases are false.
await ctx.send(f'Uptime: {uptime}')
This is the latest workign command for discord.py re-write
#commands.command()
async def uptime(self, ctx):
delta_uptime = datetime.datetime.utcnow() - self.bot.launch_time
hours, remainder = divmod(int(delta_uptime.total_seconds()), 3600)
minutes, seconds = divmod(remainder, 60)
days, hours = divmod(hours, 24)
e = discord.Embed(title=f"I've been up for {days}d, {hours}h, {minutes}m, {seconds}s,", color=discord.Color.green())
await ctx.send(embed=e)```