async def plants(self, ctx: utils.Context, user: typing.Optional[discord.User]): """ Shows you all the plants that a given user has. """ # Grab the plant data user = user or ctx.author async with self.bot.database() as db: user_rows = await db( "SELECT * FROM plant_levels WHERE user_id=$1 ORDER BY plant_name DESC", user.id) # See if they have anything available plant_data = sorted([ (i['plant_name'], i['plant_type'], i['plant_nourishment'], i['last_water_time'], i['plant_adoption_time']) for i in user_rows ]) if not plant_data: embed = utils.Embed(use_random_colour=True, description=f"<@{user.id}> has no plants :c") return await ctx.send(embed=embed) # Add the plant information embed = utils.Embed(use_random_colour=True, description=f"<@{user.id}>'s plants") ctx._set_footer(embed) for plant_name, plant_type, plant_nourishment, last_water_time, plant_adoption_time in plant_data: plant_type_display = plant_type.replace('_', ' ').capitalize() plant_death_time = last_water_time + timedelta( **self.bot.config.get('plants', {}).get( 'death_timeout', {'days': 3})) plant_death_humanize_time = utils.TimeValue( (plant_death_time - dt.utcnow()).total_seconds()).clean_full plant_life_humanize_time = utils.TimeValue( (dt.utcnow() - plant_adoption_time).total_seconds()).clean_full if plant_nourishment == 0: text = f"{plant_type_display}, nourishment level {plant_nourishment}/{self.bot.plants[plant_type].max_nourishment_level}." elif plant_nourishment > 0: text = ( f"**{plant_type_display}**, nourishment level {plant_nourishment}/{self.bot.plants[plant_type].max_nourishment_level}.\n" f"If not watered, this plant will die in **{plant_death_humanize_time}**.\n" f"This plant has been alive for **{plant_life_humanize_time}**.\n" ) else: text = f"{plant_type_display}, dead :c" embed.add_field(plant_name, text, inline=False) # Return to user v = await ctx.send(embed=embed) try: await self.bot.add_delete_button(v, ( ctx.author, user, ), wait=False) except discord.HTTPException: pass
async def herbiary(self, ctx:utils.Context, *, plant_name:str=None): """ Get the information for a given plant. """ # See if a name was given if plant_name is None: plant_list = list() for plant in self.bot.plants.values(): plant_list.append(plant.display_name.capitalize()) plant_list.sort() embed = utils.Embed(use_random_colour=True, description="\n".join(plant_list)) ctx.bot.set_footer_from_config(embed) return await ctx.send(embed=embed) # See if the given name is valid plant_name = plant_name.replace(' ', '_').lower() if plant_name not in self.bot.plants: return await ctx.send(f"There's no plant with the name **{plant_name.replace('_', ' ')}** :c", allowed_mentions=discord.AllowedMentions(users=False, roles=False, everyone=False)) plant = self.bot.plants[plant_name] # Work out our artist info to be displayed description_list = [] artist_info = self.artist_info.get(plant.artist, {}).copy() discord_id = artist_info.pop('discord', None) description_list.append(f"**Artist `{plant.artist}`**") if discord_id: description_list.append(f"Discord: <@{discord_id}> (`{discord_id}`)") for i, o in sorted(artist_info.items()): description_list.append(f"{i.capitalize()}: [Link]({o})") description_list.append("") # Embed the data with utils.Embed(use_random_colour=True) as embed: embed.title = plant.display_name.capitalize() embed.description = '\n'.join(description_list) embed.set_image("attachment://plant.gif") ctx.bot.set_footer_from_config(embed) display_utils = self.bot.get_cog("PlantDisplayUtils") # Make a gif of the stages pot_hue = random.randint(0, 360) display_levels = [] added_display_stages = [] for i, o in plant.nourishment_display_levels.items(): if o not in added_display_stages: display_levels.insert(0, int(i)) added_display_stages.append(o) gif_frames = [display_utils.get_plant_image(plant.name, i, "clay", pot_hue) for i in display_levels] plant_image_bytes = display_utils.gif_to_bytes(*gif_frames, duration=1_000) await ctx.send(embed=embed, file=discord.File(plant_image_bytes, filename=f"plant.gif"))
async def plants(self, ctx: utils.Context, user: utils.converters.UserID = None): """ Shows you all the plants that a given user has. """ # Grab the plant data user = discord.Object(user) if user else ctx.author async with self.bot.database() as db: user_rows = await db( "SELECT * FROM plant_levels WHERE user_id=$1 ORDER BY plant_name DESC", user.id) # See if they have anything available plant_data = sorted([(i['plant_name'], i['plant_type'], i['plant_nourishment'], i['last_water_time']) for i in user_rows]) if not plant_data: embed = utils.Embed(use_random_colour=True, description=f"<@{user.id}> has no plants :c") return await ctx.send(embed=embed) # Add the plant information embed = utils.Embed(use_random_colour=True, description=f"<@{user.id}>'s plants") ctx._set_footer(embed) for plant_name, plant_type, plant_nourishment, last_water_time in plant_data: plant_type_display = plant_type.replace('_', ' ').capitalize() # plant_name_display = re.sub(r"([\_*`])", r"\\\1", plant_name) plant_death_time = last_water_time + timedelta( **self.bot.config.get('plants', {}).get( 'death_timeout', {'days': 3})) plant_death_humanize_time = arrow.get(plant_death_time).humanize( granularity=["day", "hour", "minute"], only_distance=True) if plant_nourishment == 0: text = f"{plant_type_display}, nourishment level {plant_nourishment}/{self.bot.plants[plant_type].max_nourishment_level}." elif plant_nourishment > 0: text = ( f"{plant_type_display}, nourishment level {plant_nourishment}/{self.bot.plants[plant_type].max_nourishment_level}.\n" f"If not watered, this plant will die in *{plant_death_humanize_time}*." ) else: text = f"{plant_type_display}, dead :c" embed.add_field(plant_name, text) # Return to user return await ctx.send(embed=embed)
async def grandexchange(self, ctx, *, item:str): """ Get the value of an item on the grand exchange (OSRS). """ async with ctx.typing(): if item.lower() in ['random']: item_id = random.choice(list(self.item_ids.values())) else: item = item.capitalize() item_id = self.item_ids.get(item) if item_id: item_dict = await self.get_item_details_by_id(item_id) item_value = await self.parse_item_value(item_dict, return_int=False) name = item_dict['name'] item_page_url = API_BASE_URL + f"a=373/{name.replace(' ', '+')}/viewitem?obj={item_id}" with utils.Embed() as embed: embed.set_author(name=name, url=item_page_url, icon_url=item_dict['icon']) embed.set_thumbnail(url=item_dict['icon_large']) embed.add_field('Value', f'{item_value} coins', inline=False) embed.add_field(f'Examine {name}', item_dict['description'], inline=False) embed.add_field('Members', MEMBERS_MAPPING[item_dict['members']], inline=False) return await ctx.send(embed=embed) else: return await ctx.send('Item not found')
async def roll_dice(self, ctx: utils.Context, dice_limit: int, multiplier: int, bet: localutils.BetAmount): """ Roll the dice on the user's bet. """ # Work out what the user's rolled rolled_number = random.randint(1, 100) user_won = rolled_number > dice_limit # Work out what to say to the user embed = utils.Embed(title=f"\N{GAME DIE} {rolled_number}") if user_won: embed.colour = discord.Colour.green() embed.description = "You won! :D" if bet.amount: embed.description = f"You won! Added **{bet.amount * (multiplier - 1):,}** to your account! :D" win_amount = bet.amount * (multiplier - 1) else: embed.colour = discord.Colour.red() embed.description = "You lost :c" if bet.amount: embed.description = f"You lost, removed **{bet.amount:,}** from your account :c" win_amount = -bet.amount # Tell the user all is well self.bot.dispatch("transaction", ctx.author, bet.currency, win_amount, ctx.command.name.upper(), user_won) return await ctx.send(embed=embed)
async def points_leaderboard(self, ctx: utils.Context): """ Create a points leaderboard. """ # See if they're running a subcommand if ctx.invoked_subcommand is not None: return # Get data async with self.bot.database() as db: rows = await db( "SELECT * FROM user_points WHERE guild_id=$1 AND points > 0 ORDER BY points DESC", ctx.guild.id) # Format it into an embed valid_users = [] for i in rows: member = ctx.guild.get_member(i['user_id']) if member is None: continue valid_users.append(f"{member.mention}: {i['points']:,}") if len(valid_users) >= 30: break with utils.Embed(use_random_colour=True) as embed: embed.description = '\n'.join( valid_users) or 'Nobody is on here :c' # Output await ctx.send(embed=embed)
async def dnd_class(self, ctx: vbu.Context, *, class_name: str): """ Gives you information on a D&D class. """ async with ctx.typing(): data = await self.send_web_request("classes", class_name) if not data: return await ctx.send( "I couldn't find any information for that class.", wait=False) embed = vbu.Embed( use_random_colour=True, title=data['name'], ).add_field( "Proficiencies", ", ".join([i['name'] for i in data['proficiencies']]), ).add_field( "Saving Throws", ", ".join([i['name'] for i in data['saving_throws']]), ).add_field( "Starting Equipment", "\n".join([ f"{i['quantity']}x {i['equipment']['name']}" for i in data['starting_equipment'] ]), ) return await ctx.send(embed=embed, wait=False)
async def wolfram(self, ctx, *, search: str): """ Ping some data to WolframAlpha. """ params = { "input": search, "appid": self.bot.config['api_keys']['wolfram'], "format": "image", "output": "json", } headers = { "User-Agent": self.bot.user_agent, } async with ctx.typing(): async with self.bot.session.get( "https://api.wolframalpha.com/v2/query", params=params, headers=headers) as r: data = json.loads(await r.text()) try: pod = data['queryresult']['pods'][1] # await ctx.send(pod['subpods'][0]['img']) return await ctx.reply( embed=utils.Embed(title=pod['title'], use_random_colour=True ).set_image(pod['subpods'][0]['img']['src'])) except (KeyError, IndexError): return await ctx.reply("No results for that query!")
async def httpcat(self, ctx: utils.Context, errorcode: str): """ Gives you a cat based on an HTTP error code. """ standard_errorcodes = [error.value for error in http.HTTPStatus] if errorcode in ('random', 'rand', 'r'): errorcode = random.choice(standard_errorcodes) else: try: errorcode = int(errorcode) except ValueError: return ctx.channel.send( 'Converting to "int" failed for parameter "errorcode".') await ctx.channel.trigger_typing() headers = {"User-Agent": self.bot.user_agent} async with self.bot.session.get(f"https://http.cat/{errorcode}", headers=headers) as r: if r.status == 404: if errorcode not in standard_errorcodes: await ctx.send("That HTTP code doesn't exist.") else: await ctx.send('Image for HTTP code not found on provider.' ) return if r.status != 200: await ctx.send( f'Something went wrong, try again later. ({r.status})') return with utils.Embed(use_random_colour=True) as embed: embed.set_image(url=f'https://http.cat/{errorcode}') await ctx.send(embed=embed)
async def rtdm_js(self, ctx, *, obj: str): """ Gives you a documentation link for a Javascript entity. """ url = "https://developer.mozilla.org/api/v1/search" params = { 'q': obj, 'local': 'en-US', } headers = { 'User-Agent': self.bot.user_agent, } async with self.bot.session.get(url, params=params, headers=headers) as r: data = await r.json() if not data['documents']: return await ctx.send("I couldn't find anything. Sorry.") embed = vbu.Embed(use_random_colour=True, description="") for i in data['documents']: if 'web/javascript' not in i['slug']: continue embed.description += f"[`{i['title']}`](https://developer.mozilla.org{i['mdn_url']})\n" if embed.description.count("\n") >= 8: break return await ctx.send(embed=embed)
async def displayplant(self, ctx: utils.Context, user: typing.Optional[utils.converters.UserID], *, plant_name: str): """ Shows you your plant status. """ # Get data from database user = discord.Object(user) if user else ctx.author async with self.bot.database() as db: plant_rows = await db( "SELECT * FROM plant_levels WHERE user_id=$1 AND LOWER(plant_name)=LOWER($2)", user.id, plant_name) if not plant_rows: return await ctx.send( f"You have no plant named **{plant_name.capitalize()}**", allowed_mentions=discord.AllowedMentions(users=False, roles=False, everyone=False)) # Filter into variables display_utils = self.bot.get_cog("PlantDisplayUtils") if plant_rows: display_data = display_utils.get_display_data(plant_rows[0], user_id=user.id) else: display_data = display_utils.get_display_data(None, user_id=user.id) # Generate text if display_data['plant_type'] is None: if ctx.author.id == user.id: text = f"You don't have a plant yet, {ctx.author.mention}! Run `{ctx.prefix}getplant` to get one!" else: text = f"<@{user.id}> doesn't have a plant yet!" else: text = f"<@{user.id}>'s {display_data['plant_type'].replace('_', ' ')} - **{plant_rows[0]['plant_name']}**" if int(display_data['plant_nourishment']) > 0: if ctx.author.id == user.id: text += "!" elif int(display_data['plant_nourishment']) < 0: if ctx.author.id == user.id: text += f". It's looking a tad... dead. Run `{ctx.prefix}deleteplant {plant_name}` to plant some new seeds." else: text += ". It looks a bit... worse for wear, to say the least." elif int(display_data['plant_nourishment']) == 0: if ctx.author.id == user.id: text += f". There are some seeds there, but you need to `{ctx.prefix}water {plant_rows[0]['plant_name']}` them to get them to grow." else: text += ". There are some seeds there I think, but they need to be watered." # Send image image_data = display_utils.image_to_bytes( display_utils.get_plant_image(**display_data)) file = discord.File(image_data, filename="plant.png") embed = utils.Embed( use_random_colour=True, description=text).set_image("attachment://plant.png") ctx._set_footer(embed) await ctx.send(embed=embed, file=file)
async def nuget(self, ctx: vbu.Context, package_name: str): """ Check nuget for a package. """ # Get our data async with self.bot.session.get( f"https://azuresearch-usnc.nuget.org/query?q={package_name}") as e: if e.status != 200: await ctx.send("Something went wrong, try again later...") return data = await e.json() # make a lil embed with vbu.Embed(use_random_colour=True) as embed: if data['data']: embed.set_author( name=data['data'][0]['title'], url= f"https://www.nuget.org/packages/{data['data'][0]['id']}") embed.description = data['data'][0]['description'] else: await ctx.send( f"I could not find anything for `{package_name}` :c") return await ctx.send(embed=embed)
async def showallold(self, ctx: utils.Context, user: typing.Optional[discord.User]): """ Show you all of your plants. """ # Get data from database user = user or ctx.author async with self.bot.database() as db: plant_rows = await db("SELECT * FROM plant_levels WHERE user_id=$1 ORDER BY plant_name DESC", user.id) if not plant_rows: return await ctx.send(f"<@{user.id}> has no available plants.", allowed_mentions=discord.AllowedMentions(users=[ctx.author])) await ctx.trigger_typing() # Filter into variables display_utils = self.bot.get_cog("PlantDisplayUtils") plant_rows = display_utils.sort_plant_rows(plant_rows) images = [] for plant_row in plant_rows: if plant_row: display_data = display_utils.get_display_data(plant_row, user_id=user.id) else: display_data = display_utils.get_display_data(None, user_id=user.id) images.append(display_utils.get_plant_image(**display_data)) # Get our images image = display_utils.compile_plant_images(*images) image_to_send = display_utils.image_to_bytes(image) text = f"Here are all of <@{user.id}>'s plants!" file = discord.File(image_to_send, filename="plant.png") embed = utils.Embed(use_random_colour=True, description=text).set_image("attachment://plant.png") ctx.bot.set_footer_from_config(embed) await ctx.send(embed=embed, file=file)
async def wikihow(self, ctx: utils.Context): """That classic ol wikihow game""" if self.possible_images is None: await self.load_images() choices = random.choices(self.possible_images, k=4) chosen_image = choices[0] random.shuffle(choices) with utils.Embed(use_random_colour=True) as embed: embed.set_image(url=self.IMAGE_DIRECTORY + chosen_image.lower() + '.jpg') # await ctx.send(self.IMAGE_DIRECTORY + chosen_image.lower() + '.jpg') embed.description = ''.join(( "1\N{COMBINING ENCLOSING KEYCAP} How to... {0}\n".format( choices[0].lower().replace('-', ' ')), "2\N{COMBINING ENCLOSING KEYCAP} How to... {0}\n".format( choices[1].lower().replace('-', ' ')), "3\N{COMBINING ENCLOSING KEYCAP} How to... {0}\n".format( choices[2].lower().replace('-', ' ')), "4\N{COMBINING ENCLOSING KEYCAP} How to... {0}\n".format( choices[3].lower().replace('-', ' ')), )) m = await ctx.send(embed=embed) for e in [ "1\N{COMBINING ENCLOSING KEYCAP}", "2\N{COMBINING ENCLOSING KEYCAP}", "3\N{COMBINING ENCLOSING KEYCAP}", "4\N{COMBINING ENCLOSING KEYCAP}" ]: await m.add_reaction(e)
async def httpdog(self, ctx: vbu.Context, errorcode: str): """ Gives you a dog based on an HTTP error code. """ standard_errorcodes = [error.value for error in http.HTTPStatus] if errorcode in ('random', 'rand', 'r'): errorcode = random.choice(standard_errorcodes) else: try: errorcode = int(errorcode) except ValueError: return ctx.channel.send( 'Converting to "int" failed for parameter "errorcode".') await ctx.trigger_typing() headers = {"User-Agent": self.bot.user_agent} async with self.bot.session.get( f"https://httpstatusdogs.com/img/{errorcode}.jpg", headers=headers, allow_redirects=False) as r: if str(r.status)[0] != "2": if errorcode not in standard_errorcodes: await ctx.send("That HTTP code doesn't exist.", wait=False) else: await ctx.send( 'Image for HTTP code not found on provider.', wait=False) return with vbu.Embed(use_random_colour=True) as embed: embed.set_image( url=f'https://httpstatusdogs.com/img/{errorcode}.jpg') await ctx.send(embed=embed, wait=False)
async def bot(self, ctx: utils.Context, bot: discord.User): """ Gives you information about a bot. """ if bot.bot is False: return await ctx.send("That isn't even a bot.") bot_info = [ i for i in self.bot.config['bot_info'] if i['user_id'] == bot.id ] if not bot_info: return await ctx.send( f"I don't have any information on record about {bot.mention}.") bot_info = bot_info[0] with utils.Embed(use_random_colour=True) as embed: embed.set_author_to_user(user=bot) embed.description = bot_info['description'] for field in bot_info.get('fields', list()): embed.add_field(name=field['name'], value=field['value'], inline=field.get('inline', False)) embed.set_thumbnail(url=bot.avatar_url) if bot_info.get('image'): embed.set_image(url=bot_info['image']) return await ctx.send(embed=embed)
async def rtdm_dotnet(self, ctx, *, obj: str): """ Gives you a documentation link for a Javascript entity. """ url = "https://docs.microsoft.com/api/apibrowser/dotnet/search" params = { 'api-version': '0.2', 'search': obj, 'locale': 'en-us', '$filter': "monikers/any(t: t eq 'net-5.0')", } headers = { 'User-Agent': self.bot.user_agent, } async with self.bot.session.get(url, params=params, headers=headers) as r: data = await r.json() if not data['results']: return await ctx.send("I couldn't find anything. Sorry.") embed = vbu.Embed(use_random_colour=True, description="") for i in data['results']: embed.description += f"[`{i['displayName']}`]({i['url']})\n" if embed.description.count("\n") >= 8: break return await ctx.send(embed=embed)
async def list(self, ctx: utils.Context, user: discord.Member = None): """List who's simping for you""" user = user or ctx.author simp_user = localutils.SimpableUser.get_simpable_user( user.id, ctx.guild.id) simping_for = [ o for o in [ctx.guild.get_member(i.user_id) for i in simp_user.simping_for] if o ] being_simped_by = [ o for o in [ ctx.guild.get_member(i.user_id) for i in simp_user.being_simped_by ] if o ] mutual_simping = [i for i in simping_for if i in being_simped_by] with utils.Embed(use_random_colour=True) as embed: embed.set_author_to_user(user) # Add simping for if [i for i in simping_for if i not in mutual_simping]: embed.add_field("Simping For", ", ".join([ i.mention for i in simping_for if i not in mutual_simping ]), inline=False) else: if not mutual_simping: embed.add_field("Simping For", "Nobody... \N{THINKING FACE}") else: embed.add_field("Simping For", "Nobody") # Add being simped by if [i for i in being_simped_by if i not in mutual_simping]: embed.add_field("Being Simped By", ", ".join([ i.mention for i in being_simped_by if i not in mutual_simping ]), inline=False) else: if not mutual_simping: embed.add_field("Being Simped By", "Nobody... \N{UNAMUSED FACE}") else: embed.add_field("Being Simped By", "Nobody") # Add mutuals if mutual_simping: embed.add_field("Mutual Simping owo", ", ".join([i.mention for i in mutual_simping]), inline=False) # And done return await ctx.send(embed=embed)
async def avatar(self, ctx: utils.Context, user: discord.User = None): """Shows you the avatar of a given user""" if user is None: user = ctx.author with utils.Embed(use_random_colour=True) as embed: embed.set_image(url=user.avatar_url) await ctx.send(embed=embed)
async def update_shop_message(self, guild: discord.Guild): """ Edit the shop message to to be pretty good. """ # Get the shop message self.logger.info(f"Shop message update dispatched (G{guild.id})") try: shop_channel = self.bot.get_channel( self.bot.guild_settings[guild.id]['shop_channel_id']) shop_message = await shop_channel.fetch_message( self.bot.guild_settings[guild.id]['shop_message_id']) if shop_message is None: self.logger.info( f"Can't update shop message - no message found (G{guild.id})" ) raise AttributeError() except (discord.NotFound, AttributeError): self.logger.info( f"Can't update shop message - no message/channel found (G{guild.id})" ) return # Generate embed coin_emoji = self.bot.guild_settings[guild.id].get("coin_emoji", None) or "coins" emojis = [] with utils.Embed() as embed: for emoji, data in self.get_shop_items(guild).items(): item_price = self.bot.guild_settings[guild.id].get( data['price_key'], data['amount']) if item_price <= 0: continue embed.add_field( f"{data['name']} ({emoji}) - {item_price} {coin_emoji}", data['description'], inline=False) emojis.append(emoji) # See if we need to edit the message try: current_embed = shop_message.embeds[0] except IndexError: current_embed = None if embed == current_embed: self.logger.info( f"Not updating shop message - no changes presented (G{guild.id})" ) return # Edit message self.logger.info(f"Updating shop message (G{guild.id})") await shop_message.edit(content=None, embed=embed) # Add reactions await shop_message.clear_reactions() for e in emojis: await shop_message.add_reaction(e)
async def coaster_data(self, ctx: utils.Context, coaster_id: int): """Get data for a specific coaster""" # Grab page data async with self.bot.session.get(f"https://rcdb.com/{coaster_id}.htm", headers=self.HEADERS) as r: text = await r.text() # Get features soup = BeautifulSoup(text, "html.parser") data = soup.find(class_="stat-tbl") x = data.find("tbody") v = [] while True: y = list(x) for i in y: if isinstance(i, str): v.append(i) elif i.name == 'span': v.append(i.text) try: x = y[-1].children except (IndexError, AttributeError): break b = [] continue_next = False for index, i in enumerate(v): if continue_next: continue_next = False continue if i.strip().lower() == 'elements': break try: if v[index + 1].strip() in ['ft', 'mph', 'ft tall', 'ft long', '°']: b.append(f"{i}{v[index + 1].strip()}") continue_next = True else: b.append(i) except IndexError: b.append(i) features = {} for index, i in enumerate(b[::2]): try: features[i] = b[(index * 2) + 1] except IndexError: features = {} break title = soup.title.text image = "https://rcdb.com" + soup.find(id="opfAnchor")['data-url'] # Wew that took a while - let's make that into an embed now with utils.Embed(use_random_colour=True) as embed: embed.set_author(name=title, url=r.url) embed.set_image(image) for i, o in features.items(): embed.add_field(i, o, True) await ctx.send(embed=embed)
def formatter(menu, data): return vbu.Embed( use_random_colour=True, title=data[0][0] ).set_image( data[0][1] ).set_footer( f"Page {menu.current_page + 1}/{menu.max_pages}" )
async def movie(self, ctx: utils.Context, *, name: str): """Searches for a movie on the OMDB API""" # See if we gave a year original_name = name if name.split(' ')[-1].isdigit() and int(name.split(' ')[-1]) > 1900: *name, year = name.split(' ') name = ' '.join(name) else: year = None # Build up the params params = { 'apikey': self.bot.config['api_keys']['omdb'], 't': name, 'type': 'movie' } if year: params.update({'year': year}) # Send the request async with self.bot.session.get("http://www.omdbapi.com/", params=params) as r: data = await r.json() # Build an embed if data.get('Title') is None: return await ctx.invoke(self.bot.get_command("movie search"), name=original_name) with utils.Embed(use_random_colour=True, title=f"{data['Title']} ({data['Year']})") as embed: if data['Plot']: embed.description = data['Plot'] if data['Released']: embed.add_field("Release Date", data['Released']) if data['Rated']: embed.add_field("Age Rating", data['Rated']) if data['Runtime']: embed.add_field("Runtime", data['Runtime']) if data['Genre']: embed.add_field("Genre", data['Genre']) if data['imdbRating']: embed.add_field("IMDB Rating", data['imdbRating']) if data['Production']: embed.add_field("Production Company", data['Production']) if data['Director']: embed.add_field("Director", data['Director']) if data['Writer']: embed.add_field("Writer", data['Writer'], inline=False) if data['imdbID']: embed.add_field( "IMDB Page", f"[Direct Link](https://www.imdb.com/title/{data['imdbID']}/) - IMDB ID `{data['imdbID']}`", inline=False) if data['Poster']: embed.set_thumbnail(data['Poster']) return await ctx.send(embed=embed)
async def quote_list(self, ctx: vbu.Context, user: discord.Member=None): """ List the IDs of quotes for a user. """ # Grab data from db user = user or ctx.author async with self.bot.database() as db: rows = await db("SELECT quote_id FROM user_quotes WHERE user_id=$1 AND guild_id=$2", user, ctx.guild.id) if not rows: embed = vbu.Embed( use_random_colour=True, description="This user has no quotes.", ).set_author_to_user(user) return await ctx.send(embed=embed) embed = vbu.Embed( use_random_colour=True, description="\n".join([i['quote_id'] for i in rows[:50]]), ).set_author_to_user(user) return await ctx.send(embed=embed)
async def inventory(self, ctx: utils.Context, user: typing.Optional[discord.User]): """ Show you the inventory of a user. """ # Get user info user = user or ctx.author async with self.bot.database() as db: user_rows = await db( "SELECT * FROM user_settings WHERE user_id=$1", user.id) plant_rows = await db( "SELECT * FROM plant_levels WHERE user_id=$1", user.id) user_inventory_rows = await db( "SELECT * FROM user_inventory WHERE user_id=$1 AND amount > 0", user.id) # Start our embed embed = utils.Embed(use_random_colour=True, description="") ctx.bot.set_footer_from_config(embed) # Format exp into a string if user_rows: exp_value = user_rows[0]['user_experience'] else: exp_value = 0 embed.description += f"<@{user.id}> has **{exp_value:,}** experience.\n" # Format plant limit into a string if user_rows: plant_limit = user_rows[0]['plant_limit'] else: plant_limit = 1 they_you = {True: "you", False: "they"}.get(user.id == ctx.author.id) their_your = { True: "your", False: "their" }.get(user.id == ctx.author.id) if plant_limit == len(plant_rows): embed.description += (( f"{they_you.capitalize()} are currently using all of {their_your} " f"available {plant_limit} plant pots.\n")) else: embed.description += (( f"{they_you.capitalize()} are currently using {len(plant_rows)} of " f"{their_your} available {plant_limit} plant pots.\n")) # Format inventory into a string if user_inventory_rows: inventory_string = "\n".join([ f"{row['item_name'].replace('_', ' ').capitalize()} x{row['amount']:,}" for row in user_inventory_rows ]) embed.add_field("Inventory", inventory_string) # Return to user return await ctx.send(embed=embed)
async def commit_poster_loop(self, embed_title: str, api_url: str, repo_url: str): """Grab the data from the Discord datamining repo and post it to the coding channel of VFL""" # Grab the data self.logger.info(f"Grabbing repo data from {api_url}") async with self.bot.session.get(api_url) as r: data = await r.json() # Let's work out the new data new_commits = [] if self.last_posted_commit[repo_url] is None: self.last_posted_commit[repo_url] = data[0]['sha'] self.logger.info("Setting to last commit - no commits cached") return for index, i in enumerate(data): if i['sha'] == self.last_posted_commit[repo_url]: new_commits = data[:index] break # See if we have anything to talk about if not new_commits: self.logger.info("No new commits found") return self.logger.info(f"Logging info of {len(new_commits)} commits") # Work out which of our new commits have comments comment_urls = [ i['comments_url'] for i in new_commits if i['commit']['comment_count'] > 0 ] comment_text = [] for url in comment_urls: async with self.bot.session.get(url) as r: data = await r.json() comment_text.extend([(i['commit_id'], re.sub(r"^## (.+)", r"**\1**", i['body'])) for i in data]) self.logger.info(f"Logging info of {len(comment_text)} comments") # Format it all into an embed with utils.Embed(use_random_colour=True) as embed: embed.title = embed_title embed.description = '\n'.join([ f"{i['commit']['message']} - [Link]({repo_url}commit/{i['sha']})" for i in new_commits ]) for sha, body in comment_text: embed.add_field(sha, body, inline=False) # And send channel = self.bot.get_channel(self.VFL_CODING_CHANNEL_ID) m = await channel.send(embed=embed) await m.publish() self.logger.info("Sent data to channel") self.last_posted_commit[repo_url] = new_commits[0]['sha']
async def daily(self, ctx: utils.Context): """ Get money on the daily. """ async with self.bot.database() as db: # See which currencies allow faily command all_guild_currencies = await db( """SELECT currency_name FROM guild_currencies WHERE guild_id=$1 AND allow_daily_command=true""", ctx.guild.id, ) # Check out last run commands allowed_daily_currencies = await db( """SELECT currency_name, last_daily_command FROM user_money WHERE user_money.guild_id=$1 AND user_money.user_id=$2 AND currency_name=ANY($3::TEXT[])""", ctx.guild.id, ctx.author.id, [i['currency_name'] for i in all_guild_currencies], ) # Work out when each thing was last run allowed_daily_dict = {} for row in all_guild_currencies: allowed_daily_dict[row['currency_name']] = dt(2000, 1, 1) for row in allowed_daily_currencies: allowed_daily_dict[row['currency_name']] = row['last_daily_command'] if not allowed_daily_dict: return await ctx.send("There's nothing available for use with the daily command right now.") # Work out how much we're adding changed_daily = {} for currency_name, last_run_time in allowed_daily_dict.items(): if last_run_time > dt.utcnow() - self.DAILY_COMMAND_TIMEOUT: continue amount = random.randint(9_000, 13_000) await db( """INSERT INTO user_money (user_id, guild_id, currency_name, money_amount, last_daily_command) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (user_id, guild_id, currency_name) DO UPDATE SET money_amount=user_money.money_amount+excluded.money_amount, last_daily_command=excluded.last_daily_command""", ctx.author.id, ctx.guild.id, currency_name, amount, ctx.message.created_at, ) self.bot.dispatch("transaction", ctx.author, currency_name, amount, "DAILY_COMMAND") changed_daily[row['currency_name']] = amount # Make them into an embed if not changed_daily: soonest_allow_daily = max(allowed_daily_dict.values()) soonest_tv = utils.TimeValue((soonest_allow_daily - (dt.utcnow() - self.DAILY_COMMAND_TIMEOUT)).total_seconds()) return await ctx.send(f"You can't get anything with the daily command for another **{soonest_tv.clean_full}**.") embed = utils.Embed(use_random_colour=True) description_list = [] for currency, amount in changed_daily.items(): currency_name = currency.title() if currency.lower() == currency else currency description_list.append(f"**{currency_name}** - {amount}") embed.description = "\n".join(description_list) return await ctx.send(embed=embed)
def formatter(menu, items): # Create the embed commands_embed = vbu.Embed(title="Command Data (times run)") # Add the total count footer commands_embed.set_footer(text=f"Total: {total_count}") # Add the command list to the emebd commands_embed.description = "\n".join(items) # Return the embed return commands_embed
def get_embed_from_cache(self, cache, obj) -> dict: """ Build up some kwargs from the cache and a given input object. """ item_casefold = obj.casefold() split = item_casefold.split('.') outputs = [] for key, link in cache.items(): # Key would be something like 'TextChannel.fetch', now 'textchannel.fetch' key_casefold = key.casefold() # See if we got an exact match if item_casefold in key_casefold: if item_casefold == key_casefold: outputs.append((key, link, 20,)) else: outputs.append((key, link, 15,)) # See if we're looking for a method if len(split) == 1: continue # Search by method if split[1] and split[1] in key_casefold: if split[1] == key_casefold: outputs.append((key, link, 12,)) else: outputs.append((key, link, 10,)) # Search by class if split[0] and split[0] in key_casefold: if split[0] == key_casefold: outputs.append((key, link, 7,)) else: outputs.append((key, link, 5,)) # Hey maybe they didn't say anything useful if len(outputs) == 0: return {"content": "I couldn't find anything. Sorry."} # Yo there's a result. Let's embed that. embed = utils.Embed(use_random_colour=True) outputs.sort(key=lambda i: (i[2], i[0]), reverse=True) embed.description = "" for key, url, weight in outputs: v = f"[`{key}`]({url})\n" if v in embed.description: continue embed.description += v if embed.description.count("\n") >= 8: break return {"embed": embed}
async def panda(self, ctx: utils.Context): """Gives you some panda pictures""" await ctx.channel.trigger_typing() headers = {"User-Agent": "Apple.py/0.0.1 - Discord@Caleb#2831"} async with self.bot.session.get("https://some-random-api.ml/img/panda", headers=headers) as r: data = await r.json() with utils.Embed(use_random_colour=True) as embed: embed.set_image(url=data['link']) await ctx.send(embed=embed)