big 3.4 update part 1, still need to add data removal handling

This commit is contained in:
brandons209 2020-10-29 04:36:43 -04:00
parent 9146ce4efa
commit e9f7b86be9
48 changed files with 370 additions and 202 deletions

View file

@ -1,11 +1,12 @@
{ {
"author": ["Malarne (Malarne#1418)"], "author": ["Malarne (Malarne#1418)"],
"min_bot_version": "3.0.2", "min_bot_version": "3.4.0",
"description": "A leveler cog for Red V3\nInspired by Stevy's v2 leveler cog\nPlease consult the docs at ayrobot.netlify.com for setup informations.\nThanks for using my cog !\nNB:Channel whitelist is enabled by default, you can manage that under `[p]levelerset channel whitelist` command !", "description": "A leveler cog for Red V3\nInspired by Stevy's v2 leveler cog\nPlease consult the docs at ayrobot.netlify.com for setup informations.\nThanks for using my cog !\nNB:Channel whitelist is enabled by default, you can manage that under `[p]levelerset channel whitelist` command !",
"hidden": false, "hidden": false,
"install_msg": "Thank you for installing this leveler !\nPlease consult the docs at https://discord-cogs.readthedocs.io/en/latest/leveler.html for setup informations.\nPlease note that this cog come with bundled data, mostly the font for profile image.", "install_msg": "Thank you for installing this leveler !\nPlease consult the docs at https://discord-cogs.readthedocs.io/en/latest/leveler.html for setup informations.\nPlease note that this cog come with bundled data, mostly the font for profile image.",
"required_cogs": {}, "required_cogs": {},
"requirements": ["pillow"], "requirements": ["pillow"],
"short": "Leveler tool, better than MEE6", "short": "Leveler tool, better than MEE6",
"tags": ["leveler", "pillow", "fun"] "tags": ["leveler", "pillow", "fun"],
"end_user_data_statement": "Stores some level info like experience, profile description/picture, and message ID of user's last message in guild."
} }

View file

@ -287,6 +287,8 @@ class Leveler(commands.Cog):
await ctx.send(file=discord.File(img)) await ctx.send(file=discord.File(img))
async def listener(self, message): async def listener(self, message):
if await self.bot.cog_disabled_in_guild(self, message.guild):
return
if type(message.author) != discord.Member: if type(message.author) != discord.Member:
# throws an error when webhooks talk, this fixes it # throws an error when webhooks talk, this fixes it
return return
@ -330,7 +332,10 @@ class Leveler(commands.Cog):
await self.profiles._set_user_lastmessage(message.author, timenow) await self.profiles._set_user_lastmessage(message.author, timenow)
lvl = await self.profiles._get_level(message.author) lvl = await self.profiles._get_level(message.author)
if lvl == oldlvl + 1 and await self.profiles.data.guild(message.guild).lvlup_announce(): if lvl == oldlvl + 1 and await self.profiles.data.guild(message.guild).lvlup_announce():
await message.channel.send(_("{} is now level {} !".format(message.author.mention, lvl))) await message.channel.send(
_("{} is now level {} !".format(message.author.mention, lvl)),
allowed_mentions=discord.AllowedMentions.all(),
)
await self.profiles._check_exp(message.author) await self.profiles._check_exp(message.author)
await self.profiles._check_role_member(message.author) await self.profiles._check_role_member(message.author)
@ -644,5 +649,7 @@ class Leveler(commands.Cog):
# Listeners # Listeners
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_remove(self, member): async def on_member_remove(self, member):
if await self.bot.cog_disabled_in_guild(self, member.guild):
return
# reset level stats on leave. # reset level stats on leave.
await self.profiles.data.member(member).clear() await self.profiles.data.member(member).clear()

View file

