add black code formatter gitaction, update all cogs to follow format

This commit is contained in:
brandons209 2020-01-27 15:04:50 -05:00
parent 7e4b0c18b8
commit f5891ffb90
15 changed files with 632 additions and 527 deletions

13
.github/workflows/black-checker.yml vendored Normal file
View file

@ -0,0 +1,13 @@
name: black-checker
on: [pull_request, push]
jobs:
black:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Black Code Formatter
uses: lgeiger/black-action@v1.0.1
with:
args: "--line-length 120 --target-version py38 --check ."

View file

@ -1,5 +1,6 @@
from .activitylog import ActivityLogger
async def setup(bot):
n = ActivityLogger(bot)
await n.initialize()

View file

@ -12,13 +12,9 @@ import os
import asyncio
import glob
__version__ = '3.0.0'
__version__ = "3.0.0"
TIMESTAMP_FORMAT = '%Y-%m-%d %X' # YYYY-MM-DD HH:MM:SS
#PATH_LIST = ['data', 'activitylogger']
#JSON = os.path.join(*PATH_LIST, "settings.json")
#NAMES_JSON = os.path.join(*PATH_LIST, "past_names.json")
EDIT_TIMEDELTA = timedelta(seconds=3)
TIMESTAMP_FORMAT = "%Y-%m-%d %X" # YYYY-MM-DD HH:MM:SS
# 0 is Message object
AUTHOR_TEMPLATE = "@{0.author.name}#{0.author.discriminator}(id:{0.author.id})"
@ -42,6 +38,7 @@ DELETE_AUDIT_TEMPLATE = "@{0.name}#{0.discriminator}(id:{0.id}) deleted message
MAX_LINES = 50000
def get_all_names(guild_files, user):
names = [str(user)]
for log in guild_files:
@ -68,19 +65,21 @@ def get_all_names(guild_files, user):
names.append(username)
return set(names)
def format_list(*items, join='and', delim=', '):
def format_list(*items, join="and", delim=", "):
if len(items) > 1:
return (' %s ' % join).join((delim.join(items[:-1]), items[-1]))
return (" %s " % join).join((delim.join(items[:-1]), items[-1]))
elif items:
return items[0]
else:
return ''
return ""
class LogHandle:
"""basic wrapper for logfile handles, used to keep track of stale handles"""
def __init__(self, path, time=None, mode='a', buf=1):
self.handle = open(path, mode, buf, errors='backslashreplace')
def __init__(self, path, time=None, mode="a", buf=1):
self.handle = open(path, mode, buf, errors="backslashreplace")
self.lock = asyncio.Lock()
if time:
@ -111,34 +110,13 @@ class ActivityLogger(commands.Cog):
self.bot = bot
self.config = Config.get_conf(self, identifier=9584736583, force_registration=True)
default_global = {
"attrs": {
"attachments" : False,
"default" : False,
"direct" : False,
"everything" : False,
"rotation" : "m"
}
}
self.default_guild = {
"all_s": False,
"voice": False,
"events": False,
"prefixes": []
}
self.default_channel = {
"enabled": False
}
default_user = {
"past_names": []
"attrs": {"attachments": False, "default": False, "direct": False, "everything": False, "rotation": "m"}
}
self.default_guild = {"all_s": False, "voice": False, "events": False, "prefixes": []}
self.default_channel = {"enabled": False}
default_user = {"past_names": []}
default_member = {
"stats": {
"total_msg": 0,
"bot_cmd": 0,
"avg_len": 0.0,
"vc_time_sec": 0.0,
"last_vc_time": None
}
"stats": {"total_msg": 0, "bot_cmd": 0, "avg_len": 0.0, "vc_time_sec": 0.0, "last_vc_time": None}
}
self.config.register_global(**default_global)
self.config.register_guild(**self.default_guild)
@ -203,9 +181,7 @@ class ActivityLogger(commands.Cog):
since_joined = "?"
user_joined = "Unknown"
user_created = user.created_at.strftime("%b %d, %Y %H:%M UTC")
member_number = (sorted(guild.members,
key=lambda m: m.joined_at or ctx.message.created_at)
.index(user) + 1)
member_number = sorted(guild.members, key=lambda m: m.joined_at or ctx.message.created_at).index(user) + 1
created_on = "{}\n({} days ago)".format(user_created, since_created)
joined_on = "{}\n({} days ago)".format(user_joined, since_joined)
@ -243,8 +219,7 @@ class ActivityLogger(commands.Cog):
names = pagify(names, page_length=1000)
for name in names:
data.add_field(name="Also known as:", value=name, inline=False)
data.set_footer(text="Member #{} | User ID:{}"
"".format(member_number, user.id))
data.set_footer(text="Member #{} | User ID:{}" "".format(member_number, user.id))
name = str(user)
name = " ~ ".join((name, user.nick)) if user.nick else name
@ -274,7 +249,7 @@ class ActivityLogger(commands.Cog):
stats = await self.config.member(user).stats()
async with self.config.user(user).past_names() as past_names:
if not past_names:
guild_files = sorted(glob.glob(os.path.join(PATH, 'usernames', "*.log")))
guild_files = sorted(glob.glob(os.path.join(PATH, "usernames", "*.log")))
names = get_all_names(guild_files, user)
else:
names = past_names
@ -306,7 +281,9 @@ class ActivityLogger(commands.Cog):
msg += "Average message length: `{:.2f}` words\n".format(avg_len / (num_messages - num_bot_commands))
except ZeroDivisionError:
msg += "Average message length: `{:.2f}` words\n".format(0)
msg += "Time spent in voice chat: `{:.0f}` {}.\n".format(minutes if minutes <= 120 else hours, "minutes" if minutes <= 120 else "hours")
msg += "Time spent in voice chat: `{:.0f}` {}.\n".format(
minutes if minutes <= 120 else hours, "minutes" if minutes <= 120 else "hours"
)
msg += f"Bans: `{bans}`, Kicks: `{kicks}`, Mutes: `{mutes}`"
if len(names) > 1:
return msg, format_list(*names)
@ -351,12 +328,12 @@ class ActivityLogger(commands.Cog):
messages = [message for message in messages if str(user.id) in message]
message_chunks = [
messages[i * MAX_LINES:(i + 1) * MAX_LINES] for i in range((len(messages) + MAX_LINES - 1) // MAX_LINES)
messages[i * MAX_LINES : (i + 1) * MAX_LINES] for i in range((len(messages) + MAX_LINES - 1) // MAX_LINES)
]
for msgs in message_chunks:
temp_file = os.path.join(log_path, datetime.utcnow().strftime("%Y%m%d%X").replace(":", "") + ".txt")
with open(temp_file, encoding='utf-8', mode="w") as f:
with open(temp_file, encoding="utf-8", mode="w") as f:
f.writelines(msgs)
await ctx.channel.send(file=discord.File(temp_file))
@ -436,12 +413,12 @@ class ActivityLogger(commands.Cog):
"""
try:
dates = date.split(";")
dates = [dates[0].strip(), dates[1].strip()] # only use 2 dates
dates = [dates[0].strip(), dates[1].strip()] # only use 2 dates
start, end = [parse_time(date).replace(tzinfo=None) for date in dates]
# order doesnt matter, so check which date is older than the other
# end time should be the newest date since logs are processed in reverse
if start < end: # start is before end date
start, end = end, start # swap order
if start < end: # start is before end date
start, end = end, start # swap order
except:
await ctx.send("Invalid dates! Try again.")
return
@ -530,12 +507,12 @@ class ActivityLogger(commands.Cog):
"""
try:
dates = date.split(";")
dates = [dates[0].strip(), dates[1].strip()] # only use 2 dates
dates = [dates[0].strip(), dates[1].strip()] # only use 2 dates
start, end = [parse_time(date).replace(tzinfo=None) for date in dates]
# order doesnt matter, so check which date is older than the other
# end time should be the newest date since logs are processed in reverse
if start < end: # start is before end date
start, end = end, start # swap order
if start < end: # start is before end date
start, end = end, start # swap order
except:
await ctx.send("Invalid dates! Try again.")
return
@ -624,12 +601,12 @@ class ActivityLogger(commands.Cog):
"""
try:
dates = date.split(";")
dates = [dates[0].strip(), dates[1].strip()] # only use 2 dates
dates = [dates[0].strip(), dates[1].strip()] # only use 2 dates
start, end = [parse_time(date).replace(tzinfo=None) for date in dates]
# order doesnt matter, so check which date is older than the other
# end time should be the newest date since logs are processed in reverse
if start < end: # start is before end date
start, end = end, start # swap order
if start < end: # start is before end date
start, end = end, start # swap order
except:
await ctx.send("Invalid dates! Try again.")
return
@ -719,12 +696,12 @@ class ActivityLogger(commands.Cog):
"""
try:
dates = date.split(";")
dates = [dates[0].strip(), dates[1].strip()] # only use 2 dates
dates = [dates[0].strip(), dates[1].strip()] # only use 2 dates
start, end = [parse_time(date).replace(tzinfo=None) for date in dates]
# order doesnt matter, so check which date is older than the other
# end time should be the newest date since logs are processed in reverse
if start < end: # start is before end date
start, end = end, start # swap order
if start < end: # start is before end date
start, end = end, start # swap order
except:
await ctx.send("Invalid dates! Try again.")
return
@ -746,7 +723,7 @@ class ActivityLogger(commands.Cog):
"""
pass
@logset.command(name='everything', aliases=['global'])
@logset.command(name="everything", aliases=["global"])
async def set_everything(self, ctx, on_off: bool = None):
"""
Global override for all logging
@ -762,7 +739,7 @@ class ActivityLogger(commands.Cog):
else:
await ctx.send("Global logging override is disabled.")
@logset.command(name='default')
@logset.command(name="default")
async def set_default(self, ctx, on_off: bool = None):
"""
Sets whether logging is on or off where unset
@ -780,7 +757,7 @@ class ActivityLogger(commands.Cog):
else:
await ctx.send("Logging is disabled by default.")
@logset.command(name='dm')
@logset.command(name="dm")
async def set_direct(self, ctx, on_off: bool = None):
"""
Log direct messages?
@ -797,7 +774,7 @@ class ActivityLogger(commands.Cog):
else:
await ctx.send("Logging of direct messages is disabled.")
@logset.command(name='attachments')
@logset.command(name="attachments")
async def set_attachments(self, ctx, on_off: bool = None):
"""
Download message attachments?
@ -813,7 +790,7 @@ class ActivityLogger(commands.Cog):
else:
await ctx.send("Downloading of attachments is disabled.")
@logset.command(name='channel')
@logset.command(name="channel")
@commands.guild_only()
async def set_channel(self, ctx, on_off: bool, channel: discord.TextChannel = None):
"""
@ -830,11 +807,11 @@ class ActivityLogger(commands.Cog):
await self.config.channel(channel).enabled.set(on_off)
if on_off:
await ctx.send('Logging enabled for %s' % channel.mention)
await ctx.send("Logging enabled for %s" % channel.mention)
else:
await ctx.send('Logging disabled for %s' % channel.mention)
await ctx.send("Logging disabled for %s" % channel.mention)
@logset.command(name='server')
@logset.command(name="server")
@commands.guild_only()
async def set_guild(self, ctx, on_off: bool):
"""
@ -846,11 +823,11 @@ class ActivityLogger(commands.Cog):
await self.config.guild(guild).all_s.set(on_off)
if on_off:
await ctx.send('Logging enabled for %s' % guild)
await ctx.send("Logging enabled for %s" % guild)
else:
await ctx.send('Logging disabled for %s' % guild)
await ctx.send("Logging disabled for %s" % guild)
@logset.command(name='voice')
@logset.command(name="voice")
@commands.guild_only()
async def set_voice(self, ctx, on_off: bool):
"""
@ -862,11 +839,11 @@ class ActivityLogger(commands.Cog):
await self.config.guild(guild).voice.set(on_off)
if on_off:
await ctx.send('Voice event logging enabled for %s' % guild)
await ctx.send("Voice event logging enabled for %s" % guild)
else:
await ctx.send('Voice event logging disabled for %s' % guild)
await ctx.send("Voice event logging disabled for %s" % guild)
@logset.command(name='events')
@logset.command(name="events")
@commands.guild_only()
async def set_events(self, ctx, on_off: bool):
"""
@ -878,9 +855,9 @@ class ActivityLogger(commands.Cog):
await self.config.guild(guild).events.set(on_off)
if on_off:
await ctx.send('Logging enabled for guild events in %s' % guild)
await ctx.send("Logging enabled for guild events in %s" % guild)
else:
await ctx.send('Logging disabled for guild events in %s' % guild)
await ctx.send("Logging disabled for guild events in %s" % guild)
@logset.command(name="prefixes")
@commands.guild_only()
@ -895,16 +872,16 @@ class ActivityLogger(commands.Cog):
await self.config.guild(ctx.guild).prefixes.set([ctx.clean_prefix])
self.cache[ctx.guild.id]["prefixes"] = [ctx.clean_prefix]
return
await ctx.send("Current Prefixes: " + format_list(*curr, delim=', '))
await ctx.send("Current Prefixes: " + format_list(*curr, delim=", "))
return
prefixes = [p for p in prefixes if p != ' ']
prefixes = [p for p in prefixes if p != " "]
await self.config.guild(ctx.guild).prefixes.set(prefixes)
self.cache[ctx.guild.id]["prefixes"] = prefixes
prefixes = [f"`{p}`" for p in prefixes]
await ctx.send("Prefixes set to: " + format_list(*prefixes, delim=', '))
await ctx.send("Prefixes set to: " + format_list(*prefixes, delim=", "))
@logset.command(name='rotation')
@logset.command(name="rotation")
async def set_rotation(self, ctx, freq: str = None):
"""
Show, disable, or set the log rotation period
@ -921,12 +898,12 @@ class ActivityLogger(commands.Cog):
- y: one log file per year (starts 00:00Z Jan 1)
"""
if freq:
freq = freq.lower().strip('"\'` ')
freq = freq.lower().strip("\"'` ")
if freq in ('d', 'w', 'm', 'y', 'none', 'disable'):
adj = 'now'
if freq in ("d", "w", "m", "y", "none", "disable"):
adj = "now"
if freq in ('none', 'disable'):
if freq in ("none", "disable"):
freq = None
async with self.config.attrs() as attrs:
@ -937,53 +914,48 @@ class ActivityLogger(commands.Cog):
await self.bot.send_cmd_help(ctx)
return
else:
adj = 'currently'
adj = "currently"
freq = self.cache["rotation"]
if not freq:
await ctx.send("Log rotation is %s disabled." % adj)
else:
desc = {
'd' : 'daily',
'w' : 'weekly',
'm' : 'monthly',
'y' : 'yearly'
}[freq]
desc = {"d": "daily", "w": "weekly", "m": "monthly", "y": "yearly"}[freq]
await ctx.send('Log rotation period is %s %s.' % (adj, desc))
await ctx.send("Log rotation period is %s %s." % (adj, desc))
@staticmethod
def format_rotation_string(timestamp, rotation_code, filename=None):
kwargs = dict(hour=0, minute=0, second=0, microsecond=0)
if not rotation_code:
return filename or ''
return filename or ""
if rotation_code == 'y':
if rotation_code == "y":
kwargs.update(day=1, month=1)
start = timestamp.replace(**kwargs)
elif rotation_code == 'm':
elif rotation_code == "m":
kwargs.update(day=1)
start = timestamp.replace(**kwargs)
elif rotation_code == 'w':
elif rotation_code == "w":
start = timestamp - timedelta(days=timestamp.weekday())
spec = start.strftime('%Y%m%d')
spec = start.strftime("%Y%m%d")
if rotation_code == 'w':
spec += '--P7D'
if rotation_code == "w":
spec += "--P7D"
else:
spec += '--P1%c' % rotation_code.upper()
spec += "--P1%c" % rotation_code.upper()
if filename:
return '%s_%s' % (spec, filename)
return "%s_%s" % (spec, filename)
else:
return spec
@staticmethod
def get_voice_flags(voice_state):
flags = []
for f in ('deaf', 'mute', 'self_deaf', 'self_mute', 'self_stream', 'self_video'):
for f in ("deaf", "mute", "self_deaf", "self_mute", "self_stream", "self_video"):
if getattr(voice_state, f, None):
flags.append(f)
@ -992,11 +964,13 @@ class ActivityLogger(commands.Cog):
@staticmethod
def format_overwrite(target, channel, before, after, user=None):
if user:
target_str = 'Channel overwrites by @{1.name}#{1.discriminator}(id:{1.id}): {0.name} ({0.id}): '.format(channel, user)
target_str = "Channel overwrites by @{1.name}#{1.discriminator}(id:{1.id}): {0.name} ({0.id}): ".format(
channel, user
)
else:
target_str = 'Channel overwrites: {0.name} ({0.id}): '.format(channel)
target_str += 'role' if isinstance(target, discord.Role) else 'member'
target_str += ' {0.name} ({0.id})'.format(target)
target_str = "Channel overwrites: {0.name} ({0.id}): ".format(channel)
target_str += "role" if isinstance(target, discord.Role) else "member"
target_str += " {0.name} ({0.id})".format(target)
if before:
bpair = [x.value for x in before.pair()]
@ -1005,14 +979,14 @@ class ActivityLogger(commands.Cog):
apair = [x.value for x in after.pair()]
if before and after:
fmt = ' updated to values %i, %i (was %i, %i)'
fmt = " updated to values %i, %i (was %i, %i)"
return target_str + fmt % tuple(apair + bpair)
elif after:
return target_str + ' added with values %i, %i' % tuple(apair)
return target_str + " added with values %i, %i" % tuple(apair)
elif before:
return target_str + ' removed (was %i, %i)' % tuple(bpair)
return target_str + " removed (was %i, %i)" % tuple(bpair)
def gethandle(self, path, mode='a'):
def gethandle(self, path, mode="a"):
"""Manages logfile handles, culling stale ones and creating folders"""
if path in self.handles:
if os.path.exists(path):
@ -1047,34 +1021,34 @@ class ActivityLogger(commands.Cog):
return handle
def should_log(self, location):
if self.cache.get('everything', False):
if self.cache.get("everything", False):
return True
default = self.cache.get('default', False)
default = self.cache.get("default", False)
if type(location) is discord.Guild:
loc = self.cache[location.id]
return loc.get('all_s', False) or loc.get('events', default)
return loc.get("all_s", False) or loc.get("events", default)
elif type(location) is discord.TextChannel:
loc = self.cache[location.guild.id]
opts = [loc.get('all_s', False), self.cache[location.id].get("enabled", default)]
opts = [loc.get("all_s", False), self.cache[location.id].get("enabled", default)]
return any(opts)
elif type(location) is discord.VoiceChannel:
loc = self.cache[location.guild.id]
opts = [loc.get('all_s', False), loc.get('voice', False)]
opts = [loc.get("all_s", False), loc.get("voice", False)]
return any(opts)
elif isinstance(location, discord.abc.PrivateChannel):
return self.cache.get('direct', default)
return self.cache.get("direct", default)
else: # can't log other types
return False
def should_download(self, msg):
return self.should_log(msg.channel) and self.cache.get('attachments', False)
return self.should_log(msg.channel) and self.cache.get("attachments", False)
def process_attachment(self, message, a):
aid = a.id
@ -1086,23 +1060,23 @@ class ActivityLogger(commands.Cog):
if type(channel) is discord.TextChannel:
guildid = channel.guild.id
elif isinstance(channel, discord.abc.PrivateChannel):
guildid = 'direct'
guildid = "direct"
path = os.path.join(path, str(guildid), str(channel.id) + '_attachments')
filename = str(aid) + '_' + aname
path = os.path.join(path, str(guildid), str(channel.id) + "_attachments")
filename = str(aid) + "_" + aname
if len(filename) > 255:
target_len = 255 - len(aid) - 4
part_a = target_len // 2
part_b = target_len - part_a
filename = aid + '_' + aname[:part_a] + '...' + aname[-part_b:]
filename = aid + "_" + aname[:part_a] + "..." + aname[-part_b:]
truncated = True
else:
truncated = False
return aid, url, path, filename, truncated
async def log(self, location, text, timestamp=None, force=False, subfolder=None, mode='a'):
async def log(self, location, text, timestamp=None, force=False, subfolder=None, mode="a"):
if not timestamp:
timestamp = datetime.utcnow()
@ -1111,24 +1085,24 @@ class ActivityLogger(commands.Cog):
path = []
entry = [timestamp.strftime(TIMESTAMP_FORMAT)]
rotation = self.cache['rotation']
rotation = self.cache["rotation"]
if type(location) is discord.Guild:
path += [str(location.id), 'guild.log']
path += [str(location.id), "guild.log"]
elif type(location) is discord.TextChannel or type(location) is discord.VoiceChannel:
guildid = str(location.guild.id)
entry.append('#' + location.name)
path += [guildid, str(location.id) + '.log']
entry.append("#" + location.name)
path += [guildid, str(location.id) + ".log"]
elif isinstance(location, discord.abc.PrivateChannel):
path += ['direct', str(location.id) + '.log']
path += ["direct", str(location.id) + ".log"]
elif type(location) is discord.User or type(location) is discord.Member:
path += ['usernames', 'usernames.log']
path += ["usernames", "usernames.log"]
else:
return
if subfolder:
path.insert(-1, str(subfolder))
text = text.replace('\n', '\\n')
text = text.replace("\n", "\\n")
entry.append(text)
if rotation:
@ -1136,7 +1110,7 @@ class ActivityLogger(commands.Cog):
fname = os.path.join(PATH, *path)
handle = self.gethandle(fname, mode=mode)
await handle.write(' '.join(entry) + '\n')
await handle.write(" ".join(entry) + "\n")
async def message_handler(self, message, *args, force_attachments=None, **kwargs):
dl_attachment = self.should_download(message)
@ -1149,15 +1123,17 @@ class ActivityLogger(commands.Cog):
for a in message.attachments:
attachments += [self.process_attachment(message, a)]
entry = DOWNLOAD_TEMPLATE.format(message, [a[3] + ' (filename truncated)' if a[4] else a[3] for a in attachments])
entry = DOWNLOAD_TEMPLATE.format(
message, [a[3] + " (filename truncated)" if a[4] else a[3] for a in attachments]
)
elif message.attachments:
urls = ','.join(a.url for a in message.attachments)
urls = ",".join(a.url for a in message.attachments)
entry = ATTACHMENT_TEMPLATE.format(message, urls)
else:
entry = MESSAGE_TEMPLATE.format(message)
if message.author.id != self.bot.user.id: # don't calculate bot stats
if message.author.id != self.bot.user.id: # don't calculate bot stats
async with self.config.member(message.author).stats() as stats:
stats["total_msg"] += 1
if len(message.content) > 0 and message.content[0] in self.cache[message.guild.id]["prefixes"]:
@ -1199,10 +1175,12 @@ class ActivityLogger(commands.Cog):
async for entry in message.guild.audit_logs(limit=1):
# target is user who had message deleted
if entry.action is discord.AuditLogAction.message_delete:
if entry.target.id == message.author.id and \
entry.extra.channel.id == message.channel.id and \
entry.created_at.timestamp() > time.time() - 3000 and \
entry.extra.count >= 1:
if (
entry.target.id == message.author.id
and entry.extra.channel.id == message.channel.id
and entry.created_at.timestamp() > time.time() - 3000
and entry.extra.count >= 1
):
entry_s = DELETE_AUDIT_TEMPLATE.format(entry.user, message, message.author, timestamp)
break
except:
@ -1215,12 +1193,12 @@ class ActivityLogger(commands.Cog):
@commands.Cog.listener()
async def on_guild_join(self, guild):
entry = 'this bot joined the guild'
entry = "this bot joined the guild"
await self.log(guild, entry)
@commands.Cog.listener()
async def on_guild_remove(self, guild):
entry = 'this bot left the guild'
entry = "this bot left the guild"
await self.log(guild, entry)
@commands.Cog.listener()
@ -1230,39 +1208,49 @@ class ActivityLogger(commands.Cog):
try:
async for entry in after.audit_logs(limit=1):
if entry.action is discord.AuditLogAction.guild_update:
user = entry.user
user = entry.user
except:
pass
if before.owner != after.owner:
if user:
entries.append('guild owner changed by @{2.name}#{2.discriminator}(id:{2.id}), from {0.owner} (id {0.owner.id}) to {1.owner} (id {1.owner.id})')
entries.append(
"guild owner changed by @{2.name}#{2.discriminator}(id:{2.id}), from {0.owner} (id {0.owner.id}) to {1.owner} (id {1.owner.id})"
)
else:
entries.append('guild owner changed from {0.owner} (id {0.owner.id}) to {1.owner} (id {1.owner.id})')
entries.append("guild owner changed from {0.owner} (id {0.owner.id}) to {1.owner} (id {1.owner.id})")
if before.region != after.region:
if user:
entries.append('guild region changed by @{2.name}#{2.discriminator}(id:{2.id}), from {0.region} to {1.region}')
entries.append(
"guild region changed by @{2.name}#{2.discriminator}(id:{2.id}), from {0.region} to {1.region}"
)
else:
entries.append('guild region changed from {0.region} to {1.region}')
entries.append("guild region changed from {0.region} to {1.region}")
if before.name != after.name:
if user:
entries.append('guild name changed by @{2.name}#{2.discriminator}(id:{2.id}), from "{0.name}" to "{1.name}"')
entries.append(
'guild name changed by @{2.name}#{2.discriminator}(id:{2.id}), from "{0.name}" to "{1.name}"'
)
else:
entries.append('guild name changed from "{0.name}" to "{1.name}"')
if before.icon_url != after.icon_url:
if user:
entries.append('guild icon changed by @{2.name}#{2.discriminator}(id:{2.id}), from {0.icon_url} to {1.icon_url}')
entries.append(
"guild icon changed by @{2.name}#{2.discriminator}(id:{2.id}), from {0.icon_url} to {1.icon_url}"
)
else:
entries.append('guild icon changed from {0.icon_url} to {1.icon_url}')
entries.append("guild icon changed from {0.icon_url} to {1.icon_url}")
if before.splash != after.splash:
if user:
entries.append('guild splash changed by @{2.name}#{2.discriminator}(id:{2.id}), from {0.splash} to {1.splash}')
entries.append(
"guild splash changed by @{2.name}#{2.discriminator}(id:{2.id}), from {0.splash} to {1.splash}"
)
else:
entries.append('guild splash changed from {0.splash} to {1.splash}')
entries.append("guild splash changed from {0.splash} to {1.splash}")
for e in entries:
if user:
@ -1326,45 +1314,61 @@ class ActivityLogger(commands.Cog):
if before.color != after.color:
if user:
entries.append('Role color by @{2.name}#{2.discriminator}(id:{2.id}): "{0}" (id {0.id}) changed from {0.color} to {1.color}')
entries.append(
'Role color by @{2.name}#{2.discriminator}(id:{2.id}): "{0}" (id {0.id}) changed from {0.color} to {1.color}'
)
else:
entries.append('Role color: "{0}" (id {0.id}) changed from {0.color} to {1.color}')
if before.mentionable != after.mentionable:
if after.mentionable:
if user:
entries.append('Role mentionable by @{2.name}#{2.discriminator}(id:{2.id}): "{1.name}" (id {1.id}) is now mentionable')
entries.append(
'Role mentionable by @{2.name}#{2.discriminator}(id:{2.id}): "{1.name}" (id {1.id}) is now mentionable'
)
else:
entries.append('Role mentionable: "{1.name}" (id {1.id}) is now mentionable')
else:
if user:
entries.append('Role mentionable by @{2.name}#{2.discriminator}(id:{2.id}): "{1.name}" (id {1.id}) is no longer mentionable')
entries.append(
'Role mentionable by @{2.name}#{2.discriminator}(id:{2.id}): "{1.name}" (id {1.id}) is no longer mentionable'
)
else:
entries.append('Role mentionable: "{1.name}" (id {1.id}) is no longer mentionable')
if before.hoist != after.hoist:
if after.hoist:
if user:
entries.append('Role hoist by @{2.name}#{2.discriminator}(id:{2.id}): "{1.name}" (id {1.id}) is now shown seperately')
entries.append(
'Role hoist by @{2.name}#{2.discriminator}(id:{2.id}): "{1.name}" (id {1.id}) is now shown seperately'
)
else:
entries.append('Role hoist: "{1.name}" (id {1.id}) is now shown seperately')
else:
if user:
entries.append('Role hoist by @{2.name}#{2.discriminator}(id:{2.id}): "{1.name}" (id {1.id}) is no longer shown seperately')
entries.append(
'Role hoist by @{2.name}#{2.discriminator}(id:{2.id}): "{1.name}" (id {1.id}) is no longer shown seperately'
)
else:
entries.append('Role hoist: "{1.name}" (id {1.id}) is no longer shown seperately')
if before.permissions != after.permissions:
if user:
entries.append('Role permissions by @{2.name}#{2.discriminator}(id:{2.id}): "{1.name}" (id {1.id}) changed from {0.permissions.value} '
'to {1.permissions.value}')
entries.append(
'Role permissions by @{2.name}#{2.discriminator}(id:{2.id}): "{1.name}" (id {1.id}) changed from {0.permissions.value} '
"to {1.permissions.value}"
)
else:
entries.append('Role permissions: "{1.name}" (id {1.id}) changed from {0.permissions.value} '
'to {1.permissions.value}')
entries.append(
'Role permissions: "{1.name}" (id {1.id}) changed from {0.permissions.value} '
"to {1.permissions.value}"
)
if before.position != after.position:
if user:
entries.append('Role position by @{2.name}#{2.discriminator}(id:{2.id}): "{0}" changed from {0.position} to {1.position}')
entries.append(
'Role position by @{2.name}#{2.discriminator}(id:{2.id}): "{0}" changed from {0.position} to {1.position}'
)
else:
entries.append('Role position: "{0}" changed from {0.position} to {1.position}')
@ -1376,7 +1380,7 @@ class ActivityLogger(commands.Cog):
@commands.Cog.listener()
async def on_member_join(self, member):
entry = 'Member join: @{0} (id {0.id})'.format(member)
entry = "Member join: @{0} (id {0.id})".format(member)
async with self.config.user(member).past_names() as past_names:
if str(member) not in past_names:
@ -1396,9 +1400,9 @@ class ActivityLogger(commands.Cog):
pass
if user:
entry = 'Member kicked by @{1.name}#{1.discriminator}(id:{1.id}): @{0} (id {0.id})'.format(member, user)
entry = "Member kicked by @{1.name}#{1.discriminator}(id:{1.id}): @{0} (id {0.id})".format(member, user)
else:
entry = 'Member leave: @{0} (id {0.id})'.format(member)
entry = "Member leave: @{0} (id {0.id})".format(member)
await self.config.member(member).clear()
await self.log(member.guild, entry)
@ -1415,9 +1419,9 @@ class ActivityLogger(commands.Cog):
pass
if user:
entry = 'Member banned by @{1.name}#{1.discriminator}(id:{1.id}): @{0} (id {0.id})'.format(member, user)
entry = "Member banned by @{1.name}#{1.discriminator}(id:{1.id}): @{0} (id {0.id})".format(member, user)
else:
entry = 'Member ban: @{0} (id {0.id})'.format(member)
entry = "Member ban: @{0} (id {0.id})".format(member)
await self.log(member.guild, entry)
@ -1433,9 +1437,9 @@ class ActivityLogger(commands.Cog):
pass
if user:
entry = 'Member unbanned by @{1.name}#{1.discriminator}(id:{1.id}): @{0} (id {0.id})'.format(member, user)
entry = "Member unbanned by @{1.name}#{1.discriminator}(id:{1.id}): @{0} (id {0.id})".format(member, user)
else:
entry = 'Member unban: @{0} (id {0.id})'.format(member)
entry = "Member unban: @{0} (id {0.id})".format(member)
await self.log(guild, entry)
@ -1445,8 +1449,10 @@ class ActivityLogger(commands.Cog):
user = None
try:
async for entry in after.guild.audit_logs(limit=1):
if entry.action is discord.AuditLogAction.member_update \
or entry.action is discord.AuditLogAction.member_role_update:
if (
entry.action is discord.AuditLogAction.member_update
or entry.action is discord.AuditLogAction.member_role_update
):
if entry.target.id == after.id:
user = entry.user
except:
@ -1454,7 +1460,9 @@ class ActivityLogger(commands.Cog):
if before.nick != after.nick:
if user:
entries.append('Member nickname changed by @{2.name}#{2.discriminator}(id:{2.id}): "@{0}" (id {0.id}) nickname change from "{0.nick}" to "{1.nick}"')
entries.append(
'Member nickname changed by @{2.name}#{2.discriminator}(id:{2.id}): "@{0}" (id {0.id}) nickname change from "{0.nick}" to "{1.nick}"'
)
else:
entries.append('Member nickname: "@{0}" (id {0.id}) changed nickname from "{0.nick}" to "{1.nick}"')
@ -1466,18 +1474,27 @@ class ActivityLogger(commands.Cog):
for r in added:
if user:
entries.append('Member role added by @{1.name}#{1.discriminator}(id:{1.id}): "{0}" (id {0.id}) role '
'was added to "@{{0}}" (id {{0.id}})'.format(r, user))
entries.append(
'Member role added by @{1.name}#{1.discriminator}(id:{1.id}): "{0}" (id {0.id}) role '
'was added to "@{{0}}" (id {{0.id}})'.format(r, user)
)
else:
entries.append('Member role add: "{0}" (id {0.id}) role '
'was added to "@{{0}}" (id {{0.id}})'.format(r))
entries.append(
'Member role add: "{0}" (id {0.id}) role ' 'was added to "@{{0}}" (id {{0.id}})'.format(r)
)
for r in removed:
if user:
entries.append('Member role removed by @{1.name}#{1.discriminator}(id:{1.id}): "{0}" (id {0.id}) role was removed from "@{{0}}" (id {{0.id}})'.format(r, user))
entries.append(
'Member role removed by @{1.name}#{1.discriminator}(id:{1.id}): "{0}" (id {0.id}) role was removed from "@{{0}}" (id {{0.id}})'.format(
r, user
)
)
else:
entries.append('Member role remove: "{0}" (id {0.id}) role '
'was removed from "@{{0}}" (id {{0.id}})'.format(r))
entries.append(
'Member role remove: "{0}" (id {0.id}) role '
'was removed from "@{{0}}" (id {{0.id}})'.format(r)
)
for e in entries:
await self.log(before.guild, e.format(before, after, user))
@ -1513,7 +1530,9 @@ class ActivityLogger(commands.Cog):
pass
if user:
entry = 'Channel created by @{1.name}#{1.discriminator}(id:{1.id}): "{0.name}" (id {0.id})'.format(channel, user)
entry = 'Channel created by @{1.name}#{1.discriminator}(id:{1.id}): "{0.name}" (id {0.id})'.format(
channel, user
)
else:
entry = 'Channel created: "{0.name}" (id {0.id})'.format(channel)
@ -1531,7 +1550,9 @@ class ActivityLogger(commands.Cog):
pass
if user:
entry = 'Channel deleted by @{1.name}#{1.discriminator}(id:{1.id}): "{0.name}" (id {0.id})'.format(channel, user)
entry = 'Channel deleted by @{1.name}#{1.discriminator}(id:{1.id}): "{0.name}" (id {0.id})'.format(
channel, user
)
else:
entry = 'Channel deleted: "{0.name}" (id {0.id})'.format(channel)
@ -1552,19 +1573,25 @@ class ActivityLogger(commands.Cog):
if before.name != after.name:
if user:
entries.append('Channel rename by @{2.name}#{2.discriminator}(id:{2.id}): "{0.name}" (id {0.id}) renamed to "{1.name}"')
entries.append(
'Channel rename by @{2.name}#{2.discriminator}(id:{2.id}): "{0.name}" (id {0.id}) renamed to "{1.name}"'
)
else:
entries.append('Channel rename: "{0.name}" (id {0.id}) renamed to "{1.name}"')
if before.topic != after.topic:
if user:
entries.append('Channel topic by @{2.name}#{2.discriminator}(id:{2.id}): "{0.name}" (id {0.id}) topic was set to "{1.topic}"')
entries.append(
'Channel topic by @{2.name}#{2.discriminator}(id:{2.id}): "{0.name}" (id {0.id}) topic was set to "{1.topic}"'
)
else:
entries.append('Channel topic: "{0.name}" (id {0.id}) topic was set to "{1.topic}"')
if before.position != after.position:
if user:
entries.append('Channel position by @{2.name}#{2.discriminator}(id:{2.id}): "{0.name}" (id {0.id}) moved from {0.position} to {1.position}')
entries.append(
'Channel position by @{2.name}#{2.discriminator}(id:{2.id}): "{0.name}" (id {0.id}) moved from {0.position} to {1.position}'
)
else:
entries.append('Channel position: "{0.name}" (id {0.id}) moved from {0.position} to {1.position}')
@ -1603,11 +1630,11 @@ class ActivityLogger(commands.Cog):
msg = "Voice channel leave: {0} (id {0.id})"
async with self.config.member(member).stats() as stats:
stats["vc_time_sec"] += (time.time() - stats["last_vc_time"])
stats["vc_time_sec"] += time.time() - stats["last_vc_time"]
stats["last_vc_time"] = None
if after.channel:
msg += ' moving to {1.channel}'
msg += " moving to {1.channel}"
await self.log(before.channel, msg.format(member, after))
@ -1618,35 +1645,35 @@ class ActivityLogger(commands.Cog):
stats["last_vc_time"] = time.time()
if before.channel:
msg += ', moved from {1.channel}'
msg += ", moved from {1.channel}"
flags = self.get_voice_flags(after)
if flags:
msg += ', flags: %s' % ','.join(flags)
msg += ", flags: %s" % ",".join(flags)
await self.log(after.channel, msg.format(member, before))
if before.deaf != after.deaf:
verb = 'deafen' if after.deaf else 'undeafen'
await self.log(before.channel, 'guild {0}: {1} (id {1.id})'.format(verb, member))
verb = "deafen" if after.deaf else "undeafen"
await self.log(before.channel, "guild {0}: {1} (id {1.id})".format(verb, member))
if before.mute != after.mute:
verb = 'mute' if after.mute else 'unmute'
await self.log(before.channel, 'guild {0}: {1} (id {1.id})'.format(verb, member))
verb = "mute" if after.mute else "unmute"
await self.log(before.channel, "guild {0}: {1} (id {1.id})".format(verb, member))
if before.self_deaf != after.self_deaf:
verb = 'deafen' if after.self_deaf else 'undeafen'
await self.log(before.channel, 'guild self-{0}: {1} (id {1.id})'.format(verb, member))
verb = "deafen" if after.self_deaf else "undeafen"
await self.log(before.channel, "guild self-{0}: {1} (id {1.id})".format(verb, member))
if before.self_mute != after.self_mute:
verb = 'mute' if after.self_mute else 'unmute'
await self.log(before.channel, 'guild self-{0}: {1} (id {1.id})'.format(verb, member))
verb = "mute" if after.self_mute else "unmute"
await self.log(before.channel, "guild self-{0}: {1} (id {1.id})".format(verb, member))
if before.self_stream != after.self_stream:
verb = 'stop-stream' if not after.self_stream else 'start-stream'
await self.log(before.channel, 'guild self-{0}: {1} (id {1.id})'.format(verb, member))
verb = "stop-stream" if not after.self_stream else "start-stream"
await self.log(before.channel, "guild self-{0}: {1} (id {1.id})".format(verb, member))
if before.self_video != after.self_video:
verb = 'start-video' if after.self_video else 'stop-video'
await self.log(before.channel, 'guild self-{0}: {1} (id {1.id})'.format(verb, member))
verb = "start-video" if after.self_video else "stop-video"
await self.log(before.channel, "guild self-{0}: {1} (id {1.id})".format(verb, member))

View file

@ -43,7 +43,6 @@ def parse_time(datetimestring: str):
return ret
def parse_time_naive(datetimestring: str):
return parser.parse(datetimestring)

View file

@ -59,9 +59,7 @@ class Admin(commands.Cog):
self.conf.register_global(serverlocked=False)
self.conf.register_guild(
announce_ignore=False,
announce_channel=None, # Integer ID
selfroles=[], # List of integer ID's
announce_ignore=False, announce_channel=None, selfroles=[], # Integer ID # List of integer ID's
)
self.__current_announcer = None
@ -114,16 +112,12 @@ class Admin(commands.Cog):
await member.add_roles(role)
except discord.Forbidden:
if not self.pass_hierarchy_check(ctx, role):
await self.complain(
ctx, T_(HIERARCHY_ISSUE), role=role, member=member, verb=_("add")
)
await self.complain(ctx, T_(HIERARCHY_ISSUE), role=role, member=member, verb=_("add"))
else:
await self.complain(ctx, T_(GENERIC_FORBIDDEN))
else:
await ctx.send(
_("I successfully added {role.name} to {member.display_name}").format(
role=role, member=member
)
_("I successfully added {role.name} to {member.display_name}").format(role=role, member=member)
)
async def _removerole(self, ctx: commands.Context, member: discord.Member, role: discord.Role):
@ -134,24 +128,18 @@ class Admin(commands.Cog):
await member.remove_roles(role)
except discord.Forbidden:
if not self.pass_hierarchy_check(ctx, role):
await self.complain(
ctx, T_(HIERARCHY_ISSUE), role=role, member=member, verb=_("remove")
)
await self.complain(ctx, T_(HIERARCHY_ISSUE), role=role, member=member, verb=_("remove"))
else:
await self.complain(ctx, T_(GENERIC_FORBIDDEN))
else:
await ctx.send(
_("I successfully removed {role.name} from {member.display_name}").format(
role=role, member=member
)
_("I successfully removed {role.name} from {member.display_name}").format(role=role, member=member)
)
@commands.command()
@commands.guild_only()
@checks.admin_or_permissions(manage_roles=True)
async def addrole(
self, ctx: commands.Context, rolename: discord.Role, *, user: MemberDefaultAuthor = None
):
async def addrole(self, ctx: commands.Context, rolename: discord.Role, *, user: MemberDefaultAuthor = None):
"""Add a role to a user.
If user is left blank it defaults to the author of the command.
@ -162,16 +150,12 @@ class Admin(commands.Cog):
# noinspection PyTypeChecker
await self._addrole(ctx, user, rolename)
else:
await self.complain(
ctx, T_(USER_HIERARCHY_ISSUE), member=user, role=rolename, verb=_("add")
)
await self.complain(ctx, T_(USER_HIERARCHY_ISSUE), member=user, role=rolename, verb=_("add"))
@commands.command()
@commands.guild_only()
@checks.admin_or_permissions(manage_roles=True)
async def removerole(
self, ctx: commands.Context, rolename: discord.Role, *, user: MemberDefaultAuthor = None
):
async def removerole(self, ctx: commands.Context, rolename: discord.Role, *, user: MemberDefaultAuthor = None):
"""Remove a role from a user.
If user is left blank it defaults to the author of the command.
@ -182,9 +166,7 @@ class Admin(commands.Cog):
# noinspection PyTypeChecker
await self._removerole(ctx, user, rolename)
else:
await self.complain(
ctx, T_(USER_HIERARCHY_ISSUE), member=user, role=rolename, verb=_("remove")
)
await self.complain(ctx, T_(USER_HIERARCHY_ISSUE), member=user, role=rolename, verb=_("remove"))
@commands.group()
@commands.guild_only()
@ -194,9 +176,7 @@ class Admin(commands.Cog):
pass
@editrole.command(name="colour", aliases=["color"])
async def editrole_colour(
self, ctx: commands.Context, role: discord.Role, value: discord.Colour
):
async def editrole_colour(self, ctx: commands.Context, role: discord.Role, value: discord.Colour):
"""Edit a role's colour.
Use double quotes if the role contains spaces.
@ -234,9 +214,7 @@ class Admin(commands.Cog):
"""
author = ctx.message.author
old_name = role.name
reason = "{}({}) changed the name of role '{}' to '{}'".format(
author.name, author.id, old_name, name
)
reason = "{}({}) changed the name of role '{}' to '{}'".format(author.name, author.id, old_name, name)
if not self.pass_user_hierarchy_check(ctx, role):
await self.complain(ctx, T_(ROLE_USER_HIERARCHY_ISSUE), role=role)
@ -285,9 +263,7 @@ class Admin(commands.Cog):
channel = ctx.channel
await self.conf.guild(ctx.guild).announce_channel.set(channel.id)
await ctx.send(
_("The announcement channel has been set to {channel.mention}").format(channel=channel)
)
await ctx.send(_("The announcement channel has been set to {channel.mention}").format(channel=channel))
@announce.command(name="ignore")
@commands.guild_only()
@ -298,15 +274,9 @@ class Admin(commands.Cog):
await self.conf.guild(ctx.guild).announce_ignore.set(not ignored)
if ignored: # Keeping original logic....
await ctx.send(
_("The server {guild.name} will receive announcements.").format(guild=ctx.guild)
)
await ctx.send(_("The server {guild.name} will receive announcements.").format(guild=ctx.guild))
else:
await ctx.send(
_("The server {guild.name} will not receive announcements.").format(
guild=ctx.guild
)
)
await ctx.send(_("The server {guild.name} will not receive announcements.").format(guild=ctx.guild))
async def _valid_selfroles(self, guild: discord.Guild) -> Tuple[discord.Role]:
"""

View file

@ -66,9 +66,7 @@ class Announcer:
try:
await channel.send(self.message)
except discord.Forbidden:
await bot_owner.send(
_("I could not announce to server: {server.id}").format(server=g)
)
await bot_owner.send(_("I could not announce to server: {server.id}").format(server=g))
await asyncio.sleep(0.5)
self.active = False

View file

@ -1,5 +1,6 @@
from .events import Events
def setup(bot):
n = Events(bot)
bot.add_cog(n)

View file

@ -11,11 +11,30 @@ import pytz
from tzlocal import get_localzone
basic_colors = [discord.Colour.blue(), discord.Colour.teal(), discord.Colour.dark_teal(), discord.Colour.green(), discord.Colour.dark_green(), discord.Colour.dark_blue(), discord.Colour.purple(), discord.Colour.dark_purple(), discord.Colour.magenta(), discord.Colour.gold(), discord.Colour.orange(), discord.Colour.red(), discord.Colour.dark_red(), discord.Colour.blurple(), discord.Colour.greyple()]
basic_colors = [
discord.Colour.blue(),
discord.Colour.teal(),
discord.Colour.dark_teal(),
discord.Colour.green(),
discord.Colour.dark_green(),
discord.Colour.dark_blue(),
discord.Colour.purple(),
discord.Colour.dark_purple(),
discord.Colour.magenta(),
discord.Colour.gold(),
discord.Colour.orange(),
discord.Colour.red(),
discord.Colour.dark_red(),
discord.Colour.blurple(),
discord.Colour.greyple(),
]
class Events(commands.Cog):
"""
Set events that track time since set events
"""
def __init__(self, bot):
super().__init__()
self.config = Config.get_conf(self, identifier=6748392754)
@ -55,18 +74,33 @@ class Events(commands.Cog):
elapsed_time = datetime.datetime.utcnow() - start_time
embed = discord.Embed(title=event_name, colour=random.choice(basic_colors))
embed.add_field(name="Event time", value=start_time.replace(tzinfo=pytz.utc).astimezone(self.timezone).strftime("%b %d, %Y, %H:%M"))
embed.add_field(
name="Event time",
value=start_time.replace(tzinfo=pytz.utc).astimezone(self.timezone).strftime("%b %d, %Y, %H:%M"),
)
day_msg = "{} day{},".format(elapsed_time.days, "s" if elapsed_time.days > 1 else "")
hour_msg = " {} hour{}".format(int(elapsed_time.seconds / 60 / 60), "s" if int(elapsed_time.seconds / 60 / 60) > 1 else "")
hour_msg = " {} hour{}".format(
int(elapsed_time.seconds / 60 / 60), "s" if int(elapsed_time.seconds / 60 / 60) > 1 else ""
)
if elapsed_time.days > 0 or int(elapsed_time.seconds / 60 / 60) > 0:
minute_msg = ", and {} minute{}".format(int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60), "s" if int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60) > 1 else "")
minute_msg = ", and {} minute{}".format(
int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60),
"s" if int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60) > 1 else "",
)
else:
minute_msg = "{} minute{}".format(int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60), "s" if int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60) > 1 else "")
msg = "{}{}{}".format(day_msg if elapsed_time.days > 0 else "", hour_msg if int(elapsed_time.seconds / 60 / 60) > 0 else "", minute_msg)
minute_msg = "{} minute{}".format(
int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60),
"s" if int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60) > 1 else "",
)
msg = "{}{}{}".format(
day_msg if elapsed_time.days > 0 else "",
hour_msg if int(elapsed_time.seconds / 60 / 60) > 0 else "",
minute_msg,
)
embed.add_field(name="Elapsed time", value=msg)
message = await channel.send(embed=embed)
async with self.config.guild(guild).events() as events:
new_event = {"start_time" : int(start_time.replace(tzinfo=pytz.utc).timestamp()), "name" : event_name}
new_event = {"start_time": int(start_time.replace(tzinfo=pytz.utc).timestamp()), "name": event_name}
events[message.id] = new_event
await ctx.send("Event added!")
@ -98,13 +132,20 @@ class Events(commands.Cog):
msg += "```"
await ctx.send(msg)
await ctx.send("Please choose which event you want to delete. (type number in chat)")
def m_check(m):
try:
return m.author.id == ctx.author.id and m.channel.id == ctx.channel.id and int(m.content) <= counter and int(m.content) >= 0
return (
m.author.id == ctx.author.id
and m.channel.id == ctx.channel.id
and int(m.content) <= counter
and int(m.content) >= 0
)
except:
return False
try:
response = await self.bot.wait_for('message', timeout=30, check=m_check)
response = await self.bot.wait_for("message", timeout=30, check=m_check)
except:
await ctx.send("Timed out, event deletion cancelled.")
return
@ -179,14 +220,35 @@ class Events(commands.Cog):
elapsed_time = datetime.datetime.utcnow() - start_time
embed = message.embeds[0]
embed.clear_fields()
embed.add_field(name="Event time", value=start_time.replace(tzinfo=pytz.utc).astimezone(self.timezone).strftime("%b %d, %Y, %H:%M"))
embed.add_field(
name="Event time",
value=start_time.replace(tzinfo=pytz.utc)
.astimezone(self.timezone)
.strftime("%b %d, %Y, %H:%M"),
)
day_msg = "{} day{},".format(elapsed_time.days, "s" if elapsed_time.days > 1 else "")
hour_msg = " {} hour{}".format(int(elapsed_time.seconds / 60 / 60), "s" if int(elapsed_time.seconds / 60 / 60) > 1 else "")
hour_msg = " {} hour{}".format(
int(elapsed_time.seconds / 60 / 60), "s" if int(elapsed_time.seconds / 60 / 60) > 1 else ""
)
if elapsed_time.days > 0 or int(elapsed_time.seconds / 60 / 60) > 0:
minute_msg = ", and {} minute{}".format(int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60), "s" if int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60) > 1 else "")
minute_msg = ", and {} minute{}".format(
int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60),
"s"
if int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60) > 1
else "",
)
else:
minute_msg = "{} minute{}".format(int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60), "s" if int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60) > 1 else "")
msg = "{}{}{}".format(day_msg if elapsed_time.days > 0 else "", hour_msg if int(elapsed_time.seconds / 60 / 60) > 0 else "", minute_msg)
minute_msg = "{} minute{}".format(
int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60),
"s"
if int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60) > 1
else "",
)
msg = "{}{}{}".format(
day_msg if elapsed_time.days > 0 else "",
hour_msg if int(elapsed_time.seconds / 60 / 60) > 0 else "",
minute_msg,
)
embed.add_field(name="Elapsed time", value=msg)
await message.edit(embed=embed)
await asyncio.sleep(30)

