def add(self, regex, author_id=''): #Find requested replacement rep = get_match(regex) #ensure that replace was found before proceeding if not rep: return formatter.error('Could not find valid regex') p1 = formatter.escape_mentions(rep.group(2)) p2 = formatter.escape_mentions(rep.group(4)) #check regex for validity if not comp(p1, p2): return formatter.error('regex is invalid') #make sure that there are no similar regexes in db for i in self.replacements: if similar(p1, i): r = '\"{}\" -> \"{}\"'.format(i, self.replacements[i][0]) message = 'Similar regex already exists, delete or edit it\n{}'.format( formatter.inline(r)) return formatter.error(message) #make sure regex is not too broad if bad_re(p1): return formatter.error('regex is too broad') #check that regex does not already exist if p1 in self.replacements: return formatter.error('regex already exists') self.replacements[p1] = [p2, author_id] return formatter.ok()
async def on_command_error(ctx, error): msg = ctx.message if isinstance(error, commands.NoPrivateMessage): await msg.author.send(formatter.error( 'This command cannot be used in private messages.' )) elif isinstance(error, commands.DisabledCommand): await msg.channel.send(formatter.error( 'Sorry. This command is disabled and cannot be used.' )) elif isinstance(error, commands.CommandInvokeError): await msg.channel.send(formatter.error( 'Command error: {}'.format(error) )) elif isinstance(error, commands.errors.CheckFailure): await msg.channel.send(formatter.error( 'Sorry you have insufficient permissions to run that command.' )) else: await msg.channel.send(formatter.error(str(error))) e_tb = traceback.format_exception( error.__class__, error, error.__traceback__ ) lines = [] for line in e_tb: lines.extend(line.rstrip('\n').splitlines()) logger.error(f'<{msg.author.name}> {msg.content}: %s','\n'.join(lines))
def edit(self, regex, author_id=''): #Find requested replacement rep = get_match(regex) #ensure that replace was found before proceeding if not rep: return formatter.error('Could not find valid regex') p1 = formatter.escape_mentions(rep.group(2)) p2 = formatter.escape_mentions(rep.group(4)) #check regex for validity if not comp(p1, p2): return formatter.error('regex is invalid') #make sure regex is not too broad if bad_re(p1): return formatter.error('regex is too broad') #ensure that replace was found before proceeding if p1 not in self.replacements: return formatter.error('Regex not in replacements.') #check if they have correct permissions if author_id != self.replacements[p1][1] \ and not perms.is_owner_check(author_id): #will uncomment next line when reps are a per server thing #and not perms.check_permissions(ctx.message, manage_messages=True): raise commands.errors.CheckFailure('Cannot edit') self.replacements[p1] = [p2, author_id] return formatter.ok()
async def meme(self, ctx, *, text : str): """ Adds text to images Valid names so far: """ async with ctx.typing(): match = MemeGenerator.pattern.match(text) name = match.group(1).lower() if match else text text = match.group(2) if match else '' text = ' '.join(dh.remove_comments(text.split())) cfg = self.conf.get('memes', {}).get(name, None) if not cfg: await ctx.send(error('Could not find image')) return if not text: await ctx.send(error('Are you trying to get an empty image?')) return temp = tempfile.NamedTemporaryFile(suffix=".png") if 'font' not in cfg: cfg['font'] = self.conf.get('font', '') if 'path' not in cfg: cfg['path'] = self.conf.get('path', '') write_image(text, temp.name, **cfg) await ctx.send(file=discord.File(temp.name)) temp.close()
async def rep(self, ctx): """Manage replacements Uses a regex to replace text from users """ message = None if self.regex.is_banned(str(ctx.message.author.id)): message = formatter.error('No ')+':poi:' ctx.invoked_subcommand = None if ctx.invoked_subcommand is None: message = f'Error, {ctx.subcommand_passed} is not a valid command\n' + \ 'try: `.rep list`, `.rep add`, or `.rep remove` instead' if message: await ctx.send(formatter.error(message))
async def _search(self, ctx, *, query: str): """searches for query on emby, displays first result if first "word" in query is a number, returns that many results (ignoring the number) """ async with ctx.typing(): match = re.search(r'^(\d)+\s+(\S.*)$', query) if not query: await ctx.send(formatter.error('missing query')) return elif match: num = int(match.group(1)) query = match.group(2) else: num = 1 results = await self.conn.search(query) results = [i for i in results if issubclass(type(i), EmbyObject)] if not results: await ctx.send('No results found') return for result in results[:num]: await result.update() em = await emby_helper.makeEmbed(result) await ctx.message.channel.send(embed=em)
async def img(self, ctx, *search): async with ctx.typing(): path, url = await self.bot.loop.run_in_executor( None, self.az.img, *search) if path: size_ok = os.stat(path).st_size / 1024 / 1024 <= upload_limit else: size_ok = False logger.debug('img (%s) - %s', type(path), str(path)) if not path: error = formatter.error( f'Could not find image matching: {search}') await ctx.send(error) elif type(path) != str: await ctx.send(embed=path) elif path.rpartition('.')[2] in ('zip', 'cbz'): zf = zipfile(path, 'r') for fl in zf.filelist: f = zf.open(fl.filename) await ctx.send(file=discord.File(f, fl.filename)) f.close() zf.close() elif path.rpartition('.')[2] in ('gif', 'png', 'jpg', 'jpeg') and size_ok: await ctx.send(file=discord.File(path)) else: await ctx.send(url)
async def add_groupme_link(self, ctx, g_id: str): channel = ctx.message.channel group, g_bot = self.get_group_bot(g_id) if not group: await ctx.send(formatter.error("I am not in a group with that id")) return if g_id not in self.g_groups: self.l_bots.append(g_bot) self.g_groups[g_id] = group if str(channel.id) in self.g_bots: self.g_bots[str(channel.id)].append(g_bot) self.conf['links'][str(channel.id)].append(g_id) else: self.g_bots[str(channel.id)] = [g_bot] self.conf['links'][str(channel.id)] = [g_id] if g_id in self.d_chans: self.d_chans[g_id].append(channel) else: self.d_chans[g_id] = [channel] if g_id not in self.g_groups: self.conf['g_old'][g_id] = None self.conf.save() await ctx.send(formatter.ok())
async def graph(self, ctx, *, parameters): async with ctx.typing(): try: f = lambda: self.math.renderGraph( parameters, fmt='png', backgroundcolor='white') f = await self.bot.loop.run_in_executor(None, f) except: f = None if f: await ctx.send(file=discord.File(f, 'graph.png')) else: await ctx.send(formatter.error('Graph rendering issue'))
async def format(self, ctx, *, formula): async with ctx.typing(): try: f = lambda: self.math.renderLatex( formula, fmt='png', backgroundcolor='white') f = await self.bot.loop.run_in_executor(None, f) except: f = None if f: await ctx.send(file=discord.File(f, 'math.png')) else: await ctx.send(formatter.error('LaTeX syntax error'))
async def nsfw(self, ctx): """NSFW stuff""" channel = ctx.message.channel # # ensure that the current channel is marked as nsfw # if not channel.is_private and 'nsfw' not in channel.name.lower(): # await ctx.send(formatter.error('not in nsfw channel')) # ctx.invoked_subcommand = None # return # if user misstyped or does not know what they are doing, complain if ctx.invoked_subcommand is None: await ctx.send(formatter.error("Please specify valid subcommand")) return
async def _rm(self, ctx, index: int): """remove an existing replacement by index""" async with ctx.typing(): if index >= len(self.quotes_dict['quotes']): await ctx.send( formatter.error('Quote {} does not exist'.format(index))) return if str(ctx.message.author.id) != self.quotes_dict['quotes'][index]['id'] \ and not perms.check_permissions(ctx.message, manage_messages=True): raise commands.errors.CheckFailure('Cannot delete') self.quotes_dict['quotes'].pop(index) self.quotes_dict.save() await ctx.send(formatter.ok())
def rm(self, pattern, author_id=''): #pattern = re.sub('^(`)?\\(\\?[^\\)]*\\)', '\\1', pattern) pattern = formatter.escape_mentions(pattern) #ensure that replace was found before proceeding if re.search('^`.*`$', pattern) and pattern[1:-1] in self.replacements: pattern = pattern[1:-1] elif pattern not in self.replacements: return formatter.error('Regex not in replacements.') #check if they have correct permissions if author_id != self.replacements[pattern][1] \ and not perms.is_owner_check(author_id): raise commands.errors.CheckFailure('Cannot delete') self.replacements.pop(pattern) self.replacements.save() return formatter.ok()
async def _add(self, ctx, *, quote): """adds a quote""" async with ctx.typing(): for i in self.quotes_dict['quotes']: if quote.lower() == i['quote'].lower(): await ctx.send(formatter.error('Quote already exists')) return index = len(self.quotes_dict['quotes']) date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') self.quotes_dict['quotes'].append({ 'id': str(ctx.message.author.id), 'date': date, 'quote': quote, }) self.quotes_dict.save() await ctx.send(formatter.ok('quote added, index {}'.format(index)))
async def quotes(self, ctx): """Manage quotes""" if ctx.invoked_subcommand is None: async with ctx.typing(): message = ctx.message.content try: index = int(ctx.subcommand_passed) if index >= len(self.quotes_dict['quotes']): await ctx.send( formatter.error( 'Quote {} does not exist'.format(index))) else: quote = self.quotes_dict['quotes'][index] message = 'On {}:\n{}'.format( quote['date'], formatter.code(quote['quote'])) await ctx.send(message) except: await ctx.send(self._random(message))
def _random(self, message): quotes = self.quotes_dict['quotes'] message = message.split()[1:] if message: quotes = [] for quote in self.quotes_dict['quotes']: ok = True for w in message: if w.lower() not in quote['quote'].lower(): ok = False break if ok: quotes.append(quote) if not quotes: return formatter.error('No quotes found') quote = random.choice(quotes) return 'On {}:\n{}'.format(quote['date'], formatter.code(quote['quote']))
async def emby(self, ctx): """Manage emby stuff""" if ctx.invoked_subcommand is None: await ctx.send(formatter.error("Please specify valid subcommand"))