@ -5,13 +5,14 @@ from redbot.core.data_manager import cog_data_path
from redbot.core.utils.mod import is_mod_or_superior from redbot.core.utils.mod import is_mod_or_superior
import discord import discord
from .time_utils import * from .utils import *
from datetime import datetime from datetime import datetime
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
import time import time
import os import os
import asyncio import asyncio
import glob import glob
import io
# plotting # plotting
from bisect import bisect_left from bisect import bisect_left
@ -46,66 +47,6 @@ DELETE_AUDIT_TEMPLATE = "@{0.name}#{0.discriminator}(id:{0.id}) deleted message
MAX_LINES = 50000 MAX_LINES = 50000
def get_all_names(guild_files, user):
names = [str(user)]
for log in guild_files:
if not os.path.exists(log):
continue
with open(log, "r") as f:
for line in f:
if str(user.id) in line:
# user change their name
if "Member username:" in line:
username = line.strip().split('"')
discrim = username[1].split("#")[-1]
username = username[-2] + "#" + discrim
names.append(username)
# user changed their 4 digit discriminator
elif "Member discriminator:" in line:
username = line.strip().split('"')[-2]
names.append(username)
# starting name
elif "Member join:" in line:
username = line.strip().split("@")[-1].split("#")
username = username[0] + "#" + username[1].split(" ")[0]
if username is not str(user):
names.append(username)
return set(names)
def format_list(*items, join="and", delim=", "):
if len(items) > 1:
return (" %s " % join).join((delim.join(items[:-1]), items[-1]))
elif items:
return items[0]
else:
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")
self.lock = asyncio.Lock()
if time:
self.time = time
else:
self.time = datetime.fromtimestamp(os.path.getmtime(path))
async def write(self, value):
async with self.lock:
self._write(value)
def close(self):
self.handle.close()
def _write(self, value):
self.time = datetime.utcnow()
self.handle.write(value)
class ActivityLogger(commands.Cog): class ActivityLogger(commands.Cog):
"""Log activity seen by bot""" """Log activity seen by bot"""
@ -259,7 +200,7 @@ class ActivityLogger(commands.Cog):
if is_mod: if is_mod:
try: try:
await ctx.send(embed=data) await ctx.send(embed=data, allowed_mentions=discord.AllowedMentions.all())
except discord.HTTPException: except discord.HTTPException:
await ctx.send("I need the `Embed links` permission to send this") await ctx.send("I need the `Embed links` permission to send this")
else: else:
@ -317,19 +258,10 @@ class ActivityLogger(commands.Cog):
) )
msg += f"Bans: `{bans}`, Kicks: `{kicks}`, Mutes: `{mutes}`, Warnings: `{warns}`" msg += f"Bans: `{bans}`, Kicks: `{kicks}`, Mutes: `{mutes}`, Warnings: `{warns}`"
if len(names) > 1: if len(names) > 1:
return msg, format_list(*names) return msg, humanize_list(names)
return msg, None return msg, None
@commands.command(name="fixavglen")
@checks.is_owner()
async def fixavglen(self, ctx):
for guild in self.bot.guilds:
for member in guild.members:
async with self.config.member(member).stats() as stats:
stats["avg_len"] = stats["total_msg"] - stats["bot_cmd"]
await ctx.tick()
@commands.command(name="graphstats") @commands.command(name="graphstats")
@checks.mod() @checks.mod()
@commands.guild_only() @commands.guild_only()
@ -1141,14 +1073,14 @@ class ActivityLogger(commands.Cog):
await self.config.guild(ctx.guild).prefixes.set([ctx.clean_prefix]) await self.config.guild(ctx.guild).prefixes.set([ctx.clean_prefix])
self.cache[ctx.guild.id]["prefixes"] = [ctx.clean_prefix] self.cache[ctx.guild.id]["prefixes"] = [ctx.clean_prefix]
return return
await ctx.send("Current Prefixes: " + format_list(*curr, delim=", ")) await ctx.send("Current Prefixes: " + humanize_list(curr))
return return
prefixes = [p for p in prefixes.split(" ")] prefixes = [p for p in prefixes.split(" ")]
await self.config.guild(ctx.guild).prefixes.set(prefixes) await self.config.guild(ctx.guild).prefixes.set(prefixes)
self.cache[ctx.guild.id]["prefixes"] = prefixes self.cache[ctx.guild.id]["prefixes"] = prefixes
prefixes = [f"`{p}`" for p in prefixes] prefixes = [f"`{p}`" for p in prefixes]
await ctx.send("Prefixes set to: " + format_list(*prefixes, delim=", ")) await ctx.send("Prefixes set to: " + humanize_list(prefixes))
@logset.command(name="rotation") @logset.command(name="rotation")
async def set_rotation(self, ctx, freq: str = None): async def set_rotation(self, ctx, freq: str = None):
@ -1434,16 +1366,22 @@ class ActivityLogger(commands.Cog):
# Listeners # Listeners
@commands.Cog.listener() @commands.Cog.listener()
async def on_message(self, message): async def on_message(self, message):
if await self.bot.cog_disabled_in_guild(self, message.guild):
return
await self.message_handler(message) await self.message_handler(message)
@commands.Cog.listener() @commands.Cog.listener()
async def on_message_edit(self, before, after): async def on_message_edit(self, before, after):
if await self.bot.cog_disabled_in_guild(self, after.guild):
return
timestamp = before.created_at.strftime(TIMESTAMP_FORMAT) timestamp = before.created_at.strftime(TIMESTAMP_FORMAT)
entry = EDIT_TEMPLATE.format(before, after, timestamp) entry = EDIT_TEMPLATE.format(before, after, timestamp)
await self.log(after.channel, entry, after.edited_at) await self.log(after.channel, entry, after.edited_at)
@commands.Cog.listener() @commands.Cog.listener()
async def on_message_delete(self, message): async def on_message_delete(self, message):
if await self.bot.cog_disabled_in_guild(self, message.guild):
return
entry_s = None entry_s = None
timestamp = message.created_at.strftime(TIMESTAMP_FORMAT) timestamp = message.created_at.strftime(TIMESTAMP_FORMAT)
try: try:
@ -1468,16 +1406,22 @@ class ActivityLogger(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_guild_join(self, guild): async def on_guild_join(self, guild):
if await self.bot.cog_disabled_in_guild(self, guild):
return
entry = "this bot joined the guild" entry = "this bot joined the guild"
await self.log(guild, entry) await self.log(guild, entry)
@commands.Cog.listener() @commands.Cog.listener()
async def on_guild_remove(self, guild): async def on_guild_remove(self, guild):
if await self.bot.cog_disabled_in_guild(self, guild):
return
entry = "this bot left the guild" entry = "this bot left the guild"
await self.log(guild, entry) await self.log(guild, entry)
@commands.Cog.listener() @commands.Cog.listener()
async def on_guild_update(self, before, after): async def on_guild_update(self, before, after):
if await self.bot.cog_disabled_in_guild(self, after):
return
entries = [] entries = []
user = None user = None
try: try:
@ -1535,6 +1479,8 @@ class ActivityLogger(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_guild_role_create(self, role): async def on_guild_role_create(self, role):
if await self.bot.cog_disabled_in_guild(self, role.guild):
return
user = None user = None
try: try:
async for entry in role.guild.audit_logs(limit=2): async for entry in role.guild.audit_logs(limit=2):
@ -1553,6 +1499,8 @@ class ActivityLogger(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_guild_role_delete(self, role): async def on_guild_role_delete(self, role):
if await self.bot.cog_disabled_in_guild(self, role.guild):
return
user = None user = None
try: try:
async for entry in role.guild.audit_logs(limit=2): async for entry in role.guild.audit_logs(limit=2):
@ -1571,6 +1519,8 @@ class ActivityLogger(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_guild_role_update(self, before, after): async def on_guild_role_update(self, before, after):
if await self.bot.cog_disabled_in_guild(self, after.guild):
return
entries = [] entries = []
user = None user = None
try: try:
@ -1655,6 +1605,8 @@ class ActivityLogger(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_join(self, member): async def on_member_join(self, member):
if await self.bot.cog_disabled_in_guild(self, member.guild):
return
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: async with self.config.user(member).past_names() as past_names:
@ -1665,6 +1617,8 @@ class ActivityLogger(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_remove(self, member): async def on_member_remove(self, member):
if await self.bot.cog_disabled_in_guild(self, member.guild):
return
user = None user = None
try: try:
async for entry in member.guild.audit_logs(limit=2): async for entry in member.guild.audit_logs(limit=2):
@ -1688,6 +1642,8 @@ class ActivityLogger(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_ban(self, guild, member): async def on_member_ban(self, guild, member):
if await self.bot.cog_disabled_in_guild(self, guild):
return
user = None user = None
try: try:
async for entry in guild.audit_logs(limit=2): async for entry in guild.audit_logs(limit=2):
@ -1706,6 +1662,8 @@ class ActivityLogger(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_unban(self, guild, member): async def on_member_unban(self, guild, member):
if await self.bot.cog_disabled_in_guild(self, guild):
return
user = None user = None
try: try:
async for entry in guild.audit_logs(limit=2): async for entry in guild.audit_logs(limit=2):
@ -1724,6 +1682,8 @@ class ActivityLogger(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_update(self, before, after): async def on_member_update(self, before, after):
if await self.bot.cog_disabled_in_guild(self, after.guild):
return
entries = [] entries = []
user = None user = None
try: try:
@ -1799,6 +1759,8 @@ class ActivityLogger(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_guild_channel_create(self, channel): async def on_guild_channel_create(self, channel):
if await self.bot.cog_disabled_in_guild(self, channel.guild):
return
user = None user = None
try: try:
async for entry in channel.guild.audit_logs(limit=2): async for entry in channel.guild.audit_logs(limit=2):
@ -1819,6 +1781,8 @@ class ActivityLogger(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_guild_channel_delete(self, channel): async def on_guild_channel_delete(self, channel):
if await self.bot.cog_disabled_in_guild(self, channel.guild):
return
user = None user = None
try: try:
async for entry in channel.guild.audit_logs(limit=2): async for entry in channel.guild.audit_logs(limit=2):
@ -1839,6 +1803,8 @@ class ActivityLogger(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_guild_channel_update(self, before, after): async def on_guild_channel_update(self, before, after):
if await self.bot.cog_disabled_in_guild(self, after.guild):
return
user = None user = None
try: try:
async for entry in after.guild.audit_logs(limit=2): async for entry in after.guild.audit_logs(limit=2):
@ -1900,6 +1866,8 @@ class ActivityLogger(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_voice_state_update(self, member, before, after): async def on_voice_state_update(self, member, before, after):
if await self.bot.cog_disabled_in_guild(self, member.guild):
return
if not self.should_log(before.channel): if not self.should_log(before.channel):
return return
@ -1958,3 +1926,19 @@ class ActivityLogger(commands.Cog):
if before.self_video != after.self_video: if before.self_video != after.self_video:
verb = "start-video" if after.self_video else "stop-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)) await self.log(before.channel, "guild self-{0}: {1} (id {1.id})".format(verb, member))
# async def red_get_data_for_user(self, user_id: int):
# 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}
# }
# past_names = await self.config.user_from_id(user_id).past_names()
# data = {"past_names": past_names}
# for guild in self.bot.guilds:
# member = guild.get_member(user_id)
# if member:
# data[guild.name] = await self.config.member(member).stats()
async def red_delete_data_for_user(self, requester: str, user_id: int):
pass

View file

@ -3,11 +3,6 @@
"Brandons209", "Brandons209",
"calebj" "calebj"
], ],
"bot_version": [
3,
0,
0
],
"description": "Log messages, dms, attachments, guild updates (roles, channels, bans, kicks etc) and be able to retrieve these logs for review. Saves these right to disk and customize then to rotate log files. Tracks user's stats; how many messages they send, how many are bot commands, time spent in VC, and moderator actions against them. Also provides an upgraded userinfo command that gives these stats alongside the information Red's userinfo command gives. This is rewritten from @calebj's V2 cog.", "description": "Log messages, dms, attachments, guild updates (roles, channels, bans, kicks etc) and be able to retrieve these logs for review. Saves these right to disk and customize then to rotate log files. Tracks user's stats; how many messages they send, how many are bot commands, time spent in VC, and moderator actions against them. Also provides an upgraded userinfo command that gives these stats alongside the information Red's userinfo command gives. This is rewritten from @calebj's V2 cog.",
"hidden": false, "hidden": false,
"install_msg": "Thank you for using this cog! Make sure to set bot prefixes using [p]logset prefixes for proper stat logging.", "install_msg": "Thank you for using this cog! Make sure to set bot prefixes using [p]logset prefixes for proper stat logging.",
@ -19,5 +14,6 @@
"log", "log",
"activity" "activity"
], ],
"min_bot_version": "3.3.0" "min_bot_version": "3.4.0",
"end_user_data_statement": "Depending on setup, can log user messages, voice channel activity, audit actions in guilds, activity statistics per guild, user name changes, and any moderation actions per guild."
} }

View file

@ -1,59 +0,0 @@
# thanks to @Sinbad for time parsing!
from __future__ import annotations
import re
from datetime import datetime as dt
from typing import Optional
import pytz
from dateutil import parser
from dateutil.tz import gettz
from dateutil.relativedelta import relativedelta
TIME_RE_STRING = r"\s?".join(
[
r"((?P<years>\d+?)\s?(years?|y))?",
r"((?P<months>\d+?)\s?(months?|mt))?",
r"((?P<weeks>\d+?)\s?(weeks?|w))?",
r"((?P<days>\d+?)\s?(days?|d))?",
r"((?P<hours>\d+?)\s?(hours?|hrs|hr?))?",
r"((?P<minutes>\d+?)\s?(minutes?|mins?|m(?!o)))?", # prevent matching "months"
r"((?P<seconds>\d+?)\s?(seconds?|secs?|s))?",
]
)
TIME_RE = re.compile(TIME_RE_STRING, re.I)
def gen_tzinfos():
for zone in pytz.common_timezones:
try:
tzdate = pytz.timezone(zone).localize(dt.utcnow(), is_dst=None)
except pytz.NonExistentTimeError:
pass
else:
tzinfo = gettz(zone)
if tzinfo:
yield tzdate.tzname(), tzinfo
def parse_time(datetimestring: str):
tzinfo = dict(gen_tzinfos())
ret = parser.parse(datetimestring, tzinfos=tzinfo)
if ret.tzinfo is not None:
ret = ret.astimezone(pytz.utc)
return ret
def parse_time_naive(datetimestring: str):
return parser.parse(datetimestring)
def parse_timedelta(argument: str) -> Optional[relativedelta]:
matches = TIME_RE.match(argument)
if matches:
params = {k: int(v) for k, v in matches.groupdict().items() if v}
if params:
return relativedelta(**params)
return None

112
activitylog/utils.py Normal file
View file

@ -0,0 +1,112 @@
# thanks to @Sinbad for time parsing!
from __future__ import annotations
import re
from datetime import datetime as dt
from typing import Optional
import os
import asyncio
import pytz
from dateutil import parser
from dateutil.tz import gettz
from dateutil.relativedelta import relativedelta
TIME_RE_STRING = r"\s?".join(
[
r"((?P<years>\d+?)\s?(years?|y))?",
r"((?P<months>\d+?)\s?(months?|mt))?",
r"((?P<weeks>\d+?)\s?(weeks?|w))?",
r"((?P<days>\d+?)\s?(days?|d))?",
r"((?P<hours>\d+?)\s?(hours?|hrs|hr?))?",
r"((?P<minutes>\d+?)\s?(minutes?|mins?|m(?!o)))?", # prevent matching "months"
r"((?P<seconds>\d+?)\s?(seconds?|secs?|s))?",
]
)
TIME_RE = re.compile(TIME_RE_STRING, re.I)
def gen_tzinfos():
for zone in pytz.common_timezones:
try:
tzdate = pytz.timezone(zone).localize(dt.utcnow(), is_dst=None)
except pytz.NonExistentTimeError:
pass
else:
tzinfo = gettz(zone)
if tzinfo:
yield tzdate.tzname(), tzinfo
def parse_time(datetimestring: str):
tzinfo = dict(gen_tzinfos())
ret = parser.parse(datetimestring, tzinfos=tzinfo)
if ret.tzinfo is not None:
ret = ret.astimezone(pytz.utc)
return ret
def parse_time_naive(datetimestring: str):
return parser.parse(datetimestring)
def parse_timedelta(argument: str) -> Optional[relativedelta]:
matches = TIME_RE.match(argument)
if matches:
params = {k: int(v) for k, v in matches.groupdict().items() if v}
if params:
return relativedelta(**params)
return None
def get_all_names(guild_files, user):
names = [str(user)]
for log in guild_files:
if not os.path.exists(log):
continue
with open(log, "r") as f:
for line in f:
if str(user.id) in line:
# user change their name
if "Member username:" in line:
username = line.strip().split('"')
discrim = username[1].split("#")[-1]
username = username[-2] + "#" + discrim
names.append(username)
# user changed their 4 digit discriminator
elif "Member discriminator:" in line:
username = line.strip().split('"')[-2]
names.append(username)
# starting name
elif "Member join:" in line:
username = line.strip().split("@")[-1].split("#")
username = username[0] + "#" + username[1].split(" ")[0]
if username is not str(user):
names.append(username)
return set(names)
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")
self.lock = asyncio.Lock()
if time:
self.time = time
else:
self.time = dt.fromtimestamp(os.path.getmtime(path))
async def write(self, value):
async with self.lock:
self._write(value)
def close(self):
self.handle.close()
def _write(self, value):
self.time = dt.utcnow()
self.handle.write(value)

View file

@ -63,6 +63,8 @@ class Birthday(commands.Cog):
async def check_bdays(self): async def check_bdays(self):
for guild in self.bot.guilds: for guild in self.bot.guilds:
if await self.bot.cog_disabled_in_guild(self, guild):
continue
for member in guild.members: for member in guild.members:
await self.check_member_bday(member) await self.check_member_bday(member)
@ -97,7 +99,7 @@ class Birthday(commands.Cog):
else: else:
embed.description = f"Happy Birthday to {member.mention}!" embed.description = f"Happy Birthday to {member.mention}!"
try: try:
await channel.send(embed=embed) await channel.send(embed=embed, allow_mentions=True)
except: except:
pass pass

View file

@ -6,7 +6,7 @@
], ],
"bot_version": [ "bot_version": [
3, 3,
0, 4,
0 0
], ],
"description": "Cog used for setting birthdays and announcing them and giving people roles on their birthday", "description": "Cog used for setting birthdays and announcing them and giving people roles on their birthday",
@ -17,5 +17,6 @@
"tags": [ "tags": [
"brandons209", "brandons209",
"pancakesparkle" "pancakesparkle"
] ],
"end_user_data_statement": "This cog will store a user's birthday."
} }

View file

@ -1,9 +1,10 @@
{ {
"author" : ["Brandons209", "Jinatku"], "author" : ["Brandons209", "Jinatku"],
"bot_version": [3,0,0], "bot_version": [3,4,0],
"install_msg" : "Let your users confess their terrible terrible crimes in secrecy!", "install_msg" : "Let your users confess their terrible terrible crimes in secrecy!",
"short" : "Confess secretly.", "short" : "Confess secretly.",
"description" : "Confess in a confession room to repent your crimes.", "description" : "Confess in a confession room to repent your crimes.",
"tags" : ["confession", "crime", "secret"], "tags" : ["confession", "crime", "secret"],
"hidden" : false "hidden" : false,
"end_user_data_statement": "This cog won't store anything for a user."
} }

View file

@ -4,7 +4,7 @@
], ],
"bot_version": [ "bot_version": [
3, 3,
0, 4,
0 0
], ],
"description": "Allow setting up costs for any commands of your bot, with user, and role hierarchy. Also allows setting roles who do not have to pay for commands. Has receptions DMed and updated to allow users to track their spending.", "description": "Allow setting up costs for any commands of your bot, with user, and role hierarchy. Also allows setting roles who do not have to pay for commands. Has receptions DMed and updated to allow users to track their spending.",
@ -15,5 +15,6 @@
"tags": [ "tags": [
"brandons209", "brandons209",
"redbot" "redbot"
] ],
"end_user_data_statement": "This cog won't store anything for a user."
} }