View file

@ -1,4 +1,5 @@
from .pony import Pony
def setup(bot):
bot.add_cog(Pony())

View file

@ -7,18 +7,14 @@ import os
import traceback
import json
class Pony(commands.Cog):
def __init__(self):
super().__init__()
self.config = Config.get_conf(self, identifier=7384662719)
default_global = {
"maxfilters":50
}
self.default_guild = {
"filters": ["-meme", "safe", "-spoiler:*", "-vulgar"],
"verbose": False
}
default_global = {"maxfilters": 50}
self.default_guild = {"filters": ["-meme", "safe", "-spoiler:*", "-vulgar"], "verbose": False}
self.config.register_guild(**self.default_guild)
self.config.register_global(**default_global)
@ -40,7 +36,7 @@ class Pony(commands.Cog):
"""
Gives a random picture of our mascot!
"""
await fetch_image(self, ctx, randomize=True, mascot=True, tags=['safe,', 'coe'])
await fetch_image(self, ctx, randomize=True, mascot=True, tags=["safe,", "coe"])
@commands.group()
@commands.guild_only()
@ -53,7 +49,7 @@ class Pony(commands.Cog):
pass
@ponyfilter.command(name="add")
async def _add_ponyfilter(self, ctx, filter_tag : str):
async def _add_ponyfilter(self, ctx, filter_tag: str):
"""Adds a tag to the server's pony filter list
Example: !ponyfilter add safe"""
@ -72,7 +68,7 @@ class Pony(commands.Cog):
await ctx.send("This server has exceeded the maximum filters ({}/{}).".format(len(filters), max_filters))
@ponyfilter.command(name="del")
async def _del_ponyfilter(self, ctx, filter_tag : str=""):
async def _del_ponyfilter(self, ctx, filter_tag: str = ""):
"""Deletes a tag from the server's pony filter list
Without arguments, reverts to the default pony filter list
@ -100,10 +96,10 @@ class Pony(commands.Cog):
guild = ctx.guild
filters = await self.config.guild(guild).filters()
if filters:
filter_list = '\n'.join(sorted(filters))
filter_list = "\n".join(sorted(filters))
target_guild = "{}'s".format(guild.name)
else:
filter_list = '\n'.join(sorted(filters["default"]))
filter_list = "\n".join(sorted(filters["default"]))
target_guild = "Default"
await ctx.send("{} pony filter list contains:```\n{}```".format(target_guild, filter_list))
@ -114,7 +110,7 @@ class Pony(commands.Cog):
pass
@ponyset.command(name="verbose")
async def _verbose_ponyset(self, ctx, toggle : str="toggle"):
async def _verbose_ponyset(self, ctx, toggle: str = "toggle"):
"""Toggles verbose mode"""
guild = ctx.guild
verbose = await self.config.guild(guild).verbose()
@ -140,7 +136,7 @@ class Pony(commands.Cog):
@ponyset.command(name="maxfilters")
@checks.is_owner()
async def _maxfilters_ponyset(self, ctx, new_max_filters : int):
async def _maxfilters_ponyset(self, ctx, new_max_filters: int):
"""Sets the global tag limit for the filter list.
Leave blank to get current max filters.
@ -178,7 +174,7 @@ class Pony(commands.Cog):
if guild is None:
continue
await self.config.guild(guild).verbose.set(json_guild_verbose['verbose'])
await self.config.guild(guild).verbose.set(json_guild_verbose["verbose"])
msg += "**{}**\n".format(guild)
if len(msg) + 100 > 2000:
await ctx.send(msg)
@ -194,7 +190,7 @@ class Pony(commands.Cog):
for json_guild_id, json_guild_filters in import_filters.items():
if json_guild_id != "default":
guild = bot.get_guild(int(json_guild_id)) # returns None if guild is not found
guild = bot.get_guild(int(json_guild_id)) # returns None if guild is not found
if guild is None:
continue
@ -204,7 +200,7 @@ class Pony(commands.Cog):
await ctx.send(msg)
msg = ""
else:
continue
continue
if msg != "":
await ctx.send(msg)
@ -213,25 +209,25 @@ class Pony(commands.Cog):
except json.decoder.JSONDecodeError:
await ctx.send("Invalid or malformed json files.")
async def fetch_image(self, ctx, randomize : bool=False, tags : list=[], mascot=False):
async def fetch_image(self, ctx, randomize: bool = False, tags: list = [], mascot=False):
guild = ctx.guild
filters = await self.config.guild(guild).filters()
verbose = await self.config.guild(guild).verbose()
#Initialize variables
artist = "unknown artist"
artists = ""
artistList = []
embedLink = ""
embedTitle = ""
imageId = ""
message = ""
output = None
rating = ""
# Initialize variables
artist = "unknown artist"
artists = ""
artistList = []
embedLink = ""
embedTitle = ""
imageId = ""
message = ""
output = None
rating = ""
ratingColor = "FFFFFF"
ratingWord = "unknown"
search = "https://derpibooru.org/search.json?q="
tagSearch = ""
ratingWord = "unknown"
search = "https://derpibooru.org/search.json?q="
tagSearch = ""
# Assign tags to URL
if tags:
@ -250,12 +246,12 @@ class Pony(commands.Cog):
# Randomize results and apply Derpibooru's "Everything" filter
if randomize:
if not tags and filters:
if filters == []:
search = "https://derpibooru.org/images/random.json?filter_id=56027"
else:
search += "&random_image=y&filter_id=56027"
if filters == []:
search = "https://derpibooru.org/images/random.json?filter_id=56027"
else:
search += "&random_image=y&filter_id=56027"
else:
search += "&random_image=y&filter_id=56027"
search += "&random_image=y&filter_id=56027"
# Inform users about image retrieving
message = await ctx.send("Fetching pony image...")
@ -263,7 +259,7 @@ class Pony(commands.Cog):
# Fetch the image or display an error
try:
async with aiohttp.ClientSession(loop=ctx.bot.loop) as session:
async with session.get(search, headers={'User-Agent': "Booru-Cogs (https://git.io/booru)"}) as r:
async with session.get(search, headers={"User-Agent": "Booru-Cogs (https://git.io/booru)"}) as r:
website = await r.json()
if randomize:
if "id" in website:

