diff options
author | 2021-01-08 16:21:11 -0800 | |
---|---|---|
committer | 2021-01-08 16:21:11 -0800 | |
commit | c9f83eee557d46b76bda8075fac1198dac8b9d5e (patch) | |
tree | 4cefe2dc352cdaed284a2f8080631ac94d7f0423 /bot | |
parent | Merge branch 'master' into tic-tac-toe (diff) | |
parent | Merge pull request #510 from hedythedev/hackstats (diff) |
Merge remote-tracking branch 'origin/master' into tic-tac-toe
Diffstat (limited to 'bot')
-rw-r--r-- | bot/constants.py | 1 | ||||
-rw-r--r-- | bot/exts/evergreen/snakes/_snakes_cog.py | 101 | ||||
-rw-r--r-- | bot/exts/halloween/hacktoberstats.py | 45 |
3 files changed, 80 insertions, 67 deletions
diff --git a/bot/constants.py b/bot/constants.py index ad850b92..fd4854b9 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -269,6 +269,7 @@ class Roles(NamedTuple): class Tokens(NamedTuple): giphy = environ.get("GIPHY_TOKEN") + aoc_session_cookie = environ.get("AOC_SESSION_COOKIE") omdb = environ.get("OMDB_API_KEY") youtube = environ.get("YOUTUBE_API_KEY") tmdb = environ.get("TMDB_API_KEY") diff --git a/bot/exts/evergreen/snakes/_snakes_cog.py b/bot/exts/evergreen/snakes/_snakes_cog.py index 4fa4dcd1..d5e4f206 100644 --- a/bot/exts/evergreen/snakes/_snakes_cog.py +++ b/bot/exts/evergreen/snakes/_snakes_cog.py @@ -15,6 +15,7 @@ import aiohttp import async_timeout from PIL import Image, ImageDraw, ImageFont from discord import Colour, Embed, File, Member, Message, Reaction +from discord.errors import HTTPException from discord.ext.commands import Bot, Cog, CommandError, Context, bot_has_permissions, group from bot.constants import ERROR_REPLIES, Tokens @@ -151,6 +152,7 @@ class Snakes(Cog): self.snake_idioms = utils.get_resource("snake_idioms") self.snake_quizzes = utils.get_resource("snake_quiz") self.snake_facts = utils.get_resource("snake_facts") + self.num_movie_pages = None # region: Helper methods @staticmethod @@ -739,71 +741,68 @@ class Snakes(Cog): @snakes_group.command(name='movie') async def movie_command(self, ctx: Context) -> None: """ - Gets a random snake-related movie from OMDB. + Gets a random snake-related movie from TMDB. Written by Samuel. Modified by gdude. + Modified by Will Da Silva. """ - url = "http://www.omdbapi.com/" - page = random.randint(1, 27) + # Initially 8 pages are fetched. The actual number of pages is set after the first request. + page = random.randint(1, self.num_movie_pages or 8) - response = await self.bot.http_session.get( - url, - params={ - "s": "snake", - "page": page, - "type": "movie", - "apikey": Tokens.omdb - } - ) - data = await response.json() - movie = random.choice(data["Search"])["imdbID"] - - response = await self.bot.http_session.get( - url, - params={ - "i": movie, - "apikey": Tokens.omdb - } - ) - data = await response.json() - - embed = Embed( - title=data["Title"], - color=SNAKE_COLOR - ) - - del data["Response"], data["imdbID"], data["Title"] - - for key, value in data.items(): - if not value or value == "N/A" or key in ("Response", "imdbID", "Title", "Type"): - continue + async with ctx.typing(): + response = await self.bot.http_session.get( + "https://api.themoviedb.org/3/search/movie", + params={ + "query": "snake", + "page": page, + "language": "en-US", + "api_key": Tokens.tmdb, + } + ) + data = await response.json() + if self.num_movie_pages is None: + self.num_movie_pages = data["total_pages"] + movie = random.choice(data["results"])["id"] + + response = await self.bot.http_session.get( + f"https://api.themoviedb.org/3/movie/{movie}", + params={ + "language": "en-US", + "api_key": Tokens.tmdb, + } + ) + data = await response.json() - if key == "Ratings": # [{'Source': 'Internet Movie Database', 'Value': '7.6/10'}] - rating = random.choice(value) + embed = Embed(title=data["title"], color=SNAKE_COLOR) - if rating["Source"] != "Internet Movie Database": - embed.add_field(name=f"Rating: {rating['Source']}", value=rating["Value"]) + if data["poster_path"] is not None: + embed.set_image(url=f"https://images.tmdb.org/t/p/original{data['poster_path']}") - continue + if data["overview"]: + embed.add_field(name="Overview", value=data["overview"]) - if key == "Poster": - embed.set_image(url=value) - continue + if data["release_date"]: + embed.add_field(name="Release Date", value=data["release_date"]) - elif key == "imdbRating": - key = "IMDB Rating" + if data["genres"]: + embed.add_field(name="Genres", value=", ".join([x["name"] for x in data["genres"]])) - elif key == "imdbVotes": - key = "IMDB Votes" + if data["vote_count"]: + embed.add_field(name="Rating", value=f"{data['vote_average']}/10 ({data['vote_count']} votes)", inline=True) - embed.add_field(name=key, value=value, inline=True) + if data["budget"] and data["revenue"]: + embed.add_field(name="Budget", value=data["budget"], inline=True) + embed.add_field(name="Revenue", value=data["revenue"], inline=True) - embed.set_footer(text="Data provided by the OMDB API") + 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") - await ctx.channel.send( - embed=embed - ) + try: + await ctx.channel.send(embed=embed) + except HTTPException as err: + await ctx.channel.send("An error occurred while fetching a snake-related movie!") + raise err from None @snakes_group.command(name='quiz') @locked() diff --git a/bot/exts/halloween/hacktoberstats.py b/bot/exts/halloween/hacktoberstats.py index 84b75022..a1c55922 100644 --- a/bot/exts/halloween/hacktoberstats.py +++ b/bot/exts/halloween/hacktoberstats.py @@ -1,15 +1,16 @@ import logging +import random import re from collections import Counter from datetime import datetime, timedelta -from typing import List, Tuple, Union +from typing import List, Optional, Tuple, Union import aiohttp import discord from async_rediscache import RedisCache from discord.ext import commands -from bot.constants import Channels, Month, Tokens, WHITELISTED_CHANNELS +from bot.constants import Channels, Month, NEGATIVE_REPLIES, Tokens, WHITELISTED_CHANNELS from bot.utils.decorators import in_month, override_in_channel log = logging.getLogger(__name__) @@ -125,18 +126,28 @@ class HacktoberStats(commands.Cog): async with ctx.typing(): prs = await self.get_october_prs(github_username) + if prs is None: # Will be None if the user was not found + await ctx.send( + embed=discord.Embed( + title=random.choice(NEGATIVE_REPLIES), + description=f"GitHub user `{github_username}` was not found.", + colour=discord.Colour.red() + ) + ) + return + if prs: stats_embed = await self.build_embed(github_username, prs) await ctx.send('Here are some stats!', embed=stats_embed) else: - await ctx.send(f"No valid October GitHub contributions found for '{github_username}'") + await ctx.send(f"No valid Hacktoberfest PRs found for '{github_username}'") async def build_embed(self, github_username: str, prs: List[dict]) -> discord.Embed: """Return a stats embed built from github_username's PRs.""" logging.info(f"Building Hacktoberfest embed for GitHub user: '{github_username}'") in_review, accepted = await self._categorize_prs(prs) - n = len(accepted) + len(in_review) # total number of PRs + n = len(accepted) + len(in_review) # Total number of PRs if n >= PRS_FOR_SHIRT: shirtstr = f"**{github_username} is eligible for a T-shirt or a tree!**" elif n == PRS_FOR_SHIRT - 1: @@ -162,7 +173,7 @@ class HacktoberStats(commands.Cog): icon_url="https://avatars1.githubusercontent.com/u/35706162?s=200&v=4" ) - # this will handle when no PRs in_review or accepted + # This will handle when no PRs in_review or accepted review_str = self._build_prs_string(in_review, github_username) or "None" accepted_str = self._build_prs_string(accepted, github_username) or "None" stats_embed.add_field( @@ -178,7 +189,7 @@ class HacktoberStats(commands.Cog): return stats_embed @staticmethod - async def get_october_prs(github_username: str) -> Union[List[dict], None]: + async def get_october_prs(github_username: str) -> Optional[List[dict]]: """ Query GitHub's API for PRs created during the month of October by github_username. @@ -198,7 +209,8 @@ class HacktoberStats(commands.Cog): "number": int } - Otherwise, return None + Otherwise, return empty list. + None will be returned when the GitHub user was not found. """ logging.info(f"Fetching Hacktoberfest Stats for GitHub user: '{github_username}'") base_url = "https://api.github.com/search/issues?q=" @@ -226,14 +238,15 @@ class HacktoberStats(commands.Cog): # Ignore logging non-existent users or users we do not have permission to see if api_message == GITHUB_NONEXISTENT_USER_MESSAGE: logging.debug(f"No GitHub user found named '{github_username}'") + return else: logging.error(f"GitHub API request for '{github_username}' failed with message: {api_message}") - return + return [] # No October PRs were found due to error if jsonresp["total_count"] == 0: # Short circuit if there aren't any PRs - logging.info(f"No Hacktoberfest PRs found for GitHub user: '{github_username}'") - return + logging.info(f"No October PRs found for GitHub user: '{github_username}'") + return [] logging.info(f"Found {len(jsonresp['items'])} Hacktoberfest PRs for GitHub user: '{github_username}'") outlist = [] # list of pr information dicts that will get returned @@ -250,7 +263,7 @@ class HacktoberStats(commands.Cog): "number": item["number"] } - # if the PR has 'invalid' or 'spam' labels, the PR must be + # If the PR has 'invalid' or 'spam' labels, the PR must be # either merged or approved for it to be included if HacktoberStats._has_label(item, ["invalid", "spam"]): if not await HacktoberStats._is_accepted(itemdict): @@ -263,28 +276,28 @@ class HacktoberStats(commands.Cog): outlist.append(itemdict) continue - # checking PR's labels for "hacktoberfest-accepted" + # Checking PR's labels for "hacktoberfest-accepted" if HacktoberStats._has_label(item, "hacktoberfest-accepted"): outlist.append(itemdict) continue - # no need to query github if repo topics are fetched before already + # No need to query GitHub if repo topics are fetched before already if shortname in hackto_topics.keys(): if hackto_topics[shortname]: outlist.append(itemdict) continue - # fetch topics for the pr repo + # Fetch topics for the PR's repo topics_query_url = f"https://api.github.com/repos/{shortname}/topics" logging.debug(f"Fetching repo topics for {shortname} with url: {topics_query_url}") jsonresp2 = await HacktoberStats._fetch_url(topics_query_url, GITHUB_TOPICS_ACCEPT_HEADER) if jsonresp2.get("names") is None: logging.error(f"Error fetching topics for {shortname}: {jsonresp2['message']}") - return + continue # Assume the repo doesn't have the `hacktoberfest` topic if API request errored # PRs after oct 3 that doesn't have 'hacktoberfest-accepted' label # must be in repo with 'hacktoberfest' topic if "hacktoberfest" in jsonresp2["names"]: - hackto_topics[shortname] = True # cache result in the dict for later use if needed + hackto_topics[shortname] = True # Cache result in the dict for later use if needed outlist.append(itemdict) return outlist |