View file

@ -126,7 +126,8 @@ class CostManager(commands.Cog):
except: except:
if receipt != -1: # send mention if first time getting this message if receipt != -1: # send mention if first time getting this message
await ctx.send( await ctx.send(
f"Hey {member.mention}, please turn on DMs from server members in your settings so I can send you receipts for purchase of commands." f"Hey {member.mention}, please turn on DMs from server members in your settings so I can send you receipts for purchase of commands.",
allowed_mentions=discord.AllowedMentions.all(),
) )
await self.config.member(member).receipt.set(-1) await self.config.member(member).receipt.set(-1)
@ -400,7 +401,8 @@ class CostManager(commands.Cog):
currency_name = await bank.get_currency_name(ctx.guild) currency_name = await bank.get_currency_name(ctx.guild)
balance = await bank.get_balance(ctx.author) balance = await bank.get_balance(ctx.author)
message = await ctx.send( message = await ctx.send(
f"Sorry {ctx.author.name}, you do not have enough {currency_name} to use that command. (Cost: {cost}, Balance: {balance})" f"Sorry {ctx.author.name}, you do not have enough {currency_name} to use that command. (Cost: {cost}, Balance: {balance})",
allowed_mentions=discord.AllowedMentions.all(),
) )
await asyncio.sleep(10) await asyncio.sleep(10)
await message.delete() await message.delete()

