async def wrapped(*args, **kwargs): context: commands.Context = None for arg in args: if isinstance(arg, commands.Context): context = arg break if not context.guild and not await is_global(): raise commands.UserFeedbackCheckFailure( _("Can't pay for this command in DM without a global bank." )) try: await withdraw_credits(context.author, amount) except Exception: credits_name = await get_currency_name(context.guild) raise commands.UserFeedbackCheckFailure( _("You need at least {cost} {currency} to use this command." ).format(cost=humanize_number(amount), currency=credits_name)) else: try: return await coro(*args, **kwargs) except AbortPurchase: await deposit_credits(context.author, amount) except Exception: await deposit_credits(context.author, amount) raise
def tin2tdelta(tinstr): if tinstr.lower().strip() == "now": return timedelta(0) tins = re.findall(r'(-?\d+) ?([a-z]+) ?', tinstr.lower()) o = timedelta() for tin, unit in tins: try: tin = int(tin) if unit[:2] == 'mo': o += relativedelta(months=+tin) elif unit[0] == 'm': o += timedelta(minutes=tin) elif unit[0] == 'h': o += timedelta(hours=tin) elif unit[0] == 'd': o += timedelta(days=tin) elif unit[0] == 'w': o += timedelta(weeks=tin) elif unit[0] == 'y': o += relativedelta(years=+tin) elif unit[0] == 's': raise commands.UserFeedbackCheckFailure( "We aren't exact enough to use seconds! If you need that precision, try this: https://www.timeanddate.com/timer/" ) else: raise commands.UserFeedbackCheckFailure( inline( "Invalid unit: {}\nPlease use minutes, hours, days, weeks, months, or, if you're feeling especially zealous, years." .format(unit))) except OverflowError: raise commands.UserFeedbackCheckFailure( inline("Come on... Be reasonable :/")) return o
async def check_re_filters(self, ms, ctx): try: return filt_timeout(self.re_filters, ms) except TimeoutError: logger.error("Timeout with patttern: \"{}\" by user {} ({})".format( '", "'.join(self.regeces), ctx.author.name, ctx.author.id)) raise commands.UserFeedbackCheckFailure("Regex took too long to compile. Stop trying to break the bot") except re.error as e: raise commands.UserFeedbackCheckFailure("Regex search threw error '{}'".format(e.msg))
def webhook_check(ctx: commands.Context) -> Union[bool, commands.Cog]: if not ctx.channel.permissions_for(ctx.me).manage_webhooks: raise commands.UserFeedbackCheckFailure( "I need the **Manage Webhooks** permission for webhook quoting.") cog = ctx.bot.get_cog("Webhook") if cog and cog.__author__ == "PhenoM4n4n": return cog raise commands.UserFeedbackCheckFailure( "The Webhook cog by PhenoM4n4n must be loaded for webhook quoting.")
async def is_lol_staff(ctx) -> bool: staff_role = None if not ctx.guild: raise commands.UserFeedbackCheckFailure( "You must be in a server to run this command!") for role in ctx.message.guild.roles: if role.name == "LoL-Staff": staff_role = role break if staff_role not in ctx.author.roles: raise commands.UserFeedbackCheckFailure( "You don't have enough permissions to run this command!") return True
def add_mirrored_channel(self, source_channel: int, dest_channel: int): channels = self.mirrored_channels() if source_channel == dest_channel: raise commands.UserFeedbackCheckFailure('Cannot mirror a channel to itself') if dest_channel in channels: raise commands.UserFeedbackCheckFailure('Destination channel is already a source channel') if source_channel not in channels: channels[source_channel] = { 'channels': [], 'messages': {}, } channels[source_channel]['channels'].append(dest_channel) self.save_settings()
def ensure_valid_locale(locale: Optional[str] = None) -> None: if locale: # We check the locale is correct before all try: get_lang_and_theme(locale) except InvalidLanguageError: raise commands.UserFeedbackCheckFailure( "Incorrect locale/language given.")
async def removenow(self, ctx): """List users below the remove amount.""" server = ctx.guild lookback_days = self.settings.remove_lookback(server.id) for role_id, role, amount in self.roles_and_amounts( server, 'remove_amount'): if role is None or amount <= 0: continue msg = 'Removing for role {} (point cutoff {})'.format( role.name, amount) await ctx.send(inline(msg)) grant_users, ignored_users = await self.get_grant_ignore_users( server, role, amount, lookback_days, False) grant_users = [server.get_member(int(x[0])) for x in grant_users] cs = 5 user_chunks = [ grant_users[i:i + cs] for i in range(0, len(grant_users), cs) ] for chunk in user_chunks: msg = 'Removing from users: ' + ','.join( [m.name for m in chunk]) await ctx.send(inline(msg)) for member in chunk: try: await member.remove_roles(role) except Exception as ex: raise commands.UserFeedbackCheckFailure(str(ex))
async def grantnow(self, ctx): """List users above the grant amount.""" guild = ctx.guild lookback_days = self.settings.grant_lookback(guild.id) for role_id, role, amount in self.roles_and_amounts( guild, 'grant_amount'): if role is None or amount <= 0: continue msg = 'Granting for role {} (point cutoff {})'.format( role.name, amount) await ctx.send(inline(msg)) grant_users, ignored_users = await self.get_grant_ignore_users( guild, role, amount, lookback_days, True) grant_users = [guild.get_member(int(x[0])) for x in grant_users] cs = 5 user_chunks = [ grant_users[i:i + cs] for i in range(0, len(grant_users), cs) ] for chunk in user_chunks: msg = 'Granting to users: ' + ','.join([m.name for m in chunk]) await ctx.send(inline(msg)) for member in chunk: try: await member.add_roles(role) except Exception as ex: raise commands.UserFeedbackCheckFailure(str(ex))
async def predicate(ctx: commands.Context): """We don't like spam, at Red, section #testing.""" if ctx.channel.id in ( 133251234164375552, ) and ctx.author.id not in DEVS_IDS: raise commands.UserFeedbackCheckFailure( "No no no! I won't let you get smashed by Defender! - Pred.") return True
def tzstr_to_tz(tz): tz = tz.lower().strip() if tz in ['edt', 'est', 'et']: tz = 'America/New_York' elif tz in ['mdt', 'mst', 'mt']: tz = 'America/North_Dakota/Center' elif tz in ['pdt', 'pst', 'pt']: tz = 'America/Los_Angeles' elif tz in ['cdt', 'cst', 'ct']: tz = 'America/Chicago' elif tz in ['jp', 'jt', 'jst']: return tz_lookup['JST'] elif tz.upper() in tz_lookup: return tz_lookup[tz.upper()] else: for tzo in pytz.all_timezones: if tz.lower() in tzo.lower().split("/"): tz = tzo break else: for tzo in pytz.all_timezones: if tz.lower() in tzo: tz = tzo break try: return pytz.timezone(tz) except Exception as e: raise commands.UserFeedbackCheckFailure("Invalid timezone: " + tz)
def _shutdown_check(self, ctx): if self.operations: raise commands.UserFeedbackCheckFailure( f"I'm afraid I can't do that, {ctx.author.display_name}.\n" "There's an op going on." ) return True
async def role_uniquemembers(self, ctx: commands.Context, *roles: FuzzyRole): """ View the total unique members between multiple roles. """ roles_length = len(roles) if roles_length == 1: raise commands.UserFeedbackCheckFailure( "You must provide at least 2 roles.") if not ctx.guild.chunked: await ctx.guild.chunk() color = roles[0].color unique_members = set() description = [] for role in roles: unique_members.update(role.members) description.append( f"{role.mention}: {self.format_members(role.members)}") description.insert( 0, f"**Unique members**: {self.format_members(unique_members)}") e = discord.Embed( color=color, title=f"Unique members between {roles_length} roles", description="\n".join(description), ) ref = ctx.message.to_reference(fail_if_not_exists=False) await ctx.send(embed=e, reference=ref)
def t_ORB(self, t): r'orbs?(\([0-9]*\))?' t.value = t.value.strip('orb').strip('s').strip('(').strip(')') t.value = int(t.value) if t.value else 3 if t.value < 3 or t.value > 30: raise commands.UserFeedbackCheckFailure('match must have 3-30 orbs, got ' + t.value) return t
def setIfType(self, expected_type, given_type, current_value, new_value): if expected_type != given_type: return current_value if current_value is not None: raise commands.UserFeedbackCheckFailure( 'You set {} more than once'.format(given_type)) return new_value
async def _send_feedback(self, ctx, message: str, feedback_channel, success_message: str): if feedback_channel is None: raise commands.UserFeedbackCheckFailure("Feedback channel not set") guild = ctx.guild author = ctx.author footer = "User ID: " + str(author.id) if guild: source = "from {}".format(guild) footer += " | Guild ID: " + str(guild.id) else: source = "through DM" description = "Sent by {} {}".format(author, source) e = discord.Embed(description=message) if author.avatar_url: e.set_author(name=description, icon_url=author.avatar_url) else: e.set_author(name=description) e.set_footer(text=footer) try: await feedback_channel.send(embed=e) except: await ctx.send(inline("I'm unable to deliver your message. Sorry.") ) else: await ctx.send( inline("Your message has been sent." " Abusing this feature will result in a blacklist." + success_message))
async def check_glob_filters(self, ms, ctx): try: return filt_timeout(self.gl_filters, ms) except TimeoutError: logger.error("Timeout with patttern: \"{}\" by user {} ({})".format( '", "'.join(self.globs), ctx.author.name, ctx.author.id)) raise commands.UserFeedbackCheckFailure("Glob took too long to compile. Stop trying to break the bot")
async def phrase(self, ctx, name: str, cooldown: int, *, phrase: str = None): """Keep an eye out for a phrase (regex). Whenever the regex is matched, a note will be printed to the watchdog channel, subject to the specified cooldown in seconds. Name is descriptive. Set a cooldown of 0 to clear. """ server_id = ctx.guild.id if cooldown == 0: self.settings.setWatchdogPhrase( server_id, name, None, None, None) await ctx.send(inline('Watchdog phrase cleared for {}'.format(name))) return try: re.compile(phrase) except Exception as ex: raise commands.UserFeedbackCheckFailure(str(ex)) if cooldown < 300: await ctx.send(inline('Overriding cooldown to minimum')) cooldown = 300 self.settings.setWatchdogPhrase(server_id, name, ctx.author.id, cooldown, phrase) self.server_phrase_last[server_id][name] = None await ctx.send(inline('Watchdog named {} set on {} with cooldown of {} seconds'.format(name, phrase, cooldown)))
async def is_dm_or_whitelisted(ctx) -> bool: GAMHCOG = ctx.bot.get_cog("BayesGAMH") if not (isinstance(ctx.channel, DMChannel) or str(ctx.channel.id) in await GAMHCOG.config.allowed_channels()): raise commands.UserFeedbackCheckFailure( "This command is only available in" " DMs or whitelisted channels.") return True
def t_ROW(self, t): r'row(\(\d*\))?' t.value = t.value.strip('row').strip('(').strip(')') t.value = int(t.value) if t.value else 6 if t.value < 6 or t.value > 30: raise commands.UserFeedbackCheckFailure('row must have 6-30 orbs, got ' + t.value) return t
def set_role(self, server_id: str, role_id: str, remove_amount: int, warn_amount: int, grant_amount: int): roles = self.roles(server_id) if remove_amount == 0 and grant_amount == 0: roles.pop(role_id, None) elif remove_amount >= grant_amount: raise commands.UserFeedbackCheckFailure('remove_amount must be less than grant_amount') elif warn_amount >= grant_amount: raise commands.UserFeedbackCheckFailure('warn_amount must be less than grant_amount') elif remove_amount < 0 or warn_amount < 0 or grant_amount < 0: raise commands.UserFeedbackCheckFailure('role values must be >= 0') else: roles[role_id] = { 'role_id': role_id, 'remove_amount': remove_amount, 'warn_amount': warn_amount, 'grant_amount': grant_amount, } self.save_settings()
async def predicate(ctx): if ctx.guild.id == 133049272517001216: return True ## Let's make an exception for #testing ? :) perm = ctx.me.guild_permissions if perm.kick_members: return True else: raise commands.UserFeedbackCheckFailure( _("You need to give me permissions to kick members before using this cog." ))
async def get_ban_limit(ctx: commands.Context, limit: int) -> Tuple[int, list]: await ctx.trigger_typing() bans = await ctx.guild.bans() ban_count = len(bans) if not ban_count: raise commands.UserFeedbackCheckFailure("This server has no bans.") limit = min(LIMIT, min(limit, ban_count)) await ctx.send(f"Gathering stats up to the last {limit} bans.") return limit, bans
def __init__(self, lexer): self.rows = None self.oe = None self.tpas = None self.atk = None self.id = None self.mult = None self.row_matches = list() self.tpa_matches = list() self.orb_matches = list() self.combos = None for tok in iter(lexer.token, None): type = tok.type value = tok.value self.rows = self.setIfType('ROWS', type, self.rows, value) self.oe = self.setIfType('OE', type, self.oe, value) self.tpas = self.setIfType('TPAS', type, self.tpas, value) self.atk = self.setIfType('ATK', type, self.atk, value) self.id = self.setIfType('ID', type, self.id, value) self.mult = self.setIfType('MULT', type, self.mult, value) if type == 'ROW': self.row_matches.append(value) if type == 'TPA': self.tpa_matches.append(value) if type == 'ORB': if value == 4: self.tpa_matches.append(value) elif value == 30: self.row_matches.append(value) else: self.orb_matches.append(value) self.combos = self.setIfType('COMBOS', type, self.combos, value) if self.rows is None: self.rows = 0 if self.oe is None: self.oe = 0 if self.tpas is None: self.tpas = 0 if self.atk is None: self.atk = 1 if self.mult is None: self.mult = 1 if self.combos is None: self.combos = 0 if (len(self.row_matches) + len(self.tpa_matches) + len(self.orb_matches)) == 0: raise commands.UserFeedbackCheckFailure( 'You need to specify at least one attack match (orb, tpa, row)' )
async def predicate(ctx): if version_info >= VersionInfo.from_str("3.2.0"): key = await ctx.bot.get_shared_api_tokens("apex") else: key = await ctx.bot.db.api_tokens.get_raw("apex", default=None) try: res = True if key["api_key"] else False except: res = False if not res and ctx.invoked_with in dir(ctx.bot.get_cog('Apex')): raise commands.UserFeedbackCheckFailure(message="You need to set the API key using `[p]set api apex <api_key>` first !") return res
def get_role(roles, role_string): if role_string.lower() == "everyone": role_string = "@everyone" role = discord.utils.find( lambda r: r.name.lower() == role_string.lower(), roles) if role is None: print("Could not find role named " + role_string) raise commands.UserFeedbackCheckFailure("Could not find role named " + role_string) return role
async def bot_check_once(self, ctx: commands.Context) -> bool: if ctx.command is self.choosebot: return True instance_name = data_manager.instance_name assert isinstance(instance_name, str) if self.chosen_bot == instance_name: return True if not await self.bot.is_owner(ctx.author): return True if self.chosen_bot is None: raise commands.UserFeedbackCheckFailure( f"No instance name is set to be enforced, assuming that this instance" f" ({inline(instance_name)}) isn't the one you wanted to use.\n\n" f"Use `choosebot` command to choose the bot." ) raise commands.UserFeedbackCheckFailure( f"The name of enforced instance is {inline(self.chosen_bot)}" f" but you tried to use {instance_name}. Aborting..." )
def get_role_from_id(bot, guild, roleid): try: roles = guild.roles except AttributeError: guild = get_server_from_id(bot, guild) try: roles = guild.roles except AttributeError: raise ValueError("Role with id {} not found.".format(roleid)) role = discord.utils.get(roles, id=roleid) if role is None: raise commands.UserFeedbackCheckFailure("Could not find role id {} in guild {}".format(roleid, guild.name)) return role
def check_channel_permission( ctx: commands.Context, channel_or_category: Union[discord.TextChannel, discord.CategoryChannel], ) -> bool: """ Check user's permission in a channel, to be sure he can edit it. """ mc = channel_or_category.permissions_for(ctx.author).manage_channels if mc: return True reason = (_("You are not allowed to edit this channel.") if not isinstance(channel_or_category, discord.CategoryChannel) else _("You are not allowed to edit in this category.")) raise commands.UserFeedbackCheckFailure(reason)
async def afkdisconnect(self, ctx: commands.Context, *, time: Union[int, bool]): """ Sets how long to wait before disconnecting an AFK member, in seconds. Set to -1 to disable. """ if isinstance(time, bool): time = 0 if time else -1 if time < -1: raise commands.UserFeedbackCheckFailure( "Time must be 0 or greater, or -1 to disable the feature") self.timeout[ctx.guild.id] = time await self.config.guild(ctx.guild).timeout.set(time) await ctx.tick()