async def get_image_from_album(album_hash, image_id=-1): """Gets an image from an imgur album. By default will get a random image in the album, but a value can be given. Returns a url pointing to the image. Arguments --------- album_hash : str The imgur album hash image_id : int (default=-1) The imgur image id. If negative, a random image will be taken. """ url = f"https://api.imgur.com/3/album/{album_hash}" async with aiohttp.ClientSession() as session: async with session.get( url, headers=dict( Authorization=f"Client-ID {CLIENT_ID}")) as response: try: album = await response.json() if image_id < 0: image_id = randrange(album["data"]["images_count"]) image = album["data"]["images"][image_id] return image["link"] except JSONDecodeError: print("JSON Error") raise UserError("Bad Response from Imgur") except (KeyError, IndexError): raise UserError("Invalid Response format from Imgur")
async def wordcloud(self, ctx, in_time = CONFIG["commands"]["whatdidimiss"]["defaulttime"], one_channel = "True", case_insensitive = "True" ): try: await self.check_cooldown(ctx) # Checking for appropriate permissions check_cmd_perms(ctx) seconds = utils.parse_time_to_seconds(in_time) if seconds > utils.parse_time_to_seconds(CONFIG["commands"]["whatdidimiss"]["maxtime"]) or seconds < 1: raise UserError(f'Thats too much time! {CONFIG["commands"]["whatdidimiss"]["maxtime"]} Maximum!', True) one_channel = utils.parse_bool(one_channel) case_insensitive = utils.parse_bool(case_insensitive) # Getting the earliest time that should be used timestamp = datetime.datetime.utcnow() - datetime.timedelta(seconds=seconds) # And now for the slow stuff with ctx.typing(): # Next, recursively grabbing messages and appending them to a long ass string words = await utils.collect_messages(ctx, one_channel, timestamp, CONFIG["commands"]["whatdidimiss"]["stopwords"], case_insensitive) with concurrent.futures.ProcessPoolExecutor() as pool: image = await asyncio.get_event_loop().run_in_executor(pool, create_wordcloud, words) await ctx.send(f"Heres what happened in the past: {in_time}", file=discord.File(fp=image, filename="wordcloud.png")) except UserError as e: await ctx.send(f":warning: {e.message}") # Removing the cooldown as an act of mercy if e.no_cooldown: cooldown.remove_cooldown(ctx)
def create_wordcloud(words): r"""Creates a wordcloud given a frequency dictionary, saves it to filename. Parameters ---------- words : dict A dictionary of words to be used in the cloud. Every string should have an integer value representing it's frequency. Passes data, and config, to WordCloud.WordCloud().generate_from_frequencies() for generation. """ wc = wordcloud.WordCloud( scale = CONFIG["commands"]["whatdidimiss"]["scale"], width = CONFIG["commands"]["whatdidimiss"]["width"], height = CONFIG["commands"]["whatdidimiss"]["height"], background_color = CONFIG["commands"]["whatdidimiss"]["background-colour"], mode = "RGBA", outline_thickness = CONFIG["commands"]["whatdidimiss"]["outline-thickness"], font_path = CONFIG["commands"]["whatdidimiss"]["fontpath"], tint_emoji = CONFIG["commands"]["whatdidimiss"]["tint"], emoji_cache_path = CONFIG["commands"]["whatdidimiss"]["cache"], rotate_emoji = CONFIG["commands"]["whatdidimiss"]["rotate"], font_size_mod = CONFIG["commands"]["whatdidimiss"]["limit"], colormap=secrets.choice(CONFIG["commands"]["whatdidimiss"]["colormaps"]) ) file = BytesIO() if words: wc.generate_from_frequencies(words, False).to_image().save(file, 'png') file.seek(0) else: raise UserError("I need words for a wordcloud!", True) return file
async def get_json(url, headers_={}): async with aiohttp.ClientSession() as session: async with session.get(url, headers=headers_) as response: try: return await response.json() except JSONDecodeError: raise UserError("Imgur gave a bad response :(")
async def whatdidimiss(self, ctx): try: # Checking cooldown: if cooldown.cooldown_in_effect(ctx): raise UserError("Please wait for cooldown.") cooldown.add_cooldown( ctx, CONFIG["commands"]["whatdidimiss"]["cooldown"]) # Checking for appropriate permissions check_cmd_perms(ctx) timestamp = datetime.datetime.utcnow() - datetime.timedelta( seconds=utils.parse_time_to_seconds( CONFIG["commands"]["whatdidimiss"]["max-lookback-time"])) with ctx.typing(): (words, msg_time) = await utils.collect_messages( ctx, True, timestamp, CONFIG["commands"]["whatdidimiss"]["stopwords"], True, True) with concurrent.futures.ProcessPoolExecutor() as pool: image = await asyncio.get_event_loop().run_in_executor( pool, create_wordcloud, words) if msg_time.total_seconds() == 0: time_diff = f'Hit max time of {CONFIG["commands"]["whatdidimiss"]["max-lookback-time"]}' else: time_diff = utils.parse_seconds_to_time( int(msg_time.total_seconds())) await ctx.send( f"Here are the messages since your last post: ({time_diff})", file=discord.File(fp=image, filename="wordcloud.png")) cooldown.add_cooldown( ctx, CONFIG["commands"]["whatdidimiss"]["cooldown"]) except UserError as e: await ctx.send(f"Invalid input: {e.message}")
async def get_dog_image(gif=False, download=True): url = "https://api.thedogapi.com/v1/images/search?mime_types=" url += int(gif)*"gif" + int(not gif)*"jpg,png" try: url = (await get_json(url))[0]["url"] return (await get_image("dog", url)) if download else url except (KeyError, IndexError): raise UserError("Dog API gave a bad response :(")
def check_cmd_perms(ctx): # Checking for appropriate permissions # Only check if the bot type is a member of a server if not utils.check_perms(ctx, discord.Permissions( read_message_history = True, attach_files = True, send_messages = True )): raise UserError("`read_message_history`, `attach_files`, and `send_messages` permissions required.", True)
async def find_wordcloud(self, ctx, in_time, one_channel=True, case_insensitive=True, stop_after_usermsg=False): try: await self.check_cooldown(ctx) if not utils.check_perms(ctx, discord.Permissions( read_message_history = True, attach_files = True, send_messages = True )): raise UserError("`read_message_history`, `attach_files`, and `send_messages` permissions required.", True) seconds = utils.parse_time_to_seconds(in_time) if seconds > utils.parse_time_to_seconds(CONFIG["commands"]["whatdidimiss"]["maxtime"]) or seconds < 1: raise UserError(f'Thats too much time! {CONFIG["commands"]["whatdidimiss"]["maxtime"]} Maximum!', True) # Getting the earliest time that should be used timestamp = datetime.datetime.utcnow() - datetime.timedelta(seconds=seconds) # And now for the slow stuff with ctx.typing(): # Next, recursively grabbing messages and appending them to a long ass string result = await utils.collect_messages( ctx, one_channel, timestamp, CONFIG["commands"]["whatdidimiss"]["stopwords"], case_insensitive, stop_after_usermsg ) # Depending on if stop_after_usermsg is set, it'll either just return the frequency dict, or a tuple with more information words = result[0] msg_count = result[1] if stop_after_usermsg: if result[2].total_seconds() == 0: time_diff = f'Hit max time of {CONFIG["commands"]["whatdidimiss"]["max-lookback-time"]}' else: time_diff = utils.parse_seconds_to_time(int(result[2].total_seconds())) with concurrent.futures.ProcessPoolExecutor() as pool: image = await asyncio.get_event_loop().run_in_executor(pool, create_wordcloud, words) if stop_after_usermsg: await ctx.send(f"Heres what happened since your last post {time_diff} ago ({msg_count} messages)", file=discord.File(fp=image, filename="wordcloud.png")) else: await ctx.send(f"Heres what happened in the past {utils.prettify_time(in_time)} ({msg_count} messages)", file=discord.File(fp=image, filename="wordcloud.png")) except UserError as e: await ctx.send(f":warning: {e.message}") # Removing the cooldown as an act of mercy if e.no_cooldown: cooldown.remove_cooldown(ctx)
async def get_image_from_album(album_hash, download=True, image_id=-1): """Gets an image from an imgur album. By default will get a random image in the album, but a value can be given. Returns a url pointing to the image. Arguments --------- album_hash : str The imgur album hash image_id : int (default=-1) The imgur image id. If negative, a random image will be taken. """ url = f"https://api.imgur.com/3/album/{album_hash}" try: album = await get_json(url, {"Authorization": f"Client-ID {CLIENT_ID}"}) image_id = image_id if image_id > -1 else randrange(album["data"]["images_count"]) url = album["data"]["images"][image_id]["link"] return (await get_image("gator", url)) if download else url except (KeyError, IndexError): raise UserError("Got an Invalid Response")
async def check_cooldown(self, ctx): c, t = cooldown.cooldown_in_effect(ctx) if c: t = utils.parse_seconds_to_time(t) raise UserError(f"Relax. Your cooldown expires in {t}!") cooldown.add_cooldown(ctx, CONFIG["commands"]["whatdidimiss"]["cooldown"])