View file

@ -70,6 +70,8 @@ class Disable(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_command_error(self, ctx, exception): async def on_command_error(self, ctx, exception):
if await self.bot.cog_disabled_in_guild(self, ctx.guild):
return
if isinstance(exception, DisabledError): if isinstance(exception, DisabledError):
msg = await self.config.guild(ctx.guild).disabled_message() msg = await self.config.guild(ctx.guild).disabled_message()
await ctx.send(msg.format(ctx.command.name)) await ctx.send(msg.format(ctx.command.name))

View file

@ -4,7 +4,7 @@
], ],
"bot_version": [ "bot_version": [
3, 3,
3, 4,
0 0
], ],
"description": "Small cog that allows disabling all bot commands for everyone except Admins/owner in a guild. Nice for things like bot setup. You can also set the error message when a person trys using a command when its disabled.", "description": "Small cog that allows disabling all bot commands for everyone except Admins/owner in a guild. Nice for things like bot setup. You can also set the error message when a person trys using a command when its disabled.",
@ -15,5 +15,6 @@
"tags": [ "tags": [
"brandons209", "brandons209",
"redbot" "redbot"
] ],
"end_user_data_statement": "This cog won't store any data for users."
} }

View file

@ -49,6 +49,8 @@ class EconomyTrickle(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_message(self, message): async def on_message(self, message):
if await self.bot.cog_disabled_in_guild(self, message.guild):
return
if message.guild and await self.config.guild(message.guild).active(): if message.guild and await self.config.guild(message.guild).active():
self.recordhandler.proccess_message(message) self.recordhandler.proccess_message(message)

View file

@ -10,5 +10,6 @@
"short": "Trickle money into user's account on activity.", "short": "Trickle money into user's account on activity.",
"description": "Trickle money into user's account on activity, modified by Brandons209 from Sinbad.", "description": "Trickle money into user's account on activity, modified by Brandons209 from Sinbad.",
"hidden": false, "hidden": false,
"min_bot_version": "3.1.8" "min_bot_version": "3.4.0",
"end_user_data_statement": "This cog only stores internal variables per user."
} }

View file

@ -6,5 +6,7 @@
"INSTALL_MSG" : "Thanks for installing EveryoneEmoji.", "INSTALL_MSG" : "Thanks for installing EveryoneEmoji.",
"REQUIREMENTS" : [], "REQUIREMENTS" : [],
"TAGS" : ["emoji", "EveryoneEmoji", "everyone"], "TAGS" : ["emoji", "EveryoneEmoji", "everyone"],
"DISABLED" : false "DISABLED" : false,
"min_bot_version": "3.4.0",
"end_user_data_statement": "This cog stores no data."
} }

View file