View file

@ -1,5 +1,6 @@
from .punish import Punish
async def setup(bot):
punish = Punish(bot)
await punish.initialize()

View file

@ -2,7 +2,8 @@ class Memoizer:
"""
General purpose cache for function results. Appends positional args, overlays kwargs. Both must be hashable.
"""
__slots__ = ['_cache', '_func', '_args', '_kwargs']
__slots__ = ["_cache", "_func", "_args", "_kwargs"]
def __init__(self, func, *args, **kwargs):
self._cache = {}

View file

@ -16,21 +16,22 @@ import logging
import time
import textwrap
log = logging.getLogger('red.punish')
log = logging.getLogger("red.punish")
__version__ = '3.0.0'
__version__ = "3.0.0"
PURGE_MESSAGES = 1 # for cpunish
DEFAULT_ROLE_NAME = 'Punished'
DEFAULT_ROLE_NAME = "Punished"
DEFAULT_TEXT_OVERWRITE = discord.PermissionOverwrite(send_messages=False, send_tts_messages=False, add_reactions=False)
DEFAULT_VOICE_OVERWRITE = discord.PermissionOverwrite(speak=False, connect=False)
DEFAULT_TIMEOUT_OVERWRITE = discord.PermissionOverwrite(send_messages=True, read_messages=True)
QUEUE_TIME_CUTOFF = 30
DEFAULT_TIMEOUT = '5m'
DEFAULT_CASE_MIN_LENGTH = '5m' # only create modlog cases when length is longer than this
DEFAULT_TIMEOUT = "5m"
DEFAULT_CASE_MIN_LENGTH = "5m" # only create modlog cases when length is longer than this
class Punish(commands.Cog):
"""
@ -38,6 +39,7 @@ class Punish(commands.Cog):
do other things that can be denied using discord permissions. Includes
auto-setup and more.
"""
def __init__(self, bot):
super().__init__()
@ -53,7 +55,7 @@ class Punish(commands.Cog):
"VOICE_OVERWRITE": overwrite_to_dict(DEFAULT_VOICE_OVERWRITE),
"ROLE_ID": None,
"NITRO_ID": None,
"CHANNEL_ID": None
"CHANNEL_ID": None,
}
self.config.register_guild(**default_guild)
@ -100,7 +102,7 @@ class Punish(commands.Cog):
elif user:
await self._punish_cmd_common(ctx, user, duration, reason)
@punish.command(name='cstart')
@punish.command(name="cstart")
@commands.guild_only()
@checks.mod()
async def punish_cstart(self, ctx, user: discord.Member, duration: str = None, *, reason: str = None):
@ -121,7 +123,7 @@ class Punish(commands.Cog):
except discord.errors.Forbidden:
await ctx.send("Punishment set, but I need permissions to manage messages to clean up.")
@punish.command(name='list')
@punish.command(name="list")
@commands.guild_only()
@checks.mod()
async def punish_list(self, ctx):
@ -135,7 +137,7 @@ class Punish(commands.Cog):
guild = ctx.guild
guild_id = guild.id
now = time.time()
headers = ['Member', 'Remaining', 'Moderator', 'Reason']
headers = ["Member", "Remaining", "Moderator", "Reason"]
punished = await self.config.guild(guild).PUNISHED()
embeds = []
@ -143,13 +145,13 @@ class Punish(commands.Cog):
for i, data in enumerate(punished.items()):
member_id, data = data
member_name = getmname(member_id, guild)
moderator = getmname(data['by'], guild)
reason = data['reason']
until = data['until']
moderator = getmname(data["by"], guild)
reason = data["reason"]
until = data["until"]
sort = until or float("inf")
remaining = generate_timespec(until - now, short=True) if until else 'forever'
remaining = generate_timespec(until - now, short=True) if until else "forever"
row = [member_name, remaining, moderator, reason or 'No reason set.']
row = [member_name, remaining, moderator, reason or "No reason set."]
embed = discord.Embed(title="Punish List", colour=discord.Colour.from_rgb(255, 0, 0))
for header, row_val in zip(headers, row):
@ -164,7 +166,7 @@ class Punish(commands.Cog):
await menu(ctx, embeds, DEFAULT_CONTROLS)
@punish.command(name='clean')
@punish.command(name="clean")
@commands.guild_only()
@checks.mod()
async def punish_clean(self, ctx, clean_pending: bool = False):
@ -189,14 +191,14 @@ class Punish(commands.Cog):
if not mid.isdigit() or guild.get_member(mid):
continue
elif clean_pending or ((mdata['until'] or 0) < now):
del(data[mid])
elif clean_pending or ((mdata["until"] or 0) < now):
del data[mid]
count += 1
await self.config.guild(guild).PUNISHED.set(data)
await ctx.send('Cleaned %i absent members from the list.' % count)
await ctx.send("Cleaned %i absent members from the list." % count)
@punish.command(name='clean-bans')
@punish.command(name="clean-bans")
@commands.guild_only()
@checks.mod()
async def punish_clean_bans(self, ctx):
@ -220,13 +222,13 @@ class Punish(commands.Cog):
continue
elif mid in ban_ids:
del(data[mid])
del data[mid]
count += 1
await self.config.guild(guild).PUNISHED.set(data)
await ctx.send('Cleaned %i banned users from the list.' % count)
await ctx.send("Cleaned %i banned users from the list." % count)
@punish.command(name='warn')
@punish.command(name="warn")
@commands.guild_only()
@checks.mod_or_permissions(manage_messages=True)
async def punish_warn(self, ctx, user: discord.Member, *, reason: str = None):
@ -234,16 +236,15 @@ class Punish(commands.Cog):
Warns a user with boilerplate about the rules
"""
msg = ['Hey %s, ' % user.mention]
msg.append("you're doing something that might get you muted if you keep "
"doing it.")
msg = ["Hey %s, " % user.mention]
msg.append("you're doing something that might get you muted if you keep " "doing it.")
if reason:
msg.append(" Specifically, %s." % reason)
msg.append("Be sure to review the guild rules.")
await ctx.send(' '.join(msg))
await ctx.send(" ".join(msg))
@punish.command(name='end', aliases=['remove'])
@punish.command(name="end", aliases=["remove"])
@commands.guild_only()
@checks.mod()
async def punish_end(self, ctx, user: discord.Member, *, reason: str = None):
@ -260,60 +261,64 @@ class Punish(commands.Cog):
now = time.time()
punished = await self.config.guild(guild).PUNISHED()
data = punished.get(str(user.id), {})
removed_roles_parsed = resolve_role_list(guild, data.get('removed_roles', []))
removed_roles_parsed = resolve_role_list(guild, data.get("removed_roles", []))
if role and role in user.roles:
msg = 'Punishment manually ended early by %s.' % ctx.author
msg = "Punishment manually ended early by %s." % ctx.author
original_start = data.get('start')
original_end = data.get('until')
original_start = data.get("start")
original_end = data.get("until")
remaining = original_end and (original_end - now)
if remaining:
msg += ' %s was left' % generate_timespec(round(remaining))
msg += " %s was left" % generate_timespec(round(remaining))
if original_start:
msg += ' of the original %s.' % generate_timespec(round(original_end - original_start))
msg += " of the original %s." % generate_timespec(round(original_end - original_start))
else:
msg += '.'
msg += "."
if reason:
msg += '\n\nReason for ending early: ' + reason
msg += "\n\nReason for ending early: " + reason
if data.get('reason'):
msg += '\n\nOriginal reason was: ' + data['reason']
if data.get("reason"):
msg += "\n\nOriginal reason was: " + data["reason"]
updated_reason = str(msg) # copy string
updated_reason = str(msg) # copy string
if removed_roles_parsed:
names_list = format_list(*(r.name for r in removed_roles_parsed))
msg += "\nRestored role(s): {}".format(names_list)
if not await self._unpunish(user, reason=updated_reason, update=True, moderator=moderator):
msg += '\n\n(failed to send punishment end notification DM)'
msg += "\n\n(failed to send punishment end notification DM)"
await ctx.send(msg)
elif data: # This shouldn't happen, but just in case
now = time.time()
until = data.get('until')
remaining = until and generate_timespec(round(until - now)) or 'forever'
until = data.get("until")
remaining = until and generate_timespec(round(until - now)) or "forever"
data_fmt = '\n'.join([
"**Reason:** %s" % (data.get('reason') or 'no reason set'),
"**Time remaining:** %s" % remaining,
"**Moderator**: %s" % (user.guild.get_member(data.get('by')) or 'Missing ID#%s' % data.get('by'))
])
del(punished[str(user.id)])
data_fmt = "\n".join(
[
"**Reason:** %s" % (data.get("reason") or "no reason set"),
"**Time remaining:** %s" % remaining,
"**Moderator**: %s" % (user.guild.get_member(data.get("by")) or "Missing ID#%s" % data.get("by")),
]
)
del punished[str(user.id)]
await self.config.guild(guild).PUNISHED.set(punished)
await ctx.send("That user doesn't have the %s role, but they still have a data entry. I removed it, "
"but in case it's needed, this is what was there:\n\n%s" % (role.name, data_fmt))
await ctx.send(
"That user doesn't have the %s role, but they still have a data entry. I removed it, "
"but in case it's needed, this is what was there:\n\n%s" % (role.name, data_fmt)
)
elif role:
await ctx.send("That user doesn't have the %s role." % role.name)
else:
await ctx.send("The punish role couldn't be found in this guild.")
@punish.command(name='reason')
@punish.command(name="reason")
@commands.guild_only()
@checks.mod()
async def punish_reason(self, ctx, user: discord.Member, *, reason: str = None):
@ -325,19 +330,21 @@ class Punish(commands.Cog):
data = punished.get(str(user.id), None)
if not data:
await ctx.send("That user doesn't have an active punishment entry. To update modlog "
"cases manually, use the `%sreason` command." % ctx.prefix)
await ctx.send(
"That user doesn't have an active punishment entry. To update modlog "
"cases manually, use the `%sreason` command." % ctx.prefix
)
return
punished[str(user.id)]['reason'] = reason
punished[str(user.id)]["reason"] = reason
await self.config.guild(guild).PUNISHED.set(punished)
if reason:
msg = 'Reason updated.'
msg = "Reason updated."
else:
msg = 'Reason cleared.'
msg = "Reason cleared."
caseno = data.get('caseno')
caseno = data.get("caseno")
try:
case = await modlog.get_case(caseno, guild, self.bot)
except:
@ -348,12 +355,12 @@ class Punish(commands.Cog):
moderator = ctx.author
try:
edits = {'reason': reason}
edits = {"reason": reason}
if moderator.id != data.get('by'):
edits['amended_by'] = moderator
if moderator.id != data.get("by"):
edits["amended_by"] = moderator
edits['modified_at'] = ctx.message.created_at.timestamp()
edits["modified_at"] = ctx.message.created_at.timestamp()
await case.edit(edits)
except:
@ -504,23 +511,23 @@ class Punish(commands.Cog):
try:
# Combine sets to get the baseline (roles they'd have normally)
member_roles |= set(role_memo.filter(member_data['removed_roles'], skip_nulls=True))
member_roles |= set(role_memo.filter(member_data["removed_roles"], skip_nulls=True))
except KeyError:
pass
# update new removed roles with intersection of guild removal list and baseline
new_removed = guild_remove_roles & member_roles
punished[str(member.id)]['removed_roles'] = [r.id for r in new_removed]
punished[str(member.id)]["removed_roles"] = [r.id for r in new_removed]
member_roles -= guild_remove_roles
# can't restore, so skip (remove from set)
for role in (member_roles - original_roles):
for role in member_roles - original_roles:
if role >= highest_role:
member_roles.discard(role)
# can't remove, so skip (re-add to set)
for role in (original_roles - member_roles):
for role in original_roles - member_roles:
if role >= highest_role:
member_roles.add(role)
@ -541,7 +548,7 @@ class Punish(commands.Cog):
await ctx.send(msg)
@punishset.command(name='setup')
@punishset.command(name="setup")
async def punishset_setup(self, ctx):
"""
(Re)configures the punish role and channel overrides
@ -568,28 +575,29 @@ class Punish(commands.Cog):
perms = discord.Permissions.none()
role = await guild.create_role(name=default_name, permissions=perms, reason="punish cog.")
else:
msgobj = await ctx.send('%s role exists... ' % role.name)
msgobj = await ctx.send("%s role exists... " % role.name)
if role.position != (guild.me.top_role.position - 1):
if role < guild.me.top_role:
await msgobj.edit(content=msgobj.content + 'moving role to higher position... ')
await msgobj.edit(content=msgobj.content + "moving role to higher position... ")
await role.edit(position=guild.me.top_role.position - 1)
else:
await msgobj.edit(content=msgobj.content + 'role is too high to manage.'
' Please move it to below my highest role.')
await msgobj.edit(
content=msgobj.content + "role is too high to manage." " Please move it to below my highest role."
)
return
await msgobj.edit(content=msgobj.content + '(re)configuring channels... ')
await msgobj.edit(content=msgobj.content + "(re)configuring channels... ")
for channel in guild.channels:
await self.setup_channel(channel, role)
await msgobj.edit(content=msgobj.content + 'done.')
await msgobj.edit(content=msgobj.content + "done.")
if role and role.id != role_id:
await self.config.guild(guild).ROLE_ID.set(role.id)
@punishset.command(name='channel')
@punishset.command(name="channel")
async def punishset_channel(self, ctx, channel: discord.TextChannel = None):
"""
Sets or shows the punishment "timeout" channel.
@ -613,13 +621,16 @@ class Punish(commands.Cog):
await ctx.send("The timeout channel is currently %s." % current.mention)
else:
if current == channel:
await ctx.send("The timeout channel is already %s. If you need to repair its permissions, use `%spunishset setup`." % (current.mention, ctx.prefix))
await ctx.send(
"The timeout channel is already %s. If you need to repair its permissions, use `%spunishset setup`."
% (current.mention, ctx.prefix)
)
return
await self.config.guild(guild).CHANNEL_ID.set(channel.id)
role = await self.get_role(guild, create=True)
update_msg = '{} to the %s role' % role
update_msg = "{} to the %s role" % role
grants = []
denies = []
perms = permissions_for_roles(channel, role)
@ -631,7 +642,7 @@ class Punish(commands.Cog):
if getattr(perms, perm) != value:
setattr(overwrite, perm, value)
name = perm.replace('_', ' ').title().replace("Tts", "TTS")
name = perm.replace("_", " ").title().replace("Tts", "TTS")
if value:
grants.append(name)
@ -640,8 +651,8 @@ class Punish(commands.Cog):
# Any changes made? Apply them.
if grants or denies:
grants = grants and ('grant ' + format_list(*grants))
denies = denies and ('deny ' + format_list(*denies))
grants = grants and ("grant " + format_list(*grants))
denies = denies and ("deny " + format_list(*denies))
to_join = [x for x in (grants, denies) if x]
update_msg = update_msg.format(format_list(*to_join))
@ -655,14 +666,14 @@ class Punish(commands.Cog):
await self.setup_channel(current, role)
if channel.permissions_for(guild.me).manage_roles:
await ctx.send(info('Updating permissions in %s to %s...' % (channel.mention, update_msg)))
await ctx.send(info("Updating permissions in %s to %s..." % (channel.mention, update_msg)))
await channel.set_permissions(role, overwrite=overwrite)
else:
await ctx.send(error("I don't have permissions to %s." % update_msg))
await ctx.send("Timeout channel set to %s." % channel.mention)
@punishset.command(name='clear-channel')
@punishset.command(name="clear-channel")
async def punishset_clear_channel(self, ctx):
"""
Clears the timeout channel and resets its permissions
@ -678,7 +689,7 @@ class Punish(commands.Cog):
if current.permissions_for(guild.me).manage_roles:
role = await self.get_role(guild, quiet=True)
await self.setup_channel(current, role)
msg = ' and its permissions reset'
msg = " and its permissions reset"
else:
msg = ", but I don't have permissions to reset its permissions."
@ -686,7 +697,7 @@ class Punish(commands.Cog):
else:
await ctx.send("No timeout channel has been set yet.")
@punishset.command(name='case-min')
@punishset.command(name="case-min")
async def punishset_case_min(self, ctx, *, timespec: str = None):
"""
Set/disable or display the minimum punishment case duration
@ -699,11 +710,11 @@ class Punish(commands.Cog):
if not timespec:
if current:
await ctx.send('Punishments longer than %s will create cases.' % generate_timespec(current))
await ctx.send("Punishments longer than %s will create cases." % generate_timespec(current))
else:
await ctx.send("Punishment case creation is disabled.")
else:
if timespec.strip('\'"').lower() == 'disable':
if timespec.strip("'\"").lower() == "disable":
value = None
else:
try:
@ -714,9 +725,9 @@ class Punish(commands.Cog):
await self.config.guild(guild).CASE_MIN_LENGTH.set(value)
await ctx.send('Punishments longer than %s will create cases.' % generate_timespec(value))
await ctx.send("Punishments longer than %s will create cases." % generate_timespec(value))
@punishset.command(name='overrides')
@punishset.command(name="overrides")
async def punishset_overrides(self, ctx, *, channel_id: int = None):
"""
Copy or display the punish role overrides
@ -751,52 +762,58 @@ class Punish(commands.Cog):
confirm_msg = "Are you sure you want to copy overrides from this channel?"
if channel.type is discord.ChannelType.text:
key = 'text'
key = "text"
elif channel.type is discord.ChannelType.voice:
key = 'voice'
key = "voice"
else:
await ctx.send(error("Unknown channel type!"))
return
if confirm_msg:
await ctx.send(warning(confirm_msg + '(reply `yes` within 30s to confirm)'))
await ctx.send(warning(confirm_msg + "(reply `yes` within 30s to confirm)"))
def check(m):
return m.author == ctx.author and m.channel == ctx.channel
try:
reply = await self.bot.wait_for('message', check=check, timeout=30.0)
if reply.content.strip(' `"\'').lower() != 'yes':
await ctx.send('Commmand cancelled.')
reply = await self.bot.wait_for("message", check=check, timeout=30.0)
if reply.content.strip(" `\"'").lower() != "yes":
await ctx.send("Commmand cancelled.")
return
except asyncio.TimeoutError:
await ctx.send('Timed out waiting for a response.')
await ctx.send("Timed out waiting for a response.")
return
if key == 'text':
if key == "text":
await self.config.guild(guild).TEXT_OVERWRITE.set(overwrite_to_dict(overwrite))
else:
await self.config.guild(guild).VOICE_OVERWRITE.set(overwrite_to_dict(overwrite))
await ctx.send("{} channel overrides set to:\n".format(key.title()) +
format_permissions(overwrite) +
"\n\nRun `%spunishset setup` to apply them to all channels." % ctx.prefix)
await ctx.send(
"{} channel overrides set to:\n".format(key.title())
+ format_permissions(overwrite)
+ "\n\nRun `%spunishset setup` to apply them to all channels." % ctx.prefix
)
else:
msg = []
for key in ('text', 'voice'):
if key == 'text':
for key in ("text", "voice"):
if key == "text":
data = await self.config.guild(guild).TEXT_OVERWRITE()
else:
data = await self.config.guild(guild).VOICE_OVERWRITE()
title = '%s permission overrides:' % key.title()
title = "%s permission overrides:" % key.title()
if data == overwrite_to_dict(DEFAULT_TEXT_OVERWRITE) or data == overwrite_to_dict(DEFAULT_VOICE_OVERWRITE):
title = title[:-1] + ' (defaults):'
if data == overwrite_to_dict(DEFAULT_TEXT_OVERWRITE) or data == overwrite_to_dict(
DEFAULT_VOICE_OVERWRITE
):
title = title[:-1] + " (defaults):"
msg.append(bold(title) + '\n' + format_permissions(overwrite_from_dict(data)))
msg.append(bold(title) + "\n" + format_permissions(overwrite_from_dict(data)))
await ctx.send('\n\n'.join(msg))
await ctx.send("\n\n".join(msg))
@punishset.command(name='reset-overrides')
async def punishset_reset_overrides(self, ctx, channel_type: str = 'both'):
@punishset.command(name="reset-overrides")
async def punishset_reset_overrides(self, ctx, channel_type: str = "both"):
"""
Resets the punish role overrides for text, voice or both (default)
@ -804,21 +821,21 @@ class Punish(commands.Cog):
for newly created channels.
"""
channel_type = channel_type.strip('`"\' ').lower()
channel_type = channel_type.strip("`\"' ").lower()
msg = []
for key in ('text', 'voice'):
if channel_type not in ['both', key]:
for key in ("text", "voice"):
if channel_type not in ["both", key]:
continue
title = '%s permission overrides reset to:' % key.title()
title = "%s permission overrides reset to:" % key.title()
if key == 'text':
if key == "text":
await self.config.guild(guild).TEXT_OVERWRITE.set(overwrite_to_dict(DEFAULT_TEXT_OVERWRITE))
msg.append(bold(title) + '\n' + format_permissions(overwrite_to_dict(DEFAULT_TEXT_OVERWRITE)))
msg.append(bold(title) + "\n" + format_permissions(overwrite_to_dict(DEFAULT_TEXT_OVERWRITE)))
else:
await self.config.guild(guild).VOICE_OVERWRITE.set(overwrite_to_dict(DEFAULT_VOICE_OVERWRITE))
msg.append(bold(title) + '\n' + format_permissions(overwrite_to_dict(DEFAULT_VOICE_OVERWRITE)))
msg.append(bold(title) + "\n" + format_permissions(overwrite_to_dict(DEFAULT_VOICE_OVERWRITE)))
if not msg:
await ctx.send("Invalid channel type. Use `text`, `voice`, or `both` (the default, if not specified)")
@ -826,7 +843,7 @@ class Punish(commands.Cog):
msg.append("Run `%spunishset setup` to apply them to all channels." % ctx.prefix)
await ctx.send('\n\n'.join(msg))
await ctx.send("\n\n".join(msg))
async def get_role(self, guild, quiet=False, create=False):
role_id = await self.config.guild(guild).ROLE_ID()
@ -848,19 +865,19 @@ class Punish(commands.Cog):
if not quiet:
msgobj = await ctx.send(msg)
log.debug('Creating punish role in %s' % guild.name)
log.debug("Creating punish role in %s" % guild.name)
perms = discord.Permissions.none()
role = await guild.create_role(name=DEFAULT_ROLE_NAME, permissions=perms, reason="punish cog.")
await role.edit(position=guild.me.top_role.position - 1)
if not quiet:
await msgobj.edit(content=msgobj.content + '\nconfiguring channels... ')
await msgobj.edit(content=msgobj.content + "\nconfiguring channels... ")
for channel in guild.channels:
await self.setup_channel(channel, role)
if not quiet:
await msgobj.edit(content=msgobj.content + '\ndone.')
await msgobj.edit(content=msgobj.content + "\ndone.")
if role and role.id != role_id:
await self.config.guild(guild).ROLE_ID.set(role.id)
@ -906,23 +923,23 @@ class Punish(commands.Cog):
for member_id, data in punished.items():
until = data['until']
until = data["until"]
member = guild.get_member(member_id)
if until and (until - time.time()) < 0:
if member:
reason = 'Punishment removal overdue, maybe the bot was offline. '
reason = "Punishment removal overdue, maybe the bot was offline. "
if data['reason']:
reason += data['reason']
if data["reason"]:
reason += data["reason"]
await self._unpunish(member, reason=reason)
else: # member disappeared
del(punished[str(member_id)])
del punished[str(member_id)]
elif member:
# re-check roles
user_roles = set(member.roles)
removed_roles = set(role_memo.filter(data.get('removed_roles', ()), skip_nulls=True))
removed_roles = set(role_memo.filter(data.get("removed_roles", ()), skip_nulls=True))
removed_roles = user_roles & {r for r in removed_roles if r < me.top_role}
user_roles -= removed_roles
@ -954,7 +971,7 @@ class Punish(commands.Cog):
except Exception:
pass
log.debug('queue manager dying')
log.debug("queue manager dying")
while not self.queue.empty():
self.queue.get_nowait()
@ -985,7 +1002,7 @@ class Punish(commands.Cog):
return removed is not None
async def put_queue_event(self, run_at : float, *args):
async def put_queue_event(self, run_at: float, *args):
diff = run_at - time.time()
if args in self.enqueued:
@ -1038,7 +1055,7 @@ class Punish(commands.Cog):
remove_role_set = set(resolve_role_list(guild, remove_role_set))
punished = await self.config.guild(guild).PUNISHED()
current = punished.get(str(member.id), {})
reason = reason or current.get('reason') # don't clear if not given
reason = reason or current.get("reason") # don't clear if not given
hierarchy_allowed = ctx.author.top_role > member.top_role
case_min_length = await self.config.guild(guild).CASE_MIN_LENGTH()
nitro_role = await self.config.guild(guild).NITRO_ID()
@ -1051,7 +1068,7 @@ class Punish(commands.Cog):
await ctx.send("You can't punish the bot.")
return
if duration and duration.lower() in ['forever', 'inf', 'infinite']:
if duration and duration.lower() in ["forever", "inf", "infinite"]:
duration = None
else:
if not duration:
@ -1071,7 +1088,7 @@ class Punish(commands.Cog):
if role is None:
return
elif role >= guild.me.top_role:
await ctx.send('The %s role is too high for me to manage.' % role)
await ctx.send("The %s role is too high for me to manage." % role)
return
# Call time() after getting the role due to potential creation delay
@ -1085,22 +1102,26 @@ class Punish(commands.Cog):
try:
if current:
case_number = current.get('caseno')
case_number = current.get("caseno")
try:
case = await modlog.get_case(case_number, guild, self.bot)
except: # shouldn't happen
await ctx.send(warning("Error, modlog case not found, but user is punished with case.\nTry unpunishing and punishing again."))
except: # shouldn't happen
await ctx.send(
warning(
"Error, modlog case not found, but user is punished with case.\nTry unpunishing and punishing again."
)
)
return
moderator = ctx.author
try:
edits = {'reason': reason}
edits = {"reason": reason}
if moderator.id != current.get('by'):
edits['amended_by'] = moderator
if moderator.id != current.get("by"):
edits["amended_by"] = moderator
edits['modified_at'] = ctx.message.created_at.timestamp()
edits["modified_at"] = ctx.message.created_at.timestamp()
await case.edit(edits)
except Exception as e:
@ -1110,7 +1131,16 @@ class Punish(commands.Cog):
updating_case = True
else:
case = await modlog.create_case(self.bot, guild, now_date, "Timed Mute", member, moderator=ctx.author, reason=reason, until=mod_until)
case = await modlog.create_case(
self.bot,
guild,
now_date,
"Timed Mute",
member,
moderator=ctx.author,
reason=reason,
until=mod_until,
)
case_number = case.case_number
except Exception as e:
@ -1118,18 +1148,18 @@ class Punish(commands.Cog):
else:
case_number = None
subject = 'the %s role' % role.name
subject = "the %s role" % role.name
if str(member.id) in punished:
if role in member.roles:
msg = '{0} already had the {1.name} role; resetting their timer.'
msg = "{0} already had the {1.name} role; resetting their timer."
else:
msg = '{0} is missing the {1.name} role for some reason. I added it and reset their timer.'
msg = "{0} is missing the {1.name} role for some reason. I added it and reset their timer."
elif role in member.roles:
msg = '{0} already had the {1.name} role, but had no timer; setting it now.'
msg = "{0} already had the {1.name} role, but had no timer; setting it now."
else:
msg = 'Applied the {1.name} role to {0}.'
subject = 'it'
msg = "Applied the {1.name} role to {0}."
subject = "it"
msg = msg.format(member, role)
@ -1137,24 +1167,24 @@ class Punish(commands.Cog):
timespec = generate_timespec(duration)
if using_default:
timespec += ' (the default)'
timespec += " (the default)"
msg += ' I will remove %s in %s.' % (subject, timespec)
msg += " I will remove %s in %s." % (subject, timespec)
if case_error:
if isinstance(case_error, CaseMessageNotFound):
case_error = 'the case message could not be found'
case_error = "the case message could not be found"
elif isinstance(case_error, NoModLogAccess):
case_error = 'I do not have access to the modlog channel'
case_error = "I do not have access to the modlog channel"
else:
case_error = None
if case_error:
verb = 'updating' if updating_case else 'creating'
msg += '\n\n' + warning('There was an error %s the modlog case: %s.' % (verb, case_error))
verb = "updating" if updating_case else "creating"
msg += "\n\n" + warning("There was an error %s the modlog case: %s." % (verb, case_error))
elif case_number:
verb = 'updated' if updating_case else 'created'
msg += ' I also %s case #%i in the modlog.' % (verb, case_number)
verb = "updated" if updating_case else "created"
msg += " I also %s case #%i in the modlog." % (verb, case_number)
voice_overwrite = await self.config.guild(guild).VOICE_OVERWRITE()
@ -1175,12 +1205,12 @@ class Punish(commands.Cog):
# build lists of roles that *should* be removed and ones that *can* be
removed_roles = user_roles & remove_role_set
too_high_to_remove = {r for r in removed_roles if r >= guild.me.top_role}
user_roles -= (removed_roles - too_high_to_remove)
user_roles -= removed_roles - too_high_to_remove
user_roles.add(role) # add punish role to the set
await member.edit(roles=user_roles, reason=f"punish {member}")
else:
removed_roles = set(resolve_role_list(guild, current.get('removed_roles', [])))
removed_roles = set(resolve_role_list(guild, current.get("removed_roles", [])))
too_high_to_remove = {r for r in removed_roles if r >= guild.me.top_role}
if removed_roles:
@ -1190,8 +1220,10 @@ class Punish(commands.Cog):
if too_high_to_remove:
fmt_list = format_list(*(r.name for r in removed_roles))
msg += "\n" + warning("These roles were too high to remove (fix hierarchy, then run "
"`{}punishset sync-roles`): {}".format(ctx.prefix, fmt_list))
msg += "\n" + warning(
"These roles were too high to remove (fix hierarchy, then run "
"`{}punishset sync-roles`): {}".format(ctx.prefix, fmt_list)
)
if member.voice:
muted = member.voice.mute
else:
@ -1199,13 +1231,13 @@ class Punish(commands.Cog):
async with self.config.guild(guild).PUNISHED() as punished:
punished[str(member.id)] = {
'start' : current.get('start') or now, # don't override start time if updating
'until' : until,
'by' : current.get('by') or ctx.author.id, # don't override original moderator
'reason' : reason,
'unmute' : overwrite_denies_speak and not muted,
'caseno' : case_number,
'removed_roles' : [r.id for r in removed_roles]
"start": current.get("start") or now, # don't override start time if updating
"until": until,
"by": current.get("by") or ctx.author.id, # don't override original moderator
"reason": reason,
"unmute": overwrite_denies_speak and not muted,
"caseno": case_number,
"removed_roles": [r.id for r in removed_roles],
}
if member.voice and overwrite_denies_speak:
@ -1256,8 +1288,8 @@ class Punish(commands.Cog):
if role:
data = await self.config.guild(guild).PUNISHED()
member_data = data.get(str(member.id), {})
caseno = member_data.get('caseno')
removed_roles = set(resolve_role_list(guild, member_data.get('removed_roles', [])))
caseno = member_data.get("caseno")
removed_roles = set(resolve_role_list(guild, member_data.get("removed_roles", [])))
# Has to be done first to prevent triggering listeners
await self._unpunish_data(member)
@ -1280,20 +1312,20 @@ class Punish(commands.Cog):
await member.edit(roles=user_roles, reason="punish end")
if update and caseno:
until = member_data.get('until') or False
until = member_data.get("until") or False
# fallback gracefully
moderator = moderator or guild.get_member(member_data.get('by')) or guild.me
moderator = moderator or guild.get_member(member_data.get("by")) or guild.me
if until:
until = datetime.utcfromtimestamp(until).timestamp()
edits = {'reason': reason}
edits = {"reason": reason}
if moderator.id != data.get('by'):
edits['amended_by'] = moderator
if moderator.id != data.get("by"):
edits["amended_by"] = moderator
edits['modified_at'] = time.time()
edits['until'] = until
edits["modified_at"] = time.time()
edits["until"] = until
try:
case = await modlog.get_case(caseno, guild, self.bot)
@ -1301,7 +1333,7 @@ class Punish(commands.Cog):
except Exception:
pass
if member_data.get('unmute', False):
if member_data.get("unmute", False):
if member.voice:
if member.voice.channel:
await member.edit(mute=False)
@ -1313,7 +1345,7 @@ class Punish(commands.Cog):
if quiet:
return True
msg = 'Your punishment in %s has ended.' % member.guild.name
msg = "Your punishment in %s has ended." % member.guild.name
if reason:
msg += "\nReason: %s" % reason
@ -1323,8 +1355,9 @@ class Punish(commands.Cog):
if too_high_to_restore:
fmt_list = format_list(*(r.name for r in too_high_to_restore))
msg += "\n" + warning("These roles were too high for me to restore: {}. "
"Ask a mod for help.".format(fmt_list))
msg += "\n" + warning(
"These roles were too high for me to restore: {}. " "Ask a mod for help.".format(fmt_list)
)
try:
await member.send(msg)
@ -1338,7 +1371,7 @@ class Punish(commands.Cog):
async with self.config.guild(guild).PUNISHED() as punished:
if str(member.id) in punished:
del(punished[str(member.id)])
del punished[str(member.id)]
# Listeners
@commands.Cog.listener()
@ -1365,14 +1398,14 @@ class Punish(commands.Cog):
new_roles = {role.id: role for role in after.roles}
if role in before.roles and role.id not in new_roles:
msg = 'Punishment manually ended early by a moderator/admin.'
msg = "Punishment manually ended early by a moderator/admin."
if member_data['reason']:
msg += '\nReason was: ' + member_data['reason']
if member_data["reason"]:
msg += "\nReason was: " + member_data["reason"]
await self._unpunish(after, reason=msg, update=True)
else:
to_remove = {new_roles.get(role_id) for role_id in member_data.get('removed_roles', [])}
to_remove = {new_roles.get(role_id) for role_id in member_data.get("removed_roles", [])}
to_remove = [r for r in to_remove if r and r < after.guild.me.top_role]
if to_remove:
@ -1393,7 +1426,7 @@ class Punish(commands.Cog):
member = self.bot.get_guild(guild.id).get_member(member.id)
role = await self.get_role(member.guild, quiet=True)
until = data['until']
until = data["until"]
duration = until - time.time()
if role and duration > 0:
@ -1433,7 +1466,7 @@ class Punish(commands.Cog):
msg = "Punishment ended early due to ban."
if member_data.get('reason'):
msg += '\n\nOriginal reason was: ' + member_data['reason']
if member_data.get("reason"):
msg += "\n\nOriginal reason was: " + member_data["reason"]
await self._unpunish(member, reason=msg, apply_roles=False, update=True, quiet=True)

