1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
import logging
import random
from discord import Embed
from discord.ext import commands
from bot.bot import Bot
from bot.constants import Tokens
log = logging.getLogger(__name__)
class ScaryMovie(commands.Cog):
"""Selects a random scary movie and embeds info into Discord chat."""
def __init__(self, bot: Bot):
self.bot = bot
@commands.command(name="scarymovie", alias=["smovie"])
async def random_movie(self, ctx: commands.Context) -> None:
"""Randomly select a scary movie and display information about it."""
async with ctx.typing():
selection = await self.select_movie()
movie_details = await self.format_metadata(selection)
await ctx.send(embed=movie_details)
async def select_movie(self) -> dict:
"""Selects a random movie and returns a JSON of movie details from TMDb."""
url = "https://api.themoviedb.org/3/discover/movie"
params = {
"api_key": Tokens.tmdb,
"with_genres": "27",
"vote_count.gte": "5",
"include_adult": "false"
}
headers = {
"Content-Type": "application/json;charset=utf-8"
}
# Get total page count of horror movies
async with self.bot.http_session.get(url=url, params=params, headers=headers) as response:
data = await response.json()
total_pages = data.get("total_pages")
# Get movie details from one random result on a random page
params["page"] = random.randint(1, total_pages)
async with self.bot.http_session.get(url=url, params=params, headers=headers) as response:
data = await response.json()
selection_id = random.choice(data.get("results")).get("id")
# Get full details and credits
async with self.bot.http_session.get(
url=f"https://api.themoviedb.org/3/movie/{selection_id}",
params={"api_key": Tokens.tmdb, "append_to_response": "credits"}
) as selection:
return await selection.json()
@staticmethod
async def format_metadata(movie: dict) -> Embed:
"""Formats raw TMDb data to be embedded in Discord chat."""
# Build the relevant URLs.
movie_id = movie.get("id")
poster_path = movie.get("poster_path")
tmdb_url = f"https://www.themoviedb.org/movie/{movie_id}" if movie_id else None
poster = f"https://image.tmdb.org/t/p/original{poster_path}" if poster_path else None
# Get cast names
cast = []
for actor in movie.get("credits", {}).get("cast", [])[:3]:
cast.append(actor.get("name"))
# Get director name
director = movie.get("credits", {}).get("crew", [])
if director:
director = director[0].get("name")
# Determine the spookiness rating
rating = ""
rating_count = movie.get("vote_average", 0) / 2
for _ in range(int(rating_count)):
rating += ":skull:"
if (rating_count % 1) >= .5:
rating += ":bat:"
# Try to get year of release and runtime
year = movie.get("release_date", [])[:4]
runtime = movie.get("runtime")
runtime = f"{runtime} minutes" if runtime else None
# Not all these attributes will always be present
movie_attributes = {
"Directed by": director,
"Starring": ", ".join(cast),
"Running time": runtime,
"Release year": year,
"Spookiness rating": rating,
}
embed = Embed(
colour=0x01d277,
title=f"**{movie.get('title')}**",
url=tmdb_url,
description=movie.get("overview")
)
if poster:
embed.set_image(url=poster)
# Add the attributes that we actually have data for, but not the others.
for name, value in movie_attributes.items():
if value:
embed.add_field(name=name, value=value)
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:
"""Load the Scary Movie Cog."""
bot.add_cog(ScaryMovie(bot))
|