async def urban(self, ctx, *, msg: str): """Pulls the top urbandictionary.com definition for a term EXAMPLE: !urban a normal phrase RESULT: Probably something lewd; this is urban dictionary we're talking about""" if utils.channel_is_nsfw(ctx.message.channel): url = "http://api.urbandictionary.com/v0/define" params = {"term": msg} try: data = await utils.request(url, payload=params) if data is None: await ctx.send("Sorry but I failed to connect to urban dictionary!") return # List is the list of definitions found, if it's empty then nothing was found if len(data['list']) == 0: await ctx.send("No result with that term!") # If the list is not empty, use the first result and print it's defintion else: entries = [x['definition'] for x in data['list']] try: pages = utils.Pages(ctx, entries=entries[:5], per_page=1) await pages.paginate() except utils.CannotPaginate as e: await ctx.send(str(e)) # Urban dictionary has some long definitions, some might not be able to be sent except discord.HTTPException: await ctx.send('```\nError: Definition is too long for me to send```') except KeyError: await ctx.send("Sorry but I failed to connect to urban dictionary!") else: await ctx.send("This command is limited to nsfw channels")
async def e621(self, ctx, *, tags: str): """Searches for a random image from e621.net Format for the search terms need to be 'search term 1, search term 2, etc.' If the channel the command is ran in, is registered as a nsfw channel, this image will be explicit EXAMPLE: !e621 dragon RESULT: A picture of a dragon (hopefully, screw your tagging system e621)""" # This changes the formatting for queries, so we don't # Have to use e621's stupid formatting when using the command tags = tags.replace(' ', '_') tags = tags.replace(',_', ' ') url = 'https://e621.net/posts.json' params = { 'login': utils.config.e621_user, 'api_key': utils.config.e621_key, 'limit': 5, 'tags': tags } headers = {'User-Agent': utils.config.user_agent} nsfw = utils.channel_is_nsfw(ctx.message.channel) # e621 by default does not filter explicit content, so tack on # safe/explicit based on if this channel is nsfw or not params['tags'] += " rating:explicit" if nsfw else " rating:safe" # Tack on a random order params['tags'] += " order:random" data = await utils.request(url, payload=params, headers=headers) if data is None: await ctx.send( "Sorry, I had trouble connecting at the moment; please try again later" ) return # Try to find an image from the list. If there were no results, we're going to attempt to find # A number between (0,-1) and receive an error. # The response should be in a list format, so we'll end up getting a key error if the response was in json # i.e. it responded with a 404/504/etc. try: for image in data["posts"]: # Will support in the future blacklist = [] tags = itertools.chain.from_iterable(image["tags"].values()) # Check if any of the tags are in the blacklist if any(tag in tags for tag in blacklist): continue # If this image is fine, then send this and break await ctx.send(image["file"]["url"]) return except (ValueError, KeyError): await ctx.send("No results with that tag {}".format( ctx.message.author.mention)) return
async def google(self, ctx, *, query: str): """Searches google for a provided query EXAMPLE: !g Random cat pictures! RESULT: Links to sites with random cat pictures!""" url = "https://www.google.com/search" # Turn safe filter on or off, based on whether or not this is a nsfw channel nsfw = utils.channel_is_nsfw(ctx.message.channel) safe = "off" if nsfw else "on" params = {"q": query, "safe": safe, "hl": "en", "cr": "countryUS"} # Our format we'll end up using to send to the channel fmt = "" # First make the request to google to get the results data = await utils.request(url, payload=params, attr="text") if data is None: await ctx.send("I failed to connect to google! (That can happen??)" ) return # Convert to a BeautifulSoup element and loop through each result clasified by h3 tags with a class of 'r' soup = bs(data, "html.parser") for element in soup.find_all("h3", class_="r")[:3]: # Get the link's href tag, which looks like q=[url here]&sa # Use a lookahead and lookbehind to find this url exactly try: result_url = re.search("(?<=q=).*(?=&sa=)", element.find("a").get("href")).group(0) except AttributeError: await ctx.send( "I couldn't find any results for {}!".format(query)) return # Get the next sibling, find the span where the description is, and get the text from this try: description = element.next_sibling.find("span", class_="st").text except Exception: description = "" # Add this to our text we'll use to send fmt += "\n\n**URL**: <{}>\n**Description**: {}".format( result_url, description) fmt = "**Top 3 results for the query** _{}_:{}".format(query, fmt) await ctx.send(fmt)
async def derpi(self, ctx, *search: str): """Provides a random image from the first page of derpibooru.org for the following term EXAMPLE: !derpi Rainbow Dash RESULT: A picture of Rainbow Dash!""" if len(search) > 0: url = 'https://derpibooru.org/search.json' # Ensure a filter was not provided, as we either want to use our own, or none (for safe pics) query = ' '.join(value for value in search if not re.search('&?filter_id=[0-9]+', value)) params = {'q': query} nsfw = utils.channel_is_nsfw(ctx.message.channel) # If this is a nsfw channel, we just need to tack on 'explicit' to the terms # Also use the custom filter that I have setup, that blocks some certain tags # If the channel is not nsfw, we don't need to do anything, as the default filter blocks explicit if nsfw: params['q'] += ", (explicit OR suggestive)" params['filter_id'] = 95938 else: params['q'] += ", safe" # Lets filter out some of the "crap" that's on derpibooru by requiring an image with a score higher than 15 params['q'] += ', score.gt:15' try: # Get the response from derpibooru and parse the 'search' result from it data = await utils.request(url, payload=params) if data is None: await ctx.send( "Sorry but I failed to connect to Derpibooru!") return results = data['search'] except KeyError: await ctx.send("No results with that search term, {0}!".format( ctx.message.author.mention)) return # The first request we've made ensures there are results # Now we can get the total count from that, and make another request based on the number of pages as well if len(results) > 0: # Get the total number of pages pages = math.ceil(data['total'] / len(results)) # Set a new paramater to set which page to use, randomly based on the number of pages params['page'] = random.SystemRandom().randint(1, pages) data = await utils.request(url, payload=params) if data is None: await ctx.send( "Sorry but I failed to connect to Derpibooru!") return # Now get the results again results = data['search'] # Get the image link from the now random page'd and random result from that page index = random.SystemRandom().randint(0, len(results) - 1) # image_link = 'https://derpibooru.org/{}'.format(results[index]['id']) image_link = 'https:{}'.format(results[index]['image']) else: await ctx.send("No results with that search term, {0}!".format( ctx.message.author.mention)) return else: # If no search term was provided, search for a random image # .url will be the URL we end up at, not the one requested. # https://derpibooru.org/images/random redirects to a random image, so this is exactly what we want image_link = await utils.request( 'https://derpibooru.org/images/random', attr='url') await ctx.send(image_link)