View file

@ -2,13 +2,14 @@ import re
import discord
UNIT_TABLE = (
(('weeks', 'wks', 'w'), 60 * 60 * 24 * 7),
(('days', 'dys', 'd'), 60 * 60 * 24),
(('hours', 'hrs', 'h'), 60 * 60),
(('minutes', 'mins', 'm'), 60),
(('seconds', 'secs', 's'), 1),
(("weeks", "wks", "w"), 60 * 60 * 24 * 7),
(("days", "dys", "d"), 60 * 60 * 24),
(("hours", "hrs", "h"), 60 * 60),
(("minutes", "mins", "m"), 60),
(("seconds", "secs", "s"), 1),
)
class BadTimeExpr(Exception):
pass
@ -23,24 +24,23 @@ def _find_unit(unit):
def parse_time(time):
time = time.lower()
if not time.isdigit():
time = re.split(r'\s*([\d.]+\s*[^\d\s,;]*)(?:[,;\s]|and)*', time)
time = re.split(r"\s*([\d.]+\s*[^\d\s,;]*)(?:[,;\s]|and)*", time)
time = sum(map(_timespec_sec, filter(None, time)))
return int(time)
def _timespec_sec(expr):
atoms = re.split(r'([\d.]+)\s*([^\d\s]*)', expr)
atoms = re.split(r"([\d.]+)\s*([^\d\s]*)", expr)
atoms = list(filter(None, atoms))
if len(atoms) > 2: # This shouldn't ever happen
raise BadTimeExpr("invalid expression: '%s'" % expr)
elif len(atoms) == 2:
names, length = _find_unit(atoms[1])
if atoms[0].count('.') > 1 or \
not atoms[0].replace('.', '').isdigit():
if atoms[0].count(".") > 1 or not atoms[0].replace(".", "").isdigit():
raise BadTimeExpr("Not a number: '%s'" % atoms[0])
else:
names, length = _find_unit('seconds')
names, length = _find_unit("seconds")
try:
return float(atoms[0]) * length
@ -59,48 +59,46 @@ def generate_timespec(sec: int, short=False, micro=False) -> str:
if n:
if micro:
s = '%d%s' % (n, names[2])
s = "%d%s" % (n, names[2])
elif short:
s = '%d%s' % (n, names[1])
s = "%d%s" % (n, names[1])
else:
s = '%d %s' % (n, names[0])
s = "%d %s" % (n, names[0])
if n <= 1 and not (micro and names[2] == 's'):
s = s.rstrip('s')
if n <= 1 and not (micro and names[2] == "s"):
s = s.rstrip("s")
timespec.append(s)
if len(timespec) > 1:
if micro:
spec = ''.join(timespec)
spec = "".join(timespec)
segments = timespec[:-1], timespec[-1:]
spec = ' and '.join(', '.join(x) for x in segments)
spec = " and ".join(", ".join(x) for x in segments)
elif timespec:
spec = timespec[0]
else:
return '0'
return "0"
if neg:
spec += ' ago'
spec += " ago"
return spec
def format_list(*items, join='and', delim=', '):
def format_list(*items, join="and", delim=", "):
if len(items) > 1:
return (' %s ' % join).join((delim.join(items[:-1]), items[-1]))
return (" %s " % join).join((delim.join(items[:-1]), items[-1]))
elif items:
return items[0]
else:
return ''
return ""
def overwrite_to_dict(overwrite):
allow, deny = overwrite.pair()
return {
'allow' : allow.value,
'deny' : deny.value
}
return {"allow": allow.value, "deny": deny.value}
def format_permissions(permissions, include_null=False):
@ -116,10 +114,10 @@ def format_permissions(permissions, include_null=False):
else:
continue
entries.append(symbol + ' ' + perm.replace('_', ' ').title().replace("Tts", "TTS"))
entries.append(symbol + " " + perm.replace("_", " ").title().replace("Tts", "TTS"))
if entries:
return '\n'.join(entries)
return "\n".join(entries)
else:
return "No permission entries."
@ -130,7 +128,7 @@ def getmname(mid, guild):
if member:
return str(member)
else:
return '(absent user #%s)' % mid
return "(absent user #%s)" % mid
def role_from_string(guild, rolename, roles=None):
@ -186,7 +184,7 @@ def permissions_for_roles(channel, *roles):
if overwrite.id == default.id:
base.handle_overwrite(allow=overwrite.allow, deny=overwrite.deny)
if overwrite.type == 'role' and overwrite.id in role_ids:
if overwrite.type == "role" and overwrite.id in role_ids:
denies |= overwrite.deny
allows |= overwrite.allow
@ -218,6 +216,6 @@ def permissions_for_roles(channel, *roles):
def overwrite_from_dict(data):
allow = discord.Permissions(data.get('allow', 0))
deny = discord.Permissions(data.get('deny', 0))
allow = discord.Permissions(data.get("allow", 0))
deny = discord.Permissions(data.get("deny", 0))
return discord.PermissionOverwrite.from_pair(allow, deny)

