Skip to content

Commit 696789d

Browse files
committed
Add 'deleter/' from commit '677cfe10a7158d761873d1ed4c4ced7a94708c06'
git-subtree-dir: deleter git-subtree-mainline: c6cfb31 git-subtree-split: 677cfe1
2 parents c6cfb31 + 677cfe1 commit 696789d

File tree

3 files changed

+197
-0
lines changed

3 files changed

+197
-0
lines changed

deleter/__init__.py

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from .deleter import Deleter
2+
3+
__red_end_user_data_statement__ = (
4+
"This cog does not persistently store data or metadata about users."
5+
)
6+
7+
8+
def setup(bot):
9+
cog = Deleter(bot)
10+
bot.add_cog(cog)

deleter/deleter.py

+177
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
import asyncio
2+
import time
3+
from collections import defaultdict
4+
from copy import deepcopy as dc
5+
6+
import discord
7+
from redbot.core import Config, checks, commands
8+
from redbot.core.utils import AsyncIter
9+
from redbot.core.utils.chat_formatting import humanize_list
10+
11+
12+
class Deleter(commands.Cog):
13+
"""Set channels for their messages to be auto-deleted after a specified amount of time.
14+
15+
WARNING: This cog has potential API abuse AND SHOULD BE USED CAREFULLY! If you see any issues arise due to this, please report to Neuro Assassin or bot owner ASAP!"""
16+
17+
def __init__(self, bot):
18+
self.bot = bot
19+
self.lock = asyncio.Lock()
20+
self.conf = Config.get_conf(self, identifier=473541068378341376)
21+
default_channel = {"wait": 0, "messages": {}}
22+
self.conf.register_channel(**default_channel)
23+
self.task = self.bot.loop.create_task(self.background_task())
24+
25+
def cog_unload(self):
26+
self.task.cancel()
27+
28+
async def red_delete_data_for_user(self, **kwargs):
29+
"""This cog does not store user data"""
30+
return
31+
32+
async def background_task(self):
33+
await self.bot.wait_until_ready()
34+
while True:
35+
async with self.lock:
36+
cs = await self.conf.all_channels()
37+
async for channel, data in AsyncIter(cs.items()):
38+
if int(data["wait"]) == 0:
39+
continue
40+
c = self.bot.get_channel(int(channel))
41+
if not c:
42+
continue
43+
old = dc(data)
44+
ms = dc(data["messages"])
45+
async for message, wait in AsyncIter(ms.items()):
46+
if int(wait) <= time.time():
47+
try:
48+
m = await c.fetch_message(int(message))
49+
await m.delete()
50+
except (discord.NotFound, discord.Forbidden):
51+
pass
52+
del data["messages"][str(message)]
53+
if old != data:
54+
await self.conf.channel(c).messages.set(data["messages"])
55+
await asyncio.sleep(10)
56+
57+
@commands.Cog.listener()
58+
async def on_message(self, message):
59+
async with self.lock:
60+
c = await self.conf.channel(message.channel).all()
61+
if int(c["wait"]) == 0:
62+
return
63+
c["messages"][str(message.id)] = time.time() + int(c["wait"])
64+
await self.conf.channel(message.channel).messages.set(c["messages"])
65+
66+
@commands.group()
67+
@commands.guild_only()
68+
@checks.mod_or_permissions(manage_messages=True)
69+
async def deleter(self, ctx):
70+
"""Group command for commands dealing with auto-timed deletion.
71+
72+
To see what channels are currently being tracked, use this command with no subcommands passed."""
73+
if ctx.invoked_subcommand is None:
74+
async with self.lock:
75+
channels = await self.conf.all_channels()
76+
sending = ""
77+
for c, data in channels.items():
78+
c = self.bot.get_channel(int(c))
79+
if c is None:
80+
continue
81+
if c.guild.id == ctx.guild.id and int(data["wait"]) != 0:
82+
sending += f"{c.mention}: {data['wait']} seconds\n"
83+
if sending:
84+
await ctx.send(sending)
85+
else:
86+
await ctx.send(
87+
f"No channels are currently being tracked. Add one by using `{ctx.prefix}deleter channel`."
88+
)
89+
90+
@deleter.command()
91+
async def channel(self, ctx, channel: discord.TextChannel, wait):
92+
"""Set the amount of time after a message sent in the specified channel is supposed to be deleted.
93+
94+
There may be about an approximate 10 second difference between the wait and the actual time the message is deleted, due to rate limiting and cooldowns.
95+
96+
Wait times must be greater than or equal to 5 seconds, or 0 to disable auto-timed deletion. If you would like to use time specifications other than seconds, suffix the wait argument with one below:
97+
98+
s => seconds (ex. 5s => 5 seconds)
99+
m => minutes (ex. 5m => 5 minutes)
100+
h => hours (ex. 5h => 5 hours)
101+
d => days (ex. 5d => 5 days)
102+
w => weeks (ex. 5w => 5 weeks"""
103+
if wait != "0":
104+
ttype = None
105+
wait = wait.lower()
106+
wt = wait[:-1]
107+
og = wait[:-1]
108+
if not wt.isdigit():
109+
return await ctx.send(
110+
"Invalid amount of time. There is a non-number in your `wait` argument, not including the time type."
111+
)
112+
wt = int(wt)
113+
if wait.endswith("s"):
114+
ttype = "second"
115+
elif wait.endswith("m"):
116+
ttype = "minute"
117+
wt *= 60
118+
elif wait.endswith("h"):
119+
ttype = "hour"
120+
wt *= 3600
121+
elif wait.endswith("d"):
122+
ttype = "day"
123+
wt *= 86400
124+
elif wait.endswith("w"):
125+
ttype = "week"
126+
wt *= 604800
127+
if not ttype:
128+
return await ctx.send("Invalid time unit. Please use S, M, H, D or W.")
129+
else:
130+
wt = 0
131+
if wt < 5 and wt != 0:
132+
return await ctx.send("Wait times must be greater than or equal to 5 seconds.")
133+
if not channel.permissions_for(ctx.guild.me).manage_messages:
134+
return await ctx.send("I do not have permission to delete messages in that channel.")
135+
if not channel.permissions_for(ctx.author).manage_messages:
136+
return await ctx.send("You do not have permission to delete messages in that channel.")
137+
await self.conf.channel(channel).wait.set(str(wt))
138+
if wt:
139+
await ctx.send(
140+
f"Messages in {channel.mention} will now be deleted after {og} {ttype}{'s' if og != '1' else ''}."
141+
)
142+
else:
143+
await ctx.send("Messages will not be auto-deleted after a specific amount of time.")
144+
145+
@deleter.command()
146+
async def remove(self, ctx, channel: discord.TextChannel, *messages: str):
147+
"""Remove messages in the specified channel from the auto-timed deletion.
148+
149+
Helpful for announcements that you want to stay in the channel.
150+
The messages to be removed must be the IDs of the messages you wish to remove."""
151+
failed = []
152+
success = []
153+
msgs = await self.conf.channel(channel).messages()
154+
for m in messages:
155+
if not m in msgs:
156+
failed.append(m)
157+
continue
158+
del msgs[m]
159+
success.append(m)
160+
if not failed:
161+
failed = [None]
162+
if not success:
163+
success = [None]
164+
await self.conf.channel(channel).messages.set(msgs)
165+
await ctx.send(
166+
f"Messages successfully removed: {humanize_list(success)}\nMessages that failed to be removed: {humanize_list(failed)}"
167+
)
168+
169+
@deleter.command()
170+
async def wipe(self, ctx, channel: discord.TextChannel = None):
171+
"""Removes all messages in the specified channel from the auto-timed deleter.
172+
173+
Leave blank to do it for the current channel."""
174+
if not channel:
175+
channel = ctx.channel
176+
await self.conf.channel(channel).messages.set({})
177+
await ctx.tick()

deleter/info.json

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"author" : ["Neuro Assassin"],
3+
"install_msg" : "Thank you for downloading this cog.",
4+
"name" : "deleter",
5+
"short" : "Allows for the auto-deletion of messages in a channel after a specified wait time.",
6+
"description" : "Allows moderators to make messages be auto-deleted after a certain amount of time in a certain channel. WARNING: This cog has potential API abuse AND SHOULD BE USED CAREFULLY! If you see any issues arise due to this, please report to Neuro Assassin or bot owner ASAP!",
7+
"tags" : ["tools"],
8+
"requirements" : [],
9+
"hidden" : false
10+
}

0 commit comments

Comments
 (0)