aboutsummaryrefslogtreecommitdiffstats
path: root/bot
diff options
context:
space:
mode:
authorGravatar xithrius <[email protected]>2021-01-08 16:21:11 -0800
committerGravatar xithrius <[email protected]>2021-01-08 16:21:11 -0800
commitc9f83eee557d46b76bda8075fac1198dac8b9d5e (patch)
tree4cefe2dc352cdaed284a2f8080631ac94d7f0423 /bot
parentMerge branch 'master' into tic-tac-toe (diff)
parentMerge 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.py1
-rw-r--r--bot/exts/evergreen/snakes/_snakes_cog.py101
-rw-r--r--bot/exts/halloween/hacktoberstats.py45
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