View file

@ -14,6 +14,7 @@ import asyncio
import os
import json
class RolePlay(commands.Cog):
def __init__(self):
super().__init__()
@ -31,7 +32,8 @@ class RolePlay(commands.Cog):
"lotsa spaghetti",
"a brick",
"a slice of cheese",
"my foot"],
"my foot",
],
"high_iq_msgs": [
"wow!",
"that's pretty big.",
@ -40,7 +42,8 @@ class RolePlay(commands.Cog):
"someone here is actually smart.",
"thats a dab.",
"<:aureliawink:549481308519399425>",
"you must of watched Rick and Morty."],
"you must of watched Rick and Morty.",
],
"low_iq_msgs": [
":rofl:",
"oof.",
@ -49,7 +52,8 @@ class RolePlay(commands.Cog):
"awww you're special aren't you.",
":crying_cat_face:",
"god I'm sorry (not).",
"I didn't know people could have IQ that low."]
"I didn't know people could have IQ that low.",
],
}
self.config.register_guild(**self.default_guild)
@ -104,12 +108,11 @@ class RolePlay(commands.Cog):
elif user.id == botid:
user = ctx.message.author
botname = ctx.bot.user.name
await ctx.send("`-" + botname + " slaps " + user.display_name +
" multiple times with " +
(choice(slap_items) + "-`"))
await ctx.send(
"`-" + botname + " slaps " + user.display_name + " multiple times with " + (choice(slap_items) + "-`")
)
else:
await ctx.send("`-slaps " + user.display_name + " with " +
(choice(slap_items) + "-`"))
await ctx.send("`-slaps " + user.display_name + " with " + (choice(slap_items) + "-`"))
@slap.command(name="add")
@checks.admin()
@ -126,7 +129,7 @@ class RolePlay(commands.Cog):
@slap.command(name="remove")
@checks.admin()
async def _remove_slap(self, ctx, slap_item: str=""):
async def _remove_slap(self, ctx, slap_item: str = ""):
"""Removes item to use for slaps!"""
guild = ctx.guild
slap_items = await self.config.guild(guild).slap_items()
@ -146,7 +149,7 @@ class RolePlay(commands.Cog):
msg = ""
for item in slap_items:
msg += "+ {}\n".format(item)
pages = pagify(msg) # pages is an iterator of pages
pages = pagify(msg) # pages is an iterator of pages
for page in pages:
await ctx.send(box(page, lang="diff"))
@ -173,9 +176,8 @@ class RolePlay(commands.Cog):
except json.decoder.JSONDecodeError:
await ctx.send("Invalid or malformed json file.")
@commands.group(invoke_without_command=True)
async def iq(self, ctx, *users : discord.Member):
async def iq(self, ctx, *users: discord.Member):
"""
Gets IQ of a user. Use multiple users to compare IQs
"""
@ -199,7 +201,9 @@ class RolePlay(commands.Cog):
iqs = sorted(iqs.items(), key=lambda x: x[1])
for user, iq in iqs:
msg += "{}'s iq is {}, {}\n".format(user.display_name, iq, choice(high_iq_msgs) if int(iq) > 130 else choice(low_iq_messages))
msg += "{}'s iq is {}, {}\n".format(
user.display_name, iq, choice(high_iq_msgs) if int(iq) > 130 else choice(low_iq_messages)
)
await ctx.send(msg)
@ -215,11 +219,11 @@ class RolePlay(commands.Cog):
for high_phrase in high_iq_msgs:
msg1 += "+ {}\n".format(high_phrase)
high_pages = pagify(msg1) # pages is an iterator of pages
high_pages = pagify(msg1) # pages is an iterator of pages
for low_phrase in low_iq_msgs:
msg2 += "+ {}\n".format(low_phrase)
low_pages = pagify(msg2) # pages is an iterator of pages
low_pages = pagify(msg2) # pages is an iterator of pages
for high_page in high_pages:
await ctx.send(box(high_page, lang="diff"))
@ -255,7 +259,7 @@ class RolePlay(commands.Cog):
@iq.command(name="removehigh")
@checks.admin()
async def _removehigh_iq(self, ctx, high_phrase: str=""):
async def _removehigh_iq(self, ctx, high_phrase: str = ""):
"""Removes phrases for high IQ's!"""
guild = ctx.guild
high_iq_msgs = await self.config.guild(guild).high_iq_msgs()
@ -274,7 +278,7 @@ class RolePlay(commands.Cog):
@iq.command(name="removelow")
@checks.admin()
async def _removelow_iq(self, ctx, low_phrase: str=""):
async def _removelow_iq(self, ctx, low_phrase: str = ""):
"""Removes phrases for low IQ's!"""
guild = ctx.guild
low_iq_msgs = await self.config.guild(guild).low_iq_msgs()
@ -306,7 +310,7 @@ class RolePlay(commands.Cog):
largest_factor = 1
else:
largest_factor = [x for x in range(1, horses) if horses % x == 0][-1]
#largest_factor = [x for x in largest_factor if x <= 15][-1]
# largest_factor = [x for x in largest_factor if x <= 15][-1]
if largest_factor == 1:
largest_factor = horses
rows = 1
@ -367,7 +371,7 @@ class RolePlay(commands.Cog):
if user.id == ctx.bot.user.id:
await ctx.send(":newspaper2: :newspaper2: :newspaper2: " + italics(ctx.message.author.display_name))
else:
await ctx.send(":newspaper2: " + italics(user.display_name) )
await ctx.send(":newspaper2: " + italics(user.display_name))
@commands.command()
async def flip(self, ctx, *, user: discord.Member = None):