@ -5,7 +5,7 @@
], ],
"bot_version": [ "bot_version": [
3, 3,
0, 4,
0 0
], ],
"description": "Provides a way to quickly remove a user for all chats and isolate them to a single channel. Supports setting times, automatic removal of isolate, modlog integration, custom role overrides, automatic server setup, and a lot more. This is different from punish as it always remove all a user's roles and by default makes the user not read all channels.", "description": "Provides a way to quickly remove a user for all chats and isolate them to a single channel. Supports setting times, automatic removal of isolate, modlog integration, custom role overrides, automatic server setup, and a lot more. This is different from punish as it always remove all a user's roles and by default makes the user not read all channels.",
@ -16,5 +16,6 @@
"tags": [ "tags": [
"brandons209", "brandons209",
"isolate" "isolate"
] ],
"end_user_data_statement": "This cog stores members who are currently isolated for moderation purposes."
} }

View file

@ -1306,6 +1306,8 @@ class Isolate(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_guild_channel_create(self, channel): async def on_guild_channel_create(self, channel):
"""Run when new channels are created and set up role permissions""" """Run when new channels are created and set up role permissions"""
if await self.bot.cog_disabled_in_guild(self, channel.guild):
return
role = await self.get_role(channel.guild, quiet=True) role = await self.get_role(channel.guild, quiet=True)
if not role: if not role:
return return
@ -1315,6 +1317,8 @@ class Isolate(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_update(self, before, after): async def on_member_update(self, before, after):
"""Remove scheduled unisolate when manually removed role""" """Remove scheduled unisolate when manually removed role"""
if await self.bot.cog_disabled_in_guild(self, after.guild):
return
try: try:
assert before.roles != after.roles assert before.roles != after.roles
guild_data = await self.config.guild(before.guild).ISOLATED() guild_data = await self.config.guild(before.guild).ISOLATED()
@ -1343,6 +1347,8 @@ class Isolate(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_join(self, member): async def on_member_join(self, member):
"""Restore Isolation if isolated user leaves/rejoins""" """Restore Isolation if isolated user leaves/rejoins"""
if await self.bot.cog_disabled_in_guild(self, member.guild):
return
guild = member.guild guild = member.guild
isolated = await self.config.guild(guild).ISOLATED() isolated = await self.config.guild(guild).ISOLATED()
data = isolated.get(str(member.id), {}) data = isolated.get(str(member.id), {})
@ -1366,6 +1372,8 @@ class Isolate(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_voice_state_update(self, member, before, after): async def on_voice_state_update(self, member, before, after):
if await self.bot.cog_disabled_in_guild(self, after.guild):
return
if not after.channel: if not after.channel:
return return
@ -1386,6 +1394,8 @@ class Isolate(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_ban(self, member): async def on_member_ban(self, member):
"""Remove Isolation record when member is banned.""" """Remove Isolation record when member is banned."""
if await self.bot.cog_disabled_in_guild(self, member.guild):
return
guild = member.guild guild = member.guild
data = await self.config.guild(guild).ISOLATED() data = await self.config.guild(guild).ISOLATED()
member_data = data.get(str(member.id)) member_data = data.get(str(member.id))

View file

@ -145,9 +145,9 @@ def role_from_string(guild, rolename, roles=None):
if role: if role:
return role return role
else:
rolename = rolename.lower() rolename = rolename.lower()
role = discord.utils.find(lambda r: r.name.lower() == rolename, roles) role = discord.utils.find(lambda r: r.name.lower() == rolename, roles)
return role return role

View file

@ -4,7 +4,7 @@
], ],
"bot_version": [ "bot_version": [
3, 3,
0, 4,
0 0
], ],
"description": "Uses markov chains to generate unique text in your guild! Text generated is based on what users say per channel. The markov model can be reset if needed as well per channel.", "description": "Uses markov chains to generate unique text in your guild! Text generated is based on what users say per channel. The markov model can be reset if needed as well per channel.",
@ -18,5 +18,6 @@
"markov", "markov",
"generaton", "generaton",
"markov chain" "markov chain"
] ],
"end_user_data_statement": "This doesn't store any user data."
} }

View file

@ -159,11 +159,13 @@ class Markov(commands.Cog):
embed.set_thumbnail(url=avatar) embed.set_thumbnail(url=avatar)
embed.set_footer(text=f"Generated by {member.display_name}") embed.set_footer(text=f"Generated by {member.display_name}")
await ctx.send(embed=embed) await ctx.send(embed=embed, allowed_mentions=discord.AllowedMentions.all())
# Listener # Listener
@commands.Cog.listener() @commands.Cog.listener()
async def on_message(self, message): async def on_message(self, message):
if await self.bot.cog_disabled_in_guild(self, message.guild):
return
# updates model # updates model
content = message.content content = message.content
guild = message.guild guild = message.guild

View file

@ -4,7 +4,7 @@
], ],
"bot_version": [ "bot_version": [
3, 3,
0, 4,
0 0
], ],
"description": "More admin commands like purging inactive users, member count display for channel name, add roles based on author's current roles, log new user accounts joining, and more!", "description": "More admin commands like purging inactive users, member count display for channel name, add roles based on author's current roles, log new user accounts joining, and more!",
@ -15,5 +15,6 @@
"tags": [ "tags": [
"brandons209", "brandons209",
"redbot" "redbot"
] ],
"end_user_data_statement": "This will store a user's last few messages (depending on configuration)"
} }

View file

@ -170,6 +170,8 @@ class MoreAdmin(commands.Cog):
SLEEP_TIME = 300 SLEEP_TIME = 300
while True: while True:
for guild in self.bot.guilds: for guild in self.bot.guilds:
if await self.bot.cog_disabled_in_guild(self, guild):
continue
channel = await self.config.guild(guild).user_count_channel() channel = await self.config.guild(guild).user_count_channel()
if channel: if channel:
channel = guild.get_channel(channel) channel = guild.get_channel(channel)
@ -799,13 +801,13 @@ class MoreAdmin(commands.Cog):
@commands.command(hidden=True) @commands.command(hidden=True)
@commands.guild_only() @commands.guild_only()
async def say(self, ctx, *, content: str): async def say(self, ctx, *, content: str):
await ctx.send(escape(content, mass_mentions=True), allowed_mentions=discord.AllowedMentions()) await ctx.send(escape(content, mass_mentions=True), allowed_mentions=discord.AllowedMentions.all())
@commands.command(hidden=True) @commands.command(hidden=True)
@commands.guild_only() @commands.guild_only()
async def selfdm(self, ctx, *, content: str): async def selfdm(self, ctx, *, content: str):
try: try:
await ctx.author.send(content) await ctx.author.send(content, allowed_mentions=discord.AllowedMentions.all())
except: except:
await ctx.send( await ctx.send(
"I couldn't send you the DM, make sure to turn on messages from server members! Here is the message:" "I couldn't send you the DM, make sure to turn on messages from server members! Here is the message:"
@ -827,7 +829,7 @@ class MoreAdmin(commands.Cog):
return return
try: try:
await message.edit(content=msg) await message.edit(content=msg, allowed_mentions=discord.AllowedMentions.all())
except: except:
await ctx.send("Could not edit message.") await ctx.send("Could not edit message.")
@ -839,7 +841,7 @@ class MoreAdmin(commands.Cog):
Sends a message to a channel from Aurelia. Sends a message to a channel from Aurelia.
""" """
try: try:
await channel.send(msg) # , allowed_mentions=discord.AllowedMentions()) await channel.send(msg, allowed_mentions=discord.AllowedMentions.all())
except: except:
await ctx.send("Could not send message in that channel.") await ctx.send("Could not send message in that channel.")
@ -974,6 +976,10 @@ class MoreAdmin(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_join(self, member): async def on_member_join(self, member):
if await self.bot.cog_disabled_in_guild(self, member.guild):
return
if await self.bot.cog_disabled_in_guild(self, member.guild):
return
sus_threshold = await self.config.guild(member.guild).sus_user_threshold() sus_threshold = await self.config.guild(member.guild).sus_user_threshold()
if not sus_threshold: if not sus_threshold:
return return
@ -1003,6 +1009,8 @@ class MoreAdmin(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_message(self, message): async def on_message(self, message):
if await self.bot.cog_disabled_in_guild(self, message.guild):
return
# Set user's last message # Set user's last message
if not message.guild: if not message.guild:
return return

View file

@ -4,7 +4,7 @@
], ],
"bot_version": [ "bot_version": [
3, 3,
3, 4,
0 0
], ],
"description": "Allow nitro boosters to add an emoji to the server, with channel logging.", "description": "Allow nitro boosters to add an emoji to the server, with channel logging.",
@ -17,5 +17,6 @@
"nitro", "nitro",
"boost", "boost",
"emoji" "emoji"
] ],
"end_user_data_statement": "This cog will store a user's custom emojis in each guild."
} }

