aboutsummaryrefslogtreecommitdiffstats
path: root/bot/exts/evergreen
diff options
context:
space:
mode:
Diffstat (limited to 'bot/exts/evergreen')
-rw-r--r--bot/exts/evergreen/emoji_count.py94
-rw-r--r--bot/exts/evergreen/fun.py24
-rw-r--r--bot/exts/evergreen/githubinfo.py98
-rw-r--r--bot/exts/evergreen/issues.py5
-rw-r--r--bot/exts/evergreen/minesweeper.py12
-rw-r--r--bot/exts/evergreen/movie.py5
-rw-r--r--bot/exts/evergreen/snakes/_snakes_cog.py4
-rw-r--r--bot/exts/evergreen/trivia_quiz.py6
8 files changed, 179 insertions, 69 deletions
diff --git a/bot/exts/evergreen/emoji_count.py b/bot/exts/evergreen/emoji_count.py
index ef900199..cc43e9ab 100644
--- a/bot/exts/evergreen/emoji_count.py
+++ b/bot/exts/evergreen/emoji_count.py
@@ -1,12 +1,14 @@
import datetime
import logging
import random
-from typing import Dict, Optional
+from collections import defaultdict
+from typing import List, Tuple
import discord
from discord.ext import commands
from bot.constants import Colours, ERROR_REPLIES
+from bot.utils.pagination import LinePaginator
log = logging.getLogger(__name__)
@@ -17,73 +19,77 @@ class EmojiCount(commands.Cog):
def __init__(self, bot: commands.Bot):
self.bot = bot
- def embed_builder(self, emoji: dict) -> discord.Embed:
+ @staticmethod
+ def embed_builder(emoji: dict) -> Tuple[discord.Embed, List[str]]:
"""Generates an embed with the emoji names and count."""
embed = discord.Embed(
color=Colours.orange,
title="Emoji Count",
timestamp=datetime.datetime.utcnow()
)
+ msg = []
if len(emoji) == 1:
- for key, value in emoji.items():
- embed.description = f"There are **{len(value)}** emojis in the **{key}** category"
- embed.set_thumbnail(url=random.choice(value).url)
+ for category_name, category_emojis in emoji.items():
+ if len(category_emojis) == 1:
+ msg.append(f"There is **{len(category_emojis)}** emoji in **{category_name}** category")
+ else:
+ msg.append(f"There are **{len(category_emojis)}** emojis in **{category_name}** category")
+ embed.set_thumbnail(url=random.choice(category_emojis).url)
+
else:
- msg = ''
- for key, value in emoji.items():
- emoji_choice = random.choice(value)
- emoji_info = f'There are **{len(value)}** emojis in the **{key}** category\n'
- msg += f'<:{emoji_choice.name}:{emoji_choice.id}> {emoji_info}'
- embed.description = msg
- return embed
+ for category_name, category_emojis in emoji.items():
+ emoji_choice = random.choice(category_emojis)
+ if len(category_emojis) > 1:
+ emoji_info = f"There are **{len(category_emojis)}** emojis in **{category_name}** category"
+ else:
+ emoji_info = f"There is **{len(category_emojis)}** emoji in **{category_name}** category"
+ if emoji_choice.animated:
+ msg.append(f'<a:{emoji_choice.name}:{emoji_choice.id}> {emoji_info}')
+ else:
+ msg.append(f'<:{emoji_choice.name}:{emoji_choice.id}> {emoji_info}')
+ return embed, msg
@staticmethod
- def generate_invalid_embed(ctx: commands.Context) -> discord.Embed:
- """Genrates error embed."""
+ def generate_invalid_embed(emojis: list) -> Tuple[discord.Embed, List[str]]:
+ """Generates error embed."""
embed = discord.Embed(
color=Colours.soft_red,
title=random.choice(ERROR_REPLIES)
)
+ msg = []
- emoji_dict = {}
- for emoji in ctx.guild.emojis:
- emoji_dict[emoji.name.split("_")[0]] = []
+ emoji_dict = defaultdict(list)
+ for emoji in emojis:
+ emoji_dict[emoji.name.split("_")[0]].append(emoji)
- error_comp = ', '.join(key for key in emoji_dict.keys())
- embed.description = f"These are the valid categories\n```{error_comp}```"
- return embed
+ error_comp = ', '.join(emoji_dict)
+ msg.append(f"These are the valid categories\n```{error_comp}```")
+ return embed, msg
- def emoji_list(self, ctx: commands.Context, categories: dict) -> Dict:
- """Generates an embed with the emoji names and count."""
- out = {category: [] for category in categories}
+ @commands.command(name="emojicount", aliases=["ec", "emojis"])
+ async def emoji_count(self, ctx: commands.Context, *, category_query: str = None) -> None:
+ """Returns embed with emoji category and info given by the user."""
+ emoji_dict = defaultdict(list)
+ if not ctx.guild.emojis:
+ await ctx.send("No emojis found.")
+ return
+ log.trace(f"Emoji Category {'' if category_query else 'not '}provided by the user")
for emoji in ctx.guild.emojis:
- category = emoji.name.split('_')[0]
- if category in out:
- out[category].append(emoji)
- return out
-
- @commands.command(name="emoji_count", aliases=["ec"])
- async def ec(self, ctx: commands.Context, *, emoji: str = None) -> Optional[str]:
- """Returns embed with emoji category and info given by the user."""
- emoji_dict = {}
+ emoji_category = emoji.name.split("_")[0]
- for a in ctx.guild.emojis:
- if emoji is None:
- log.trace("Emoji Category not provided by the user")
- emoji_dict.update({a.name.split("_")[0]: []})
- elif a.name.split("_")[0] in emoji:
- log.trace("Emoji Category provided by the user")
- emoji_dict.update({a.name.split("_")[0]: []})
+ if category_query is not None and emoji_category not in category_query:
+ continue
- emoji_dict = self.emoji_list(ctx, emoji_dict)
+ emoji_dict[emoji_category].append(emoji)
- if len(emoji_dict) == 0:
- embed = self.generate_invalid_embed(ctx)
+ if not emoji_dict:
+ log.trace("Invalid name provided by the user")
+ embed, msg = self.generate_invalid_embed(ctx.guild.emojis)
else:
- embed = self.embed_builder(emoji_dict)
- await ctx.send(embed=embed)
+ embed, msg = self.embed_builder(emoji_dict)
+ await LinePaginator.paginate(lines=msg, ctx=ctx, embed=embed)
def setup(bot: commands.Bot) -> None:
diff --git a/bot/exts/evergreen/fun.py b/bot/exts/evergreen/fun.py
index de6a92c6..101725da 100644
--- a/bot/exts/evergreen/fun.py
+++ b/bot/exts/evergreen/fun.py
@@ -7,10 +7,10 @@ from typing import Callable, Iterable, Tuple, Union
from discord import Embed, Message
from discord.ext import commands
-from discord.ext.commands import Bot, Cog, Context, MessageConverter, clean_content
+from discord.ext.commands import BadArgument, Bot, Cog, Context, MessageConverter, clean_content
from bot import utils
-from bot.constants import Colours, Emojis
+from bot.constants import Client, Colours, Emojis
log = logging.getLogger(__name__)
@@ -57,18 +57,20 @@ class Fun(Cog):
with Path("bot/resources/evergreen/caesar_info.json").open("r", encoding="UTF-8") as f:
self._caesar_cipher_embed = json.load(f)
+ @staticmethod
+ def _get_random_die() -> str:
+ """Generate a random die emoji, ready to be sent on Discord."""
+ die_name = f"dice_{random.randint(1, 6)}"
+ return getattr(Emojis, die_name)
+
@commands.command()
async def roll(self, ctx: Context, num_rolls: int = 1) -> None:
"""Outputs a number of random dice emotes (up to 6)."""
- output = ""
- if num_rolls > 6:
- num_rolls = 6
- elif num_rolls < 1:
- output = ":no_entry: You must roll at least once."
- for _ in range(num_rolls):
- dice = f"dice_{random.randint(1, 6)}"
- output += getattr(Emojis, dice, '')
- await ctx.send(output)
+ if 1 <= num_rolls <= 6:
+ dice = " ".join(self._get_random_die() for _ in range(num_rolls))
+ await ctx.send(dice)
+ else:
+ raise BadArgument(f"`{Client.prefix}roll` only supports between 1 and 6 rolls.")
@commands.command(name="uwu", aliases=("uwuwize", "uwuify",))
async def uwu_command(self, ctx: Context, *, text: clean_content(fix_channel_mentions=True)) -> None:
diff --git a/bot/exts/evergreen/githubinfo.py b/bot/exts/evergreen/githubinfo.py
new file mode 100644
index 00000000..2e38e3ab
--- /dev/null
+++ b/bot/exts/evergreen/githubinfo.py
@@ -0,0 +1,98 @@
+import logging
+import random
+from datetime import datetime
+from typing import Optional
+
+import discord
+from discord.ext import commands
+from discord.ext.commands.cooldowns import BucketType
+
+from bot.constants import NEGATIVE_REPLIES
+
+log = logging.getLogger(__name__)
+
+
+class GithubInfo(commands.Cog):
+ """Fetches info from GitHub."""
+
+ def __init__(self, bot: commands.Bot):
+ self.bot = bot
+
+ async def fetch_data(self, url: str) -> dict:
+ """Retrieve data as a dictionary."""
+ async with self.bot.http_session.get(url) as r:
+ return await r.json()
+
+ @commands.command(name='github', aliases=['gh'])
+ @commands.cooldown(1, 60, BucketType.user)
+ async def get_github_info(self, ctx: commands.Context, username: Optional[str]) -> None:
+ """
+ Fetches a user's GitHub information.
+
+ Username is optional and sends the help command if not specified.
+ """
+ if username is None:
+ await ctx.invoke(self.bot.get_command('help'), 'github')
+ ctx.command.reset_cooldown(ctx)
+ return
+
+ async with ctx.typing():
+ user_data = await self.fetch_data(f"https://api.github.com/users/{username}")
+
+ # User_data will not have a message key if the user exists
+ if user_data.get('message') is not None:
+ await ctx.send(embed=discord.Embed(title=random.choice(NEGATIVE_REPLIES),
+ description=f"The profile for `{username}` was not found.",
+ colour=discord.Colour.red()))
+ return
+
+ org_data = await self.fetch_data(user_data['organizations_url'])
+ orgs = [f"[{org['login']}](https://github.com/{org['login']})" for org in org_data]
+ orgs_to_add = ' | '.join(orgs)
+
+ gists = user_data['public_gists']
+
+ # Forming blog link
+ if user_data['blog'].startswith("http"): # Blog link is complete
+ blog = user_data['blog']
+ elif user_data['blog']: # Blog exists but the link is not complete
+ blog = f"https://{user_data['blog']}"
+ else:
+ blog = "No website link available"
+
+ embed = discord.Embed(
+ title=f"`{user_data['login']}`'s GitHub profile info",
+ description=f"```{user_data['bio']}```\n" if user_data['bio'] is not None else "",
+ colour=0x7289da,
+ url=user_data['html_url'],
+ timestamp=datetime.strptime(user_data['created_at'], "%Y-%m-%dT%H:%M:%SZ")
+ )
+ embed.set_thumbnail(url=user_data['avatar_url'])
+ embed.set_footer(text="Account created at")
+
+ if user_data['type'] == "User":
+
+ embed.add_field(name="Followers",
+ value=f"[{user_data['followers']}]({user_data['html_url']}?tab=followers)")
+ embed.add_field(name="\u200b", value="\u200b")
+ embed.add_field(name="Following",
+ value=f"[{user_data['following']}]({user_data['html_url']}?tab=following)")
+
+ embed.add_field(name="Public repos",
+ value=f"[{user_data['public_repos']}]({user_data['html_url']}?tab=repositories)")
+ embed.add_field(name="\u200b", value="\u200b")
+
+ if user_data['type'] == "User":
+ embed.add_field(name="Gists", value=f"[{gists}](https://gist.github.com/{username})")
+
+ embed.add_field(name=f"Organization{'s' if len(orgs)!=1 else ''}",
+ value=orgs_to_add if orgs else "No organizations")
+ embed.add_field(name="\u200b", value="\u200b")
+ embed.add_field(name="Website", value=blog)
+
+ await ctx.send(embed=embed)
+
+
+def setup(bot: commands.Bot) -> None:
+ """Adding the cog to the bot."""
+ bot.add_cog(GithubInfo(bot))
diff --git a/bot/exts/evergreen/issues.py b/bot/exts/evergreen/issues.py
index 5a5c82e7..97ee6a12 100644
--- a/bot/exts/evergreen/issues.py
+++ b/bot/exts/evergreen/issues.py
@@ -38,7 +38,7 @@ class Issues(commands.Cog):
) -> None:
"""Command to retrieve issue(s) from a GitHub repository."""
links = []
- numbers = set(numbers)
+ numbers = set(numbers) # Convert from list to set to remove duplicates, if any
if not numbers:
await ctx.invoke(self.bot.get_command('help'), 'issue')
@@ -53,8 +53,7 @@ class Issues(commands.Cog):
await ctx.send(embed=embed)
return
- for number in set(numbers):
- # Convert from list to set to remove duplicates, if any.
+ for number in numbers:
url = f"https://api.github.com/repos/{user}/{repository}/issues/{number}"
merge_url = f"https://api.github.com/repos/{user}/{repository}/pulls/{number}/merge"
diff --git a/bot/exts/evergreen/minesweeper.py b/bot/exts/evergreen/minesweeper.py
index 3e40f493..286ac7a5 100644
--- a/bot/exts/evergreen/minesweeper.py
+++ b/bot/exts/evergreen/minesweeper.py
@@ -120,14 +120,14 @@ class Minesweeper(commands.Cog):
def format_for_discord(board: GameBoard) -> str:
"""Format the board as a string for Discord."""
discord_msg = (
- ":stop_button: :regional_indicator_a::regional_indicator_b::regional_indicator_c:"
- ":regional_indicator_d::regional_indicator_e::regional_indicator_f::regional_indicator_g:"
- ":regional_indicator_h::regional_indicator_i::regional_indicator_j:\n\n"
+ ":stop_button: :regional_indicator_a: :regional_indicator_b: :regional_indicator_c: "
+ ":regional_indicator_d: :regional_indicator_e: :regional_indicator_f: :regional_indicator_g: "
+ ":regional_indicator_h: :regional_indicator_i: :regional_indicator_j:\n\n"
)
rows = []
for row_number, row in enumerate(board):
new_row = f"{MESSAGE_MAPPING[row_number + 1]} "
- new_row += "".join(MESSAGE_MAPPING[cell] for cell in row)
+ new_row += " ".join(MESSAGE_MAPPING[cell] for cell in row)
rows.append(new_row)
discord_msg += "\n".join(rows)
@@ -158,7 +158,7 @@ class Minesweeper(commands.Cog):
if ctx.guild:
await ctx.send(f"{ctx.author.mention} is playing Minesweeper")
- chat_msg = await ctx.send(f"Here's there board!\n{self.format_for_discord(revealed_board)}")
+ chat_msg = await ctx.send(f"Here's their board!\n{self.format_for_discord(revealed_board)}")
else:
chat_msg = None
@@ -176,7 +176,7 @@ class Minesweeper(commands.Cog):
await game.dm_msg.delete()
game.dm_msg = await ctx.author.send(f"Here's your board!\n{self.format_for_discord(game.revealed)}")
if game.activated_on_server:
- await game.chat_msg.edit(content=f"Here's there board!\n{self.format_for_discord(game.revealed)}")
+ await game.chat_msg.edit(content=f"Here's their board!\n{self.format_for_discord(game.revealed)}")
@commands.dm_only()
@minesweeper_group.command(name="flag")
diff --git a/bot/exts/evergreen/movie.py b/bot/exts/evergreen/movie.py
index 93aeef30..340a5724 100644
--- a/bot/exts/evergreen/movie.py
+++ b/bot/exts/evergreen/movie.py
@@ -190,7 +190,10 @@ class Movie(Cog):
async def get_embed(self, name: str) -> Embed:
"""Return embed of random movies. Uses name in title."""
- return Embed(title=f'Random {name} Movies').set_footer(text='Powered by TMDB (themoviedb.org)')
+ embed = Embed(title=f"Random {name} Movies")
+ embed.set_footer(text="This product uses the TMDb API but is not endorsed or certified by TMDb.")
+ embed.set_thumbnail(url="https://i.imgur.com/LtFtC8H.png")
+ return embed
def setup(bot: Bot) -> None:
diff --git a/bot/exts/evergreen/snakes/_snakes_cog.py b/bot/exts/evergreen/snakes/_snakes_cog.py
index a846274b..70bb0e73 100644
--- a/bot/exts/evergreen/snakes/_snakes_cog.py
+++ b/bot/exts/evergreen/snakes/_snakes_cog.py
@@ -1083,13 +1083,13 @@ class Snakes(Cog):
url,
params={
"part": "snippet",
- "q": urllib.parse.quote(query),
+ "q": urllib.parse.quote_plus(query),
"type": "video",
"key": Tokens.youtube
}
)
response = await response.json()
- data = response['items']
+ data = response.get("items", [])
# Send the user a video
if len(data) > 0:
diff --git a/bot/exts/evergreen/trivia_quiz.py b/bot/exts/evergreen/trivia_quiz.py
index 8dceceac..fe692c2a 100644
--- a/bot/exts/evergreen/trivia_quiz.py
+++ b/bot/exts/evergreen/trivia_quiz.py
@@ -121,8 +121,10 @@ class TriviaQuiz(commands.Cog):
# A function to check whether user input is the correct answer(close to the right answer)
def check(m: discord.Message) -> bool:
- ratio = fuzz.ratio(answer.lower(), m.content.lower())
- return ratio > 85 and m.channel == ctx.channel
+ return (
+ m.channel == ctx.channel
+ and fuzz.ratio(answer.lower(), m.content.lower()) > 85
+ )
try:
msg = await self.bot.wait_for('message', check=check, timeout=10)