Made the plex functions use buttons

This commit is contained in:
NikolajDanger
2021-08-18 21:12:32 +02:00
parent ae71ff631d
commit 3819e56cd6
6 changed files with 305 additions and 307 deletions

View File

@ -34,6 +34,11 @@ class EventCog(commands.Cog):
"""Handle when someone reacts to a message.""" """Handle when someone reacts to a message."""
await self.bot.event_handler.on_reaction_add(reaction, user) await self.bot.event_handler.on_reaction_add(reaction, user)
@commands.Cog.listener()
async def on_component(self, ctx):
"""Handle when someone reacts to a message."""
await self.bot.event_handler.on_component(ctx)
def setup(bot): def setup(bot):
"""Add the eventcog to the bot.""" """Add the eventcog to the bot."""

View File

@ -1,11 +1,15 @@
"""Plex integration with the bot.""" """Plex integration with the bot."""
from math import floor, ceil from math import floor, ceil
import time import time
import json
import asyncio import asyncio
import requests import requests
import imdb import imdb
import discord import discord
import xmltodict
from discord_slash.utils.manage_components import (create_button,
create_actionrow)
from discord_slash.model import ButtonStyle
class Plex(): class Plex():
"""Container for Plex functions and commands.""" """Container for Plex functions and commands."""
@ -64,88 +68,102 @@ class Plex():
colour=0x00FF00 colour=0x00FF00
) )
message = await ctx.send(embed=embed) buttons = []
message_data = {"message_id":message.id,"imdb_ids":imdb_ids}
file_path = f"gwendolyn/resources/plex/old_message{ctx.channel.id}"
with open(file_path,"w") as file_pointer:
json.dump(message_data, file_pointer)
if len(movies) == 1: if len(movies) == 1:
await message.add_reaction("✔️") buttons.append(create_button(
style=ButtonStyle.green,
label="",
custom_id=f"plex:movie:{imdb_ids[0]}"
)
)
else: else:
for i in range(len(movies)): for i in range(len(movies)):
await message.add_reaction(["1","2","3","4","5"][i]) buttons.append(
create_button(
style=ButtonStyle.blue,
label=str(i+1),
custom_id=f"plex:movie:{imdb_ids[i]}"
)
)
buttons.append(create_button(
style=ButtonStyle.red,
label="X",
custom_id="plex:movie:"
)
)
action_rows = []
for i in range(((len(buttons)-1)//5)+1):
action_rows.append(
create_actionrow(
*buttons[(i*5):(min(len(buttons),i*5+5))]
)
)
await ctx.send(embed=embed, components=action_rows)
await message.add_reaction("")
message = await ctx.channel.fetch_message(message.id)
if (message.content != "" and
not isinstance(ctx.channel, discord.DMChannel)):
await message.clear_reactions()
async def add_movie(self, message, imdb_id, edit_message = True): async def add_movie(self, message, imdb_id, edit_message = True):
"""Add a movie to Plex server.""" """Add a movie to Plex server."""
if imdb_id is None:
if not edit_message:
await message.delete()
if imdb_id == "":
self.bot.log("Did not find what the user was searching for") self.bot.log("Did not find what the user was searching for")
if edit_message: message_text = "Try searching for the IMDB id"
await message.edit(
embed = None,
content = "Try searching for the IMDB id"
)
else:
await message.channel.send("Try searching for the IMDB id")
else: else:
self.bot.log("Trying to add movie "+str(imdb_id)) self.bot.log("Trying to add movie "+str(imdb_id))
# Searches for the movie using the imdb id through Radarr
api_key = self.credentials["radarr_key"] api_key = self.credentials["radarr_key"]
request_url = self.radarr_url+"movie/lookup/imdb?imdbId=tt"+imdb_id request_url = self.radarr_url+"movie/lookup/imdb?imdbId=tt"+imdb_id
request_url += "&apiKey="+api_key request_url += "&apiKey="+api_key
response = requests.get(request_url) response = requests.get(request_url)
# Makes the dict used for the post request
lookup_data = response.json() lookup_data = response.json()
post_data = {"qualityProfileId": 1, post_data = {
"rootFolder_path" : self.movie_path, "qualityProfileId": 1,
"rootFolderPath" : self.movie_path,
"monitored" : True, "monitored" : True,
"addOptions": {"searchForMovie": True}} "addOptions": {"searchForMovie": True}
}
for key in ["tmdbId","title","titleSlug","images","year"]: for key in ["tmdbId","title","titleSlug","images","year"]:
post_data.update({key : lookup_data[key]}) post_data.update({key : lookup_data[key]})
# Makes the post request
response = requests.post( response = requests.post(
url = self.radarr_url+"movie?apikey="+api_key, url = self.radarr_url+"movie?apikey="+api_key,
json = post_data json = post_data
) )
# Deciphers the response
if response.status_code == 201: if response.status_code == 201:
success_message = "{} successfully added to Plex".format( self.bot.log("Added "+post_data["title"]+" to Plex")
message_text = "{} successfully added to Plex".format(
post_data["title"] post_data["title"]
) )
if edit_message:
await message.edit(
embed = None,
content = success_message
)
else:
await message.channel.send(success_message)
self.bot.log("Added "+post_data["title"]+" to Plex")
elif response.status_code == 400: elif response.status_code == 400:
fail_text = self.long_strings["Already on Plex"].format( self.bot.log("The movie was already on plex")
message_text = self.long_strings["Already on Plex"].format(
post_data['title'] post_data['title']
) )
if edit_message:
await message.edit(embed = None, content = fail_text)
else:
await message.channel.send(fail_text)
else: else:
self.bot.log(str(response.status_code)+" "+response.reason)
message_text = "Something went wrong",
if edit_message: if edit_message:
await message.edit( await message.edit(
embed = None, embed = None,
content = "Something went wrong" content = message_text,
components = []
) )
else: else:
await message.channel.send("Something went wrong") await message.channel.send(message_text)
self.bot.log(str(response.status_code)+" "+response.reason)
async def request_show(self, ctx, show_name): async def request_show(self, ctx, show_name):
"""Request a show for the Plex server.""" """Request a show for the Plex server."""
@ -166,7 +184,7 @@ class Plex():
message_title = "**Is it any of these shows?**" message_title = "**Is it any of these shows?**"
message_text = "" message_text = ""
imdb_names = [] imdb_ids = []
for i, show in enumerate(shows): for i, show in enumerate(shows):
try: try:
@ -176,10 +194,10 @@ class Plex():
message_text += "\n"+str(i+1)+") "+show["title"] message_text += "\n"+str(i+1)+") "+show["title"]
except KeyError: except KeyError:
message_text += "Error" message_text += "Error"
imdb_names.append(show["title"]) imdb_ids.append(show.movieID)
self.bot.log( self.bot.log(
f"Returning a list of {len(shows)} possible shows: {imdb_names}" f"Returning a list of {len(shows)} possible shows: {imdb_ids}"
) )
embed = discord.Embed( embed = discord.Embed(
@ -188,42 +206,69 @@ class Plex():
colour=0x00FF00 colour=0x00FF00
) )
message = await ctx.send(embed=embed) buttons = []
message_data = {"message_id":message.id,"imdb_names":imdb_names}
file_path = "gwendolyn/resources/plex/old_message"+str(ctx.channel.id)
with open(file_path,"w") as file_pointer:
json.dump(message_data, file_pointer)
if len(shows) == 1: if len(shows) == 1:
await message.add_reaction("✔️") buttons.append(create_button(
else: style=ButtonStyle.green,
for i in range(len(shows)): label="",
await message.add_reaction(["1","2","3","4","5"][i]) custom_id=f"plex:show:{imdb_ids[0]}"
)
await message.add_reaction("")
message = await ctx.channel.fetch_message(message.id)
if message.content != "":
if not isinstance(ctx.channel, discord.DMChannel):
await message.clear_reactions()
async def add_show(self, message, imdb_name):
"""Add the requested show to Plex."""
if imdb_name is None:
self.bot.log("Did not find what the user was searching for")
await message.edit(
embed = None,
content = "Try searching for the IMDB id"
) )
else: else:
self.bot.log("Trying to add show "+str(imdb_name)) for i in range(len(shows)):
buttons.append(
create_button(
style=ButtonStyle.blue,
label=str(i+1),
custom_id=f"plex:show:{imdb_ids[i]}"
)
)
buttons.append(create_button(
style=ButtonStyle.red,
label="X",
custom_id="plex:show:"
)
)
action_rows = []
for i in range(((len(buttons)-1)//5)+1):
action_rows.append(
create_actionrow(
*buttons[(i*5):(min(len(buttons),i*5+5))]
)
)
await ctx.send(embed=embed, components=action_rows)
async def add_show(self, message, imdb_id, edit_message = True):
"""Add the requested show to Plex."""
if imdb_id == "":
self.bot.log("Did not find what the user was searching for")
message_text = "Try searching for the IMDB id"
else:
self.bot.log("Trying to add show "+str(imdb_id))
# Finds the tvdb id
tvdb_api_url = "https://thetvdb.com/api/"
tvdb_method = "GetSeriesByRemoteID.php"
tvdb_request_url = f"{tvdb_api_url}{tvdb_method}"
tvdb_id = xmltodict.parse(
requests.get(
tvdb_request_url+f"?imdbid=tt{imdb_id}",
headers = {"ContentType" : "application/json"}
).text
)['Data']['Series']['seriesid']
# Finds the rest of the information using Sonarr
api_key = self.credentials["sonarr_key"] api_key = self.credentials["sonarr_key"]
request_url = self.sonarr_url+"series/lookup?term=" request_url = self.sonarr_url+"series/lookup?term="
request_url += imdb_name.replace(" ","%20") request_url += f"tvdb:{tvdb_id}"
request_url += "&apiKey="+api_key request_url += "&apiKey="+api_key
response = requests.get(request_url) response = requests.get(request_url)
# Makes the dict used for the post request
lookup_data = response.json()[0] lookup_data = response.json()[0]
post_data = { post_data = {
"ProfileId" : 1, "ProfileId" : 1,
@ -234,29 +279,32 @@ class Plex():
for key in ["tvdbId","title","titleSlug","images","seasons"]: for key in ["tvdbId","title","titleSlug","images","seasons"]:
post_data.update({key : lookup_data[key]}) post_data.update({key : lookup_data[key]})
# Makes the post request
response = requests.post( response = requests.post(
url= self.sonarr_url+"series?apikey="+api_key, url= self.sonarr_url+"series?apikey="+api_key,
json = post_data json = post_data
) )
# Deciphers the response
if response.status_code == 201: if response.status_code == 201:
await message.edit(
embed = None,
content = post_data["title"]+" successfully added to Plex"
)
self.bot.log("Added a "+post_data["title"]+" to Plex") self.bot.log("Added a "+post_data["title"]+" to Plex")
message_text = post_data["title"]+" successfully added to Plex"
elif response.status_code == 400: elif response.status_code == 400:
text = self.long_strings["Already on Plex"].format( message_text = self.long_strings["Already on Plex"].format(
post_data['title'] post_data['title']
) )
await message.edit(embed = None, content = text)
else: else:
self.bot.log(str(response.status_code)+" "+response.reason)
message_text = "Something went wrong"
if edit_message:
await message.edit( await message.edit(
embed = None, embed = None,
content = "Something went wrong" content = message_text,
components = []
) )
self.bot.log(str(response.status_code)+" "+response.reason) else:
await message.channel.send(message_text)
async def __generate_download_list(self, show_dm, show_movies, show_shows, async def __generate_download_list(self, show_dm, show_movies, show_shows,
episodes): episodes):
@ -364,7 +412,9 @@ class Plex():
movie_list = requests.get( movie_list = requests.get(
self.radarr_url+"movie?apiKey="+self.credentials["radarr_key"] self.radarr_url+"movie?apiKey="+self.credentials["radarr_key"]
).json() ).json()
print(self.radarr_url+"movie?apiKey="+self.credentials["radarr_key"]) print(
self.radarr_url+"movie?apiKey="+self.credentials["radarr_key"]
)
movie_queue = requests.get( movie_queue = requests.get(
self.radarr_url+"queue?apiKey="+self.credentials["radarr_key"] self.radarr_url+"queue?apiKey="+self.credentials["radarr_key"]
).json() ).json()

View File

@ -15,7 +15,7 @@ import discord # Used to init discord.Game and discord.Status, as well
from discord.ext import commands # Used to compare errors with command from discord.ext import commands # Used to compare errors with command
# errors # errors
from discord_slash.context import SlashContext from discord_slash.context import SlashContext, ComponentContext
from gwendolyn.utils.util_functions import emoji_to_command from gwendolyn.utils.util_functions import emoji_to_command
@ -72,13 +72,6 @@ class EventHandler():
channel = message.channel channel = message.channel
reacted_message = f"{user.display_name} reacted to a message" reacted_message = f"{user.display_name} reacted to a message"
self.bot.log(reacted_message, str(channel.id)) self.bot.log(reacted_message, str(channel.id))
plex_data = tests.plex_reaction_test(message)
# plex_data is a list containing 3 elements: whether it was
# the add_show/add_movie command message the reaction was to
# (bool), whether it's a movie (bool) (if false, it's a
# show), and the imdb ids/names for the for the movies or
# shows listed in the message (list).
reaction_test_parameters = [message, f"#{str(user.id)}"] reaction_test_parameters = [message, f"#{str(user.id)}"]
if tests.connect_four_reaction_test(*reaction_test_parameters): if tests.connect_four_reaction_test(*reaction_test_parameters):
@ -86,34 +79,6 @@ class EventHandler():
params = [message, f"#{user.id}", column-1] params = [message, f"#{user.id}", column-1]
await self.bot.games.connect_four.place_piece(*params) await self.bot.games.connect_four.place_piece(*params)
if plex_data[0]:
plex_functions = self.bot.other.plex
if plex_data[1]:
movie_pick = emoji_to_command(reaction.emoji)
if movie_pick == "none":
imdb_id = None
else:
imdb_id = plex_data[2][movie_pick-1]
if isinstance(channel, discord.DMChannel):
await message.delete()
await plex_functions.add_movie(message, imdb_id, False)
else:
await message.clear_reactions()
await plex_functions.add_movie(message, imdb_id)
else:
show_pick = emoji_to_command(reaction.emoji)
if show_pick == "none":
imdb_name = None
else:
imdb_name = plex_data[2][show_pick-1]
if isinstance(channel, discord.DMChannel):
await message.delete()
await plex_functions.add_show(message, imdb_name, False)
else:
await message.clear_reactions()
await plex_functions.add_show(message, imdb_name)
elif tests.hangman_reaction_test(*reaction_test_parameters): elif tests.hangman_reaction_test(*reaction_test_parameters):
self.bot.log("They reacted to the hangman message") self.bot.log("They reacted to the hangman message")
@ -126,6 +91,25 @@ class EventHandler():
else: else:
self.bot.log("Bot they didn't react with a valid guess") self.bot.log("Bot they didn't react with a valid guess")
async def on_component(self, ctx: ComponentContext):
info = ctx.custom_id.split(":")
channel = ctx.origin_message.channel
if info[0] == "plex":
if info[1] == "movie":
await self.bot.other.plex.add_movie(
ctx.origin_message,
info[2],
not isinstance(channel, discord.DMChannel)
)
if info[1] == "show":
await self.bot.other.plex.add_show(
ctx.origin_message,
info[2],
not isinstance(channel, discord.DMChannel)
)
class ErrorHandler(): class ErrorHandler():
""" """

View File

@ -6,7 +6,6 @@ Contains classes used for utilities.
DatabaseFuncs() DatabaseFuncs()
""" """
import os # Used to test if files exist import os # Used to test if files exist
import json # Used to read the data about add_movie/add_show
import time # Used to test how long it's been since commands were synced import time # Used to test how long it's been since commands were synced
import re # Used in get_id import re # Used in get_id
@ -206,45 +205,6 @@ class DatabaseFuncs():
return game_message return game_message
def plex_reaction_test(self, message: discord.Message):
"""
Test if the given message is the response to a plex request.
*Parameters*
------------
message: discord.Message
The message to test.
*Returns*
---------
: bool
Whether the message is the response to a plex request.
: bool
Whether it was a movie request (false for a show
request)
: list
A list of ids or names of the shows or movies that
Gwendolyn presented after the request.
"""
channel = message.channel
old_messages_path = "gwendolyn/resources/plex/"
file_path = old_messages_path + f"old_message{str(channel.id)}"
if os.path.isfile(file_path):
with open(file_path, "r") as file_pointer:
data = json.load(file_pointer)
else:
return (False, None, None)
if data["message_id"] != message.id:
return (False, None, None)
if "imdb_ids" in data:
return_data = (True, True, data["imdb_ids"])
else:
return_data = (True, False, data["imdb_names"])
return return_data
async def imdb_commands(self): async def imdb_commands(self):
"""Sync the slash commands with the discord API.""" """Sync the slash commands with the discord API."""
collection = self.bot.database["last synced"] collection = self.bot.database["last synced"]

View File

@ -23,7 +23,6 @@ lxml==4.6.3
more-itertools==8.8.0 more-itertools==8.8.0
multidict==5.1.0 multidict==5.1.0
Pillow==8.3.1 Pillow==8.3.1
pip==21.2.3
pymongo==3.12.0 pymongo==3.12.0
requests==2.26.0 requests==2.26.0
setuptools==57.4.0 setuptools==57.4.0