View file

@ -285,6 +285,8 @@ class NitroEmoji(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_update(self, before, after): async def on_member_update(self, before, after):
if await self.bot.cog_disabled_in_guild(self, after.guild):
return
# check if they stopped boosting # check if they stopped boosting
if (before.premium_since != after.premium_since and after.premium_since is None) or before.roles != after.roles: if (before.premium_since != after.premium_since and after.premium_since is None) or before.roles != after.roles:
boosts = await self.get_boosts(after) boosts = await self.get_boosts(after)
@ -312,6 +314,8 @@ class NitroEmoji(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_leave(self, member): async def on_member_leave(self, member):
if await self.bot.cog_disabled_in_guild(self, member.guild):
return
# remove all member emojis on leave # remove all member emojis on leave
emojis = await self.config.member(member).emojis() emojis = await self.config.member(member).emojis()
for emoji in emojis: for emoji in emojis:
@ -324,6 +328,8 @@ class NitroEmoji(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_guild_emojis_update(self, guild, before, after): async def on_guild_emojis_update(self, guild, before, after):
if await self.bot.cog_disabled_in_guild(self, guild):
return
b_e = set(before) b_e = set(before)
a_e = set(after) a_e = set(after)
diff = b_e - a_e diff = b_e - a_e

View file

@ -14,5 +14,7 @@
], ],
"requirements": [ "requirements": [
"tabulate" "tabulate"
] ],
"min_bot_version": "3.4.0",
"end_user_data_statement": "This will store what a user's custom role is if they have one."
} }

View file

@ -370,6 +370,8 @@ class PersonalRoles(commands.Cog):
@commands.Cog.listener("on_member_join") @commands.Cog.listener("on_member_join")
async def role_persistance(self, member): async def role_persistance(self, member):
"""Automatically give already assigned roles on join""" """Automatically give already assigned roles on join"""
if await self.bot.cog_disabled_in_guild(self, member.guild):
return
role = await self.config.member(member).role() role = await self.config.member(member).role()
if role: if role:
role = member.guild.get_role(role) role = member.guild.get_role(role)
@ -382,6 +384,8 @@ class PersonalRoles(commands.Cog):
@commands.Cog.listener("on_member_remove") @commands.Cog.listener("on_member_remove")
async def remove_role(self, member): async def remove_role(self, member):
""" Delete personal role if member leaves.""" """ Delete personal role if member leaves."""
if await self.bot.cog_disabled_in_guild(self, member.guild):
return
role = await self.config.member(member).role() role = await self.config.member(member).role()
auto = await self.config.member(member).auto_role() auto = await self.config.member(member).auto_role()
role = member.guild.get_role(role) role = member.guild.get_role(role)
@ -396,6 +400,8 @@ class PersonalRoles(commands.Cog):
@commands.Cog.listener("on_member_update") @commands.Cog.listener("on_member_update")
async def modify_roles(self, before, after): async def modify_roles(self, before, after):
""" Delete personal role if member looses their auto role or looses their personal role """ """ Delete personal role if member looses their auto role or looses their personal role """
if await self.bot.cog_disabled_in_guild(self, after.guild):
return
role = await self.config.member(after).role() role = await self.config.member(after).role()
role = before.guild.get_role(role) role = before.guild.get_role(role)
if not role: if not role:

View file

@ -6,7 +6,7 @@
], ],
"bot_version": [ "bot_version": [
3, 3,
0, 4,
0 0
], ],
"description": "Search derpibooru for images of ponies! Fully customizable filter list!", "description": "Search derpibooru for images of ponies! Fully customizable filter list!",
@ -20,5 +20,6 @@
"pony", "pony",
"mlp", "mlp",
"image" "image"
] ],
"end_user_data_statement": "This doesn't store any data."
} }

View file

@ -5,7 +5,7 @@
], ],
"bot_version": [ "bot_version": [
3, 3,
0, 4,
0 0
], ],
"description": "Provides a way to quickly remove a user for all chats and isolate them to a single channel. Supports setting times, automatic removal of punish, modlog integration, removing roles so that role overrides work, custom role overrides, automatic server setup, and a lot more.", "description": "Provides a way to quickly remove a user for all chats and isolate them to a single channel. Supports setting times, automatic removal of punish, modlog integration, removing roles so that role overrides work, custom role overrides, automatic server setup, and a lot more.",
@ -16,5 +16,6 @@
"tags": [ "tags": [
"brandons209", "brandons209",
"punish" "punish"
] ],
"end_user_data_statement": "This will store who is currently punished."
} }

View file

@ -18,7 +18,7 @@ import textwrap
log = logging.getLogger("red.punish") log = logging.getLogger("red.punish")
__version__ = "3.0.0" __version__ = "3.3.0"
PURGE_MESSAGES = 1 # for cpunish PURGE_MESSAGES = 1 # for cpunish
@ -1373,6 +1373,8 @@ class Punish(commands.Cog):
# Listeners # Listeners
@commands.Cog.listener() @commands.Cog.listener()
async def on_guild_channel_create(self, channel): async def on_guild_channel_create(self, channel):
if await self.bot.cog_disabled_in_guild(self, channel.guild):
return
"""Run when new channels are created and set up role permissions""" """Run when new channels are created and set up role permissions"""
role = await self.get_role(channel.guild, quiet=True) role = await self.get_role(channel.guild, quiet=True)
if not role: if not role:
@ -1383,6 +1385,8 @@ class Punish(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_update(self, before, after): async def on_member_update(self, before, after):
"""Remove scheduled unpunish when manually removed role""" """Remove scheduled unpunish when manually removed role"""
if await self.bot.cog_disabled_in_guild(self, after.guild):
return
try: try:
assert before.roles != after.roles assert before.roles != after.roles
guild_data = await self.config.guild(before.guild).PUNISHED() guild_data = await self.config.guild(before.guild).PUNISHED()
@ -1411,6 +1415,8 @@ class Punish(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_join(self, member): async def on_member_join(self, member):
"""Restore punishment if punished user leaves/rejoins""" """Restore punishment if punished user leaves/rejoins"""
if await self.bot.cog_disabled_in_guild(self, member.guild):
return
guild = member.guild guild = member.guild
punished = await self.config.guild(guild).PUNISHED() punished = await self.config.guild(guild).PUNISHED()
data = punished.get(str(member.id), {}) data = punished.get(str(member.id), {})
@ -1434,6 +1440,8 @@ class Punish(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_voice_state_update(self, member, before, after): async def on_voice_state_update(self, member, before, after):
if await self.bot.cog_disabled_in_guild(self, after.guild):
return
if not after.channel: if not after.channel:
return return
@ -1454,6 +1462,8 @@ class Punish(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_ban(self, member): async def on_member_ban(self, member):
"""Remove punishment record when member is banned.""" """Remove punishment record when member is banned."""
if await self.bot.cog_disabled_in_guild(self, member.guild):
return
guild = member.guild guild = member.guild
data = await self.config.guild(guild).PUNISHED() data = await self.config.guild(guild).PUNISHED()
member_data = data.get(str(member.id)) member_data = data.get(str(member.id))

View file

@ -145,9 +145,9 @@ def role_from_string(guild, rolename, roles=None):
if role: if role:
return role return role
else:
rolename = rolename.lower() rolename = rolename.lower()
role = discord.utils.find(lambda r: r.name.lower() == rolename, roles) role = discord.utils.find(lambda r: r.name.lower() == rolename, roles)
return role return role

View file

@ -6,5 +6,7 @@
"INSTALL_MSG" : "Thanks for installing ReactPoll. Please make sure your bot has the 'Manage Messages' permission so it can manage emoji reactions on messages.", "INSTALL_MSG" : "Thanks for installing ReactPoll. Please make sure your bot has the 'Manage Messages' permission so it can manage emoji reactions on messages.",
"REQUIREMENTS" : ["python-dateutil", "pytz"], "REQUIREMENTS" : ["python-dateutil", "pytz"],
"TAGS" : ["poll", "reaction", "emoji", "react"], "TAGS" : ["poll", "reaction", "emoji", "react"],
"DISABLED" : false "DISABLED" : false,
"min_bot_version": "3.4.0",
"end_user_data_statement": "This cog won't store user data."
} }

View file

@ -135,6 +135,10 @@ class ReactPoll(commands.Cog):
guild = self.bot.get_guild(payload.guild_id) guild = self.bot.get_guild(payload.guild_id)
if not guild: if not guild:
return return
if await self.bot.cog_disabled_in_guild(self, guild):
return
user = guild.get_member(payload.user_id) user = guild.get_member(payload.user_id)
message = await self.bot.get_channel(payload.channel_id).fetch_message(payload.message_id) message = await self.bot.get_channel(payload.channel_id).fetch_message(payload.message_id)
# Listener is required to remove bad reactions # Listener is required to remove bad reactions

View file

@ -43,6 +43,8 @@ class EventMixin(MixinMeta):
Section has been optimized assuming member._roles Section has been optimized assuming member._roles
remains an iterable containing snowflakes remains an iterable containing snowflakes
""" """
if await self.bot.cog_disabled_in_guild(self, after.guild):
return
await self.wait_for_ready() await self.wait_for_ready()
if before._roles == after._roles: if before._roles == after._roles:
return return
@ -85,6 +87,8 @@ class EventMixin(MixinMeta):
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_join(self, member: discord.Member): async def on_member_join(self, member: discord.Member):
await self.wait_for_ready() await self.wait_for_ready()
if await self.bot.cog_disabled_in_guild(self, member.guild):
return
guild = member.guild guild = member.guild
if not guild.me.guild_permissions.manage_roles: if not guild.me.guild_permissions.manage_roles:
return return
@ -134,6 +138,9 @@ class EventMixin(MixinMeta):
await self.maybe_update_guilds(guild) await self.maybe_update_guilds(guild)
else: else:
return return
if await self.bot.cog_disabled_in_guild(self, guild):
return
member = guild.get_member(payload.user_id) member = guild.get_member(payload.user_id)
if member is None or member.bot: if member is None or member.bot:
@ -182,6 +189,8 @@ class EventMixin(MixinMeta):
if not guild: if not guild:
# Where's it go? # Where's it go?
return return
if await self.bot.cog_disabled_in_guild(self, guild):
return
member = guild.get_member(payload.user_id) member = guild.get_member(payload.user_id)
if not member or member.bot: if not member or member.bot:
return return

View file

@ -17,5 +17,6 @@
"massrole" "massrole"
], ],
"hidden": false, "hidden": false,
"min_bot_version": "3.2.0a0.dev1" "min_bot_version": "3.4.0",
"end_user_data_statement": "This will only store sticky roles for users."
} }

View file

@ -206,7 +206,11 @@ class MassManagementMixin(MixinMeta):
embed = discord.Embed(description=description) embed = discord.Embed(description=description)
if ctx.guild: if ctx.guild:
embed.color = ctx.guild.me.color embed.color = ctx.guild.me.color
await ctx.send(embed=embed, content=f"Search results for {ctx.author.mention}") await ctx.send(
embed=embed,
content=f"Search results for {ctx.author.mention}",
allowed_mentions=discord.AllowedMentions.all(),
)
else: else:
await self.send_maybe_chunked_csv(ctx, list(members)) await self.send_maybe_chunked_csv(ctx, list(members))
@ -251,6 +255,7 @@ class MassManagementMixin(MixinMeta):
await ctx.send( await ctx.send(
content=f"Data for {ctx.author.mention}", content=f"Data for {ctx.author.mention}",
files=[discord.File(data, filename=filename)], files=[discord.File(data, filename=filename)],
allowed_mentions=discord.AllowedMentions.all(),
) )
csvf.close() csvf.close()
data.close() data.close()

19
roleplay/info.json Normal file
View file

@ -0,0 +1,19 @@
{
"author": [
"TheBluekr"
],
"bot_version": [
3,
4,
0
],
"description": "Roleplay commands for booping, hugging, etc.",
"hidden": false,
"install_msg": "Thanks for using my cog!",
"requirements": [],
"tags": [
"brandons209",
"Som3thing"
],
"end_user_data_statement": "No data is stored."
}

View file

@ -4,16 +4,16 @@
], ],
"bot_version": [ "bot_version": [
3, 3,
0, 4,
0 0
], ],
"description": "", "description": "Tracks specified roles on when they are added, removed, and who updates them.",
"hidden": false, "hidden": false,
"install_msg": "", "install_msg": "Thank you for using my cog!",
"requirements": [], "requirements": [],
"short": "",
"tags": [ "tags": [
"brandons209", "brandons209",
"pancakesparkle" "pancakesparkle"
] ],
} "end_user_data_statement": "Depending on setup, can log user messages, voice channel activity, audit actions in guilds, activity statistics per guild, user name changes, and any moderation actions per guild."
}

View file

@ -200,6 +200,8 @@ class RoleTracker(commands.Cog):
""" """
Listens for role updates and more Listens for role updates and more
""" """
if await self.bot.cog_disabled_in_guild(self, after.guild):
return
if before.roles != after.roles: if before.roles != after.roles:
user = self.bot.user user = self.bot.user

View file

@ -5,9 +5,10 @@
"install_msg": "Thanks for install.", "install_msg": "Thanks for install.",
"short": "Quickly list server and channel rules.", "short": "Quickly list server and channel rules.",
"description": "Quickly list server and channel rules.", "description": "Quickly list server and channel rules.",
"min_bot_version": "3.2.1", "min_bot_version": "3.4.0",
"tags": [ "tags": [
"rules", "rules",
"rule" "rule"
] ],
"end_user_data_statement": "This only stores rules added by admins of guilds."
} }

View file

@ -16,6 +16,6 @@
"python-dateutil", "python-dateutil",
"pytz" "pytz"
], ],
"min_bot_version": "3.3.0", "min_bot_version": "3.4.0",
"end_user_data_statement": "This cog does not persistently store data or metadata about users. It does store commands provided for intended later use along with the user ID of the person who scheduled it.\nUsers may delete their own data with or without making a data request." "end_user_data_statement": "This cog does not persistently store data or metadata about users. It does store commands provided for intended later use along with the user ID of the person who scheduled it.\nUsers may delete their own data with or without making a data request."
} }

View file

@ -577,7 +577,7 @@ class Scheduler(commands.Cog):
@helpers.command(name="say") @helpers.command(name="say")
async def say(self, ctx: commands.GuildContext, *, content: str): async def say(self, ctx: commands.GuildContext, *, content: str):
await ctx.send(content, allowed_mentions=discord.AllowedMentions()) await ctx.send(content, allowed_mentions=discord.AllowedMentions.all())
@helpers.command(name="selfwhisper") @helpers.command(name="selfwhisper")
async def swhisp(self, ctx: commands.GuildContext, *, content: str): async def swhisp(self, ctx: commands.GuildContext, *, content: str):

View file

@ -5,11 +5,12 @@
"install_msg": "Thanks for install.", "install_msg": "Thanks for install.",
"short": "Play sound effects!", "short": "Play sound effects!",
"description": "Play sound effects, either via links or files. Integrates with economy and cost manager cog.", "description": "Play sound effects, either via links or files. Integrates with economy and cost manager cog.",
"min_bot_version": "3.3.0", "min_bot_version": "3.4.0",
"requirements": ["tabulate"], "requirements": ["tabulate"],
"tags": [ "tags": [
"sfx", "sfx",
"saysound", "saysound",
"audio" "audio"
] ],
"end_user_data_statement": "This doesn't store any user data."
} }

View file

@ -6,5 +6,7 @@
"INSTALL_MSG" : "Thanks for installing SmartReact.", "INSTALL_MSG" : "Thanks for installing SmartReact.",
"REQUIREMENTS" : [], "REQUIREMENTS" : [],
"TAGS" : ["reaction", "smart", "auto"], "TAGS" : ["reaction", "smart", "auto"],
"DISABLED" : false "DISABLED" : false,
"min_bot_version": "3.4.0",
"end_user_data_statement": "This doesn't store any user data."
} }

View file

@ -114,6 +114,8 @@ class SmartReact(commands.Cog):
# Thanks irdumb#1229 for the help making this "more Pythonic" # Thanks irdumb#1229 for the help making this "more Pythonic"
@commands.Cog.listener() @commands.Cog.listener()
async def on_message(self, message): async def on_message(self, message):
if await self.bot.cog_disabled_in_guild(self, message.guild):
return
if not message.guild: if not message.guild:
return return
if message.author == self.bot.user: if message.author == self.bot.user:

View file

@ -3,7 +3,7 @@
], ],
"bot_version": [ "bot_version": [
3, 3,
0, 4,
0 0
], ],
"description": "Trick or treat! Sometimes you get some credits, sometimes you get tricked and lose them!", "description": "Trick or treat! Sometimes you get some credits, sometimes you get tricked and lose them!",
@ -14,4 +14,5 @@
"tags": [ "tags": [
"brandons209", "brandons209",
"Halloween" "Halloween"
] ],
"end_user_data_statement": "This doesn't store any user data."

View file

@ -1,6 +1,7 @@
{ {
"author": [ "author": [
"tmerc" "tmerc",
"brandons209"
], ],
"install_msg": "Thanks for installing!", "install_msg": "Thanks for installing!",
"name": "Welcome", "name": "Welcome",
@ -13,5 +14,7 @@
"leave", "leave",
"ban", "ban",
"utility" "utility"
] ],
"min_bot_version": "3.4.0",
"end_user_data_statement": "This cog doesn't store any user data."
} }

View file

@ -570,6 +570,8 @@ class Welcome(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_join(self, member: discord.Member) -> None: async def on_member_join(self, member: discord.Member) -> None:
"""Listens for member joins.""" """Listens for member joins."""
if await self.bot.cog_disabled_in_guild(self, member.guild):
return
guild: discord.Guild = member.guild guild: discord.Guild = member.guild
guild_settings = self.config.guild(guild) guild_settings = self.config.guild(guild)
@ -601,12 +603,16 @@ class Welcome(commands.Cog):
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_remove(self, member: discord.Member) -> None: async def on_member_remove(self, member: discord.Member) -> None:
"""Listens for member leaves.""" """Listens for member leaves."""
if await self.bot.cog_disabled_in_guild(self, member.guild):
return
await self.__handle_event(member.guild, member, "leave") await self.__handle_event(member.guild, member, "leave")
@commands.Cog.listener() @commands.Cog.listener()
async def on_member_ban(self, guild: discord.Guild, member: discord.Member) -> None: async def on_member_ban(self, guild: discord.Guild, member: discord.Member) -> None:
"""Listens for user bans.""" """Listens for user bans."""
if await self.bot.cog_disabled_in_guild(self, member.guild):
return
await self.__handle_event(guild, member, "ban") await self.__handle_event(guild, member, "ban")
@ -804,7 +810,8 @@ class Welcome(commands.Cog):
return await channel.send( return await channel.send(
format_str.format( format_str.format(
member=user, server=guild, bot=user, count=count or "", plural=plural, roles=roles, stats=stats member=user, server=guild, bot=user, count=count or "", plural=plural, roles=roles, stats=stats
) ),
allowed_mentions=discord.AllowedMentions.all(),
) )
except discord.Forbidden: except discord.Forbidden:
log.error( log.error(
@ -848,7 +855,10 @@ class Welcome(commands.Cog):
message_format = await self.config.guild(member.guild).join.whisper.message() message_format = await self.config.guild(member.guild).join.whisper.message()
try: try:
await member.send(message_format.format(member=member, server=member.guild)) await member.send(
message_format.format(member=member, server=member.guild),
allowed_mentions=discord.AllowedMentions.all(),
)
except discord.Forbidden: except discord.Forbidden:
log.error( log.error(
f"Failed to send DM to member ID {member.id} (server ID {member.guild.id}): insufficient permissions" f"Failed to send DM to member ID {member.id} (server ID {member.guild.id}): insufficient permissions"