Skip to content

Commit e3daf07

Browse files
authored
Merge pull request #6 from multitheftauto/tblock
Add duration (by default) to tblock command
2 parents 1cf5cb4 + 4d9d86f commit e3daf07

File tree

2 files changed

+110
-8
lines changed

2 files changed

+110
-8
lines changed

forward/converters.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import logging
2+
import re
3+
from typing import Union, Dict
4+
from datetime import timedelta
5+
6+
from discord.ext.commands.converter import Converter
7+
from redbot.core import commands
8+
from redbot.core import i18n
9+
10+
log = logging.getLogger("red.cogs.forward")
11+
12+
# the following regex is slightly modified from Red
13+
# it's changed to be slightly more strict on matching with finditer
14+
# this is to prevent "empty" matches when parsing the full reason
15+
# This is also designed more to allow time interval at the beginning or the end of the mute
16+
# to account for those times when you think of adding time *after* already typing out the reason
17+
# https://github.com/Cog-Creators/Red-DiscordBot/blob/V3/develop/redbot/core/commands/converter.py#L55
18+
TIME_RE_STRING = r"|".join(
19+
[
20+
r"((?P<weeks>\d+?)\s?(weeks?|w))",
21+
r"((?P<days>\d+?)\s?(days?|d))",
22+
r"((?P<hours>\d+?)\s?(hours?|hrs|hr?))",
23+
r"((?P<minutes>\d+?)\s?(minutes?|mins?|m(?!o)))", # prevent matching "months"
24+
r"((?P<seconds>\d+?)\s?(seconds?|secs?|s))",
25+
]
26+
)
27+
TIME_RE = re.compile(TIME_RE_STRING, re.I)
28+
TIME_SPLIT = re.compile(r"t(?:ime)?=")
29+
30+
_ = i18n.Translator("Forward", __file__)
31+
32+
def str_to_timedelta(
33+
duration: str
34+
) -> Dict[str, Union[timedelta, str, None]]:
35+
time_split = TIME_SPLIT.split(duration)
36+
result: Dict[str, Union[timedelta, str, None]] = {}
37+
if time_split:
38+
maybe_time = time_split[-1]
39+
else:
40+
maybe_time = duration
41+
42+
time_data = {}
43+
for time in TIME_RE.finditer(maybe_time):
44+
duration = duration.replace(time[0], "")
45+
for k, v in time.groupdict().items():
46+
if v:
47+
time_data[k] = int(v)
48+
if time_data:
49+
try:
50+
result["duration"] = timedelta(**time_data)
51+
except OverflowError:
52+
raise commands.BadArgument(
53+
_("The time provided is too long; use a more reasonable time.")
54+
)
55+
result["reason"] = duration.strip()
56+
return result

forward/forward.py

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,19 @@
22
# from googletrans import Translator
33
import discord
44
import uuid
5+
from .converters import str_to_timedelta
6+
from datetime import datetime, timezone, timedelta
7+
import asyncio
8+
import logging
9+
10+
from typing import Optional, Dict
511

612
# trans = Translator()
713

14+
log = logging.getLogger("red.cogs.forward")
815

916
class Forward(commands.Cog):
10-
"""Forward messages sent to the bot to the bot owner or in a specified channel."""
17+
"""Forward messages sent to the bot to the bot owner or a specified channel."""
1118

1219
__version__ = "1.2.5"
1320

@@ -27,6 +34,30 @@ def __init__(self, bot):
2734

2835
self.welcome = {}
2936

37+
self._unblock_task = asyncio.create_task(self._handle_automatic_unblock())
38+
39+
def cog_unload(self):
40+
self._unblock_task.cancel()
41+
42+
async def _handle_automatic_unblock(self):
43+
"""This is the core task creator and loop
44+
for automatic unblocks
45+
"""
46+
await self.bot.wait_until_red_ready()
47+
while True:
48+
try:
49+
await self._process_expired_blocks()
50+
except Exception:
51+
log.error("Error checking bot unblocks", exc_info=True)
52+
await asyncio.sleep(60) # 60 seconds
53+
54+
async def _process_expired_blocks(self):
55+
async with self.config.blocked() as blocked:
56+
for userid in list(blocked.keys()):
57+
until = blocked[userid]
58+
if datetime.now(timezone.utc).timestamp() > until:
59+
del blocked[userid]
60+
3061
async def _destination(self, msg: str = None, embed: discord.Embed = None):
3162
await self.bot.wait_until_ready()
3263
channel = await self.config.destination()
@@ -240,28 +271,43 @@ async def tpm(self, ctx, language, user: discord.Member, *, message: str):
240271
@commands.command()
241272
@commands.guild_only()
242273
@checks.guildowner()
243-
async def tblock(self, ctx, user: discord.Member):
244-
"""Blocks a member from sending dm
274+
async def tblock(self, ctx, user: discord.Member, time: Optional[str] = "5d"):
275+
"""Blocks a member from sending DMs to the bot
245276
"""
246277
async with self.config.blocked() as blocked:
247278
userid = str(user.id)
248279
if userid not in blocked:
249-
blocked[userid] = True
250-
await ctx.maybe_send_embed("Blocked <@{}> from send messages to the bot.".format(userid))
280+
duration = str_to_timedelta(duration=time).get("duration")
281+
duration = duration if type(duration) is timedelta else str_to_timedelta(duration="5d").get("duration")
282+
blocked[userid] = (datetime.now(timezone.utc) + duration).timestamp() # until
283+
await ctx.maybe_send_embed("Blocked <@{id}> from sending messages to the bot until <t:{until}>.".format(id=userid, until=int(blocked[userid])))
251284
else:
252-
await ctx.maybe_send_embed("This user is already blocked.")
285+
await ctx.maybe_send_embed("This user is already blocked until <t:{}>.".format(int(blocked[userid])))
253286

254287
@commands.command()
255288
@commands.guild_only()
256289
@checks.guildowner()
257290
async def tunblock(self, ctx, user: discord.Member):
258-
"""Blocks a member from sending dm
291+
"""Unblocks a member from sending dms
259292
"""
260293
async with self.config.blocked() as blocked:
261294
userid = str(user.id)
262295
if userid in blocked:
263296
del blocked[userid]
264-
await ctx.maybe_send_embed("Unblocked <@{}> from sending messages to the bot.".format(userid))
297+
await ctx.maybe_send_embed("Unblocked <@{}> sending messages to the bot.".format(userid))
298+
else:
299+
await ctx.maybe_send_embed("This user is not blocked.")
300+
301+
@commands.command()
302+
@commands.guild_only()
303+
@checks.guildowner()
304+
async def tcheckblock(self, ctx, user: discord.Member):
305+
"""Checks if a member is blocked from sending dms to the bot
306+
"""
307+
async with self.config.blocked() as blocked:
308+
userid = str(user.id)
309+
if userid in blocked:
310+
await ctx.maybe_send_embed("User <@{id}> is blocked until <t:{until}>.".format(id=userid, until=int(blocked[userid])))
265311
else:
266312
await ctx.maybe_send_embed("This user is not blocked.")
267313

0 commit comments

Comments
 (0)