✨
This commit is contained in:
@ -6,4 +6,9 @@ class NoToken(Exception):
|
||||
class CannotConnectToService(Exception):
|
||||
def __init__(self, service: str) -> None:
|
||||
self.message = f"Cannot connect to {service}"
|
||||
super().__init__(self.message)
|
||||
|
||||
class ServiceNotProvided(Exception):
|
||||
def __init__(self, service: str) -> None:
|
||||
self.message = f"A {service} instance was not provided"
|
||||
super().__init__(self.message)
|
@ -1,6 +1,6 @@
|
||||
"""A collection of all Gwendolyn functions."""
|
||||
|
||||
__all__ = ["Other","BetterNetflix", "Sonarr", "Radarr", "TMDb"]
|
||||
__all__ = ["Other","BetterNetflix", "Sonarr", "Radarr", "TMDb", "QBittorrent"]
|
||||
|
||||
from .other import Other
|
||||
from .better_netflix import Radarr, Sonarr, BetterNetflix, TMDb
|
||||
from .better_netflix import Radarr, Sonarr, BetterNetflix, TMDb, QBittorrent
|
@ -1,5 +1,5 @@
|
||||
"""Better Netflix functions for Gwendolyn."""
|
||||
|
||||
__all__ = ["BetterNetflix", "Sonarr", "Radarr", "TMDb"]
|
||||
__all__ = ["BetterNetflix", "Sonarr", "Radarr", "TMDb", "QBittorrent"]
|
||||
|
||||
from .better_netflix import BetterNetflix, Sonarr, Radarr, TMDb
|
||||
from .better_netflix import BetterNetflix, Sonarr, Radarr, TMDb, QBittorrent
|
||||
|
@ -1,11 +1,13 @@
|
||||
from requests import get
|
||||
from random import choice
|
||||
import io
|
||||
from math import floor
|
||||
from time import time
|
||||
|
||||
from PIL import Image
|
||||
from interactions import SlashContext, Embed, EmbedFooter, EmbedAttachment, File
|
||||
|
||||
from gwendolyn.exceptions import CannotConnectToService
|
||||
from gwendolyn.exceptions import CannotConnectToService, ServiceNotProvided
|
||||
|
||||
class Service():
|
||||
def __init__(self, ip: str, port: str, api_key: str) -> None:
|
||||
@ -35,6 +37,24 @@ class Sonarr(Service):
|
||||
|
||||
return response.json()
|
||||
|
||||
class QBittorrent(Service):
|
||||
def __init__(self, ip: str, port: str, username: str, password: str) -> None:
|
||||
self.ip = ip
|
||||
self.port = port
|
||||
response = get(f"http://{ip}:{port}/api/v2/auth/login?username={username}&password={password}")
|
||||
self.logged_in = response.ok
|
||||
self.cookie = {"SID": response.cookies.values()[0]}
|
||||
|
||||
def test(self):
|
||||
return self.logged_in
|
||||
|
||||
def get_torrents(self):
|
||||
response = get(
|
||||
f"http://{self.ip}:{self.port}/api/v2/torrents/info",
|
||||
cookies=self.cookie
|
||||
)
|
||||
return response.json()
|
||||
|
||||
class TMDb():
|
||||
def __init__(self, api_token: str) -> None:
|
||||
self.header = {
|
||||
@ -47,20 +67,23 @@ class TMDb():
|
||||
|
||||
|
||||
class BetterNetflix():
|
||||
def __init__(self, radarr: Radarr, sonarr: Sonarr, tmdb: TMDb, bot) -> None:
|
||||
self.radarr = radarr
|
||||
self.sonarr = sonarr
|
||||
self.tmdb = tmdb
|
||||
def __init__(self, bot, **kwargs) -> None:
|
||||
self.bot = bot
|
||||
|
||||
services = ["radarr","sonarr","tmdb"]
|
||||
services = ["radarr","sonarr","tmdb","qbittorrent"]
|
||||
|
||||
for service in services:
|
||||
try:
|
||||
setattr(self,service,kwargs[service])
|
||||
except:
|
||||
raise ServiceNotProvided(service)
|
||||
|
||||
if getattr(self,service).test():
|
||||
self.bot.log(f"Connected to {service}")
|
||||
else:
|
||||
raise CannotConnectToService(service)
|
||||
|
||||
|
||||
def _poster_color(self, poster_url: str):
|
||||
response = get(poster_url, stream=True)
|
||||
img = Image.open(io.BytesIO(response.content))
|
||||
@ -157,3 +180,301 @@ class BetterNetflix():
|
||||
footer=year
|
||||
)
|
||||
await msg.edit(content="",embed=embed)
|
||||
|
||||
def _draw_torrent_list(self, title_width: int):
|
||||
def ratio_to_bar(ratio):
|
||||
progress_bar = "|"+("█"*floor(download_ratio*20))
|
||||
while len(progress_bar) < 21:
|
||||
progress_bar += " "
|
||||
|
||||
progress_bar += "| "+str(floor(download_ratio*100))+"%"
|
||||
|
||||
while len(progress_bar) < 27:
|
||||
progress_bar += " "
|
||||
|
||||
return progress_bar
|
||||
|
||||
message = [""]
|
||||
all_downloaded = True
|
||||
|
||||
dm_section_title = "*Torrent Downloads*"
|
||||
dm_section_title_line = "-"*((title_width-len(dm_section_title))//2)
|
||||
message.append(
|
||||
dm_section_title_line+dm_section_title+dm_section_title_line
|
||||
)
|
||||
|
||||
torrent_list = self.qbittorrent.get_torrents()
|
||||
|
||||
if len(torrent_list) == 0:
|
||||
message.append("No torrents currently downloading")
|
||||
return message, all_downloaded
|
||||
|
||||
for torrent in torrent_list:
|
||||
if torrent['category'] not in ["radarr", "tv-sonarr"]:
|
||||
break
|
||||
|
||||
torrent_name = torrent["name"]
|
||||
if len(torrent_name) > 30:
|
||||
if torrent_name[26] == " ":
|
||||
torrent_name = torrent_name[:26]+"...."
|
||||
else:
|
||||
torrent_name = torrent_name[:27]+"..."
|
||||
while len(torrent_name) < 30:
|
||||
torrent_name += " "
|
||||
|
||||
if torrent["size"] == 0:
|
||||
download_ratio = 0
|
||||
elif torrent["amount_left"] == 0:
|
||||
download_ratio = 1
|
||||
else:
|
||||
download_ratio = min(
|
||||
torrent["downloaded"]/torrent["size"],
|
||||
1
|
||||
)
|
||||
|
||||
progress_bar = ratio_to_bar(download_ratio)
|
||||
|
||||
eta_in_seconds = torrent["eta"]
|
||||
|
||||
if eta_in_seconds >= 8640000:
|
||||
eta = "∞"
|
||||
else:
|
||||
eta = ""
|
||||
if eta_in_seconds >= 86400:
|
||||
eta += str(floor(eta_in_seconds/86400))+"d "
|
||||
if eta_in_seconds >= 3600:
|
||||
eta += str(floor((eta_in_seconds%86400)/3600))+"h "
|
||||
if eta_in_seconds >= 60:
|
||||
eta += str(floor((eta_in_seconds%3600)/60))+"m "
|
||||
|
||||
eta += str(eta_in_seconds%60)+"s"
|
||||
|
||||
torrent_info = f"{torrent_name} {progress_bar} "
|
||||
torrent_info += f"(Eta: {eta})"
|
||||
|
||||
if torrent["state"] == "stalledDL":
|
||||
torrent_info += " (Stalled)"
|
||||
|
||||
if not (download_ratio == 1 and
|
||||
torrent["last_activity"] < time()-7200):
|
||||
message.append(torrent_info)
|
||||
|
||||
if download_ratio < 1 and torrent["state"] != "stalledDL":
|
||||
all_downloaded = False
|
||||
|
||||
return message, all_downloaded
|
||||
|
||||
async def _generate_download_list(self, show_dm, show_movies, show_shows,
|
||||
episodes):
|
||||
"""Generate a list of all torrents.
|
||||
|
||||
*Returns*
|
||||
message_text: str
|
||||
A formatted list of all torrents
|
||||
|
||||
all_downloaded: bool
|
||||
Whether all torrents are downloaded
|
||||
"""
|
||||
self.bot.log("Generating torrent list")
|
||||
title_width = 100
|
||||
message = []
|
||||
|
||||
if show_dm:
|
||||
m, all_downloaded = self._draw_torrent_list(title_width)
|
||||
message += m
|
||||
|
||||
# if show_movies:
|
||||
# message.append("")
|
||||
# movies_section_title = "*Missing movies not downloading*"
|
||||
# movies_section_line = (
|
||||
# "-"*((title_width-len(movies_section_title))//2)
|
||||
# )
|
||||
# message.append(
|
||||
# movies_section_line+movies_section_title+movies_section_line
|
||||
# )
|
||||
# movie_list = requests.get(
|
||||
# self.radarr_url+"movie?apiKey="+self.credentials["radarr_key"]
|
||||
# ).json()
|
||||
# print(
|
||||
# self.radarr_url+"movie?apiKey="+self.credentials["radarr_key"]
|
||||
# )
|
||||
# movie_queue = requests.get(
|
||||
# self.radarr_url+"queue?apiKey="+self.credentials["radarr_key"]
|
||||
# ).json()
|
||||
# movie_queue_ids = []
|
||||
|
||||
# for queue_item in movie_queue["records"]:
|
||||
# movie_queue_ids.append(queue_item["movieId"])
|
||||
|
||||
# for movie in movie_list:
|
||||
# if (not movie["hasFile"] and
|
||||
# movie["id"] not in movie_queue_ids):
|
||||
# movie_name = movie["title"]
|
||||
# if len(movie_name) > 40:
|
||||
# if movie_name[36] == " ":
|
||||
# movie_name = movie_name[:36]+"...."
|
||||
# else:
|
||||
# movie_name = movie_name[:37]+"..."
|
||||
|
||||
# while len(movie_name) < 41:
|
||||
# movie_name += " "
|
||||
|
||||
# if movie["monitored"]:
|
||||
# movie_info = movie_name+"Could not find a torrent"
|
||||
# else:
|
||||
# movie_info = self.long_strings["No torrent"].format(
|
||||
# movie_name
|
||||
# )
|
||||
|
||||
# message.append(movie_info)
|
||||
|
||||
# if show_shows:
|
||||
# message.append("")
|
||||
# show_section_title = "*Missing shows not downloading*"
|
||||
# show_section_line = "-"*((title_width-len(show_section_title))//2)
|
||||
# message.append(
|
||||
# show_section_line+show_section_title+show_section_line
|
||||
# )
|
||||
|
||||
# show_list = requests.get(
|
||||
# self.sonarr_url+"series?apiKey="+self.credentials["sonarr_key"]
|
||||
# ).json()
|
||||
|
||||
# for show in show_list:
|
||||
# if show["seasons"][0]["seasonNumber"] == 0:
|
||||
# seasons = show["seasons"][1:]
|
||||
# else:
|
||||
# seasons = show["seasons"]
|
||||
# if any(
|
||||
# (
|
||||
# i["statistics"]["episodeCount"] !=
|
||||
# i["statistics"]["totalEpisodeCount"]
|
||||
# ) for i in seasons):
|
||||
# if all(
|
||||
# i["statistics"]["episodeCount"] == 0 for i in seasons
|
||||
# ):
|
||||
# message.append(show["title"] + " (all episodes)")
|
||||
# else:
|
||||
# if episodes:
|
||||
# missing_episodes = sum(
|
||||
# (i["statistics"]["totalEpisodeCount"] -
|
||||
# i["statistics"]["episodeCount"])
|
||||
# for i in seasons)
|
||||
# message.append(
|
||||
# f"{show['title']} ({missing_episodes} episodes)"
|
||||
# )
|
||||
|
||||
message.append("-"*title_width)
|
||||
|
||||
message_text = "```"+"\n".join(message[1:])+"```"
|
||||
if message_text == "``````":
|
||||
message_text = self.long_strings["No torrents downloading"]
|
||||
|
||||
return message_text, all_downloaded
|
||||
|
||||
# async def downloading(self, ctx, content):
|
||||
# """Send message with list of all downloading torrents."""
|
||||
# async def send_long_message(ctx,message_text):
|
||||
# if len(message_text) <= 1994:
|
||||
# await ctx.send("```"+message_text+"```")
|
||||
# else:
|
||||
# cut_off_index = message_text[:1994].rfind("\n")
|
||||
# await ctx.send("```"+message_text[:cut_off_index]+"```")
|
||||
# await send_long_message(ctx,message_text[cut_off_index+1:])
|
||||
|
||||
# await self.bot.defer(ctx)
|
||||
|
||||
# # showDM, showMovies, showShows, episodes
|
||||
# parameters = [False, False, False, False]
|
||||
# show_dm_args = ["d", "dm", "downloading", "downloadmanager"]
|
||||
# show_movies_args = ["m", "movies"]
|
||||
# show_shows_args = ["s", "shows", "series"]
|
||||
# show_episode_args = ["e", "episodes"]
|
||||
# arg_list = [
|
||||
# show_dm_args, show_movies_args, show_shows_args, show_episode_args
|
||||
# ]
|
||||
# input_args = []
|
||||
# valid_arguments = True
|
||||
|
||||
# while content != "" and valid_arguments:
|
||||
# if content[0] == " ":
|
||||
# content = content[1:]
|
||||
# elif content[0] == "-":
|
||||
# if content[1] == "-":
|
||||
# arg_start = 2
|
||||
# if " " in content:
|
||||
# arg_stop = content.find(" ")
|
||||
# else:
|
||||
# arg_stop = None
|
||||
# else:
|
||||
# arg_start = 1
|
||||
# arg_stop = 2
|
||||
|
||||
# input_args.append(content[arg_start:arg_stop])
|
||||
# if arg_stop is None:
|
||||
# content = ""
|
||||
# else:
|
||||
# content = content[arg_stop:]
|
||||
# else:
|
||||
# valid_arguments = False
|
||||
|
||||
# if valid_arguments:
|
||||
# for arg_index, arg_aliases in enumerate(arg_list):
|
||||
# arg_in_input = [i in input_args for i in arg_aliases]
|
||||
# if any(arg_in_input):
|
||||
# input_args.remove(arg_aliases[arg_in_input.index(True)])
|
||||
# parameters[arg_index] = True
|
||||
|
||||
# if len(input_args) != 0 or (not parameters[2] and parameters[3]):
|
||||
# valid_arguments = False
|
||||
|
||||
# show_anything = any(i for i in parameters)
|
||||
# if not (valid_arguments and show_anything):
|
||||
# await ctx.send(self.long_strings["Invalid parameters"])
|
||||
# else:
|
||||
# message_text, all_downloaded = await self.__generate_download_list(
|
||||
# *parameters
|
||||
# )
|
||||
# if not message_text.startswith("```"):
|
||||
# await ctx.send(message_text)
|
||||
|
||||
# elif len(message_text) > 2000:
|
||||
# message_text = message_text[3:-3]
|
||||
# await send_long_message(ctx,message_text)
|
||||
|
||||
# elif all_downloaded:
|
||||
# await ctx.send(message_text)
|
||||
|
||||
# else:
|
||||
# updates_left = 60
|
||||
# message_text = self.long_strings["Update"].format(
|
||||
# message_text[:-3], ceil(updates_left/6)
|
||||
# )
|
||||
# old_message = await ctx.send(message_text)
|
||||
|
||||
# while ((not all_downloaded) and updates_left > 0):
|
||||
# await asyncio.sleep(10)
|
||||
# updates_left -= 1
|
||||
# message_text, all_downloaded = await (
|
||||
# self.__generate_download_list(*parameters)
|
||||
# )
|
||||
# message_text = self.long_strings["Update"].format(
|
||||
# message_text[:-3],
|
||||
# ceil(updates_left/6)
|
||||
# )
|
||||
# await old_message.edit(content = message_text)
|
||||
|
||||
# message_text, all_downloaded = await (
|
||||
# self.__generate_download_list(*parameters)
|
||||
# )
|
||||
|
||||
# if message_text.startswith("```"):
|
||||
# if all_downloaded:
|
||||
# self.bot.log("All torrents are downloaded")
|
||||
# else:
|
||||
# message_text = self.long_strings["No updates"].format(
|
||||
# message_text[:-3]
|
||||
# )
|
||||
# self.bot.log("The message updated 20 times")
|
||||
|
||||
# await old_message.edit(content = message_text)
|
||||
|
@ -6,7 +6,7 @@ from pymongo import MongoClient # Used for database management
|
||||
|
||||
from gwendolyn.utils import log
|
||||
from gwendolyn.exceptions import NoToken, CannotConnectToService
|
||||
from gwendolyn.funcs import Other, BetterNetflix, Sonarr, Radarr, TMDb
|
||||
from gwendolyn.funcs import Other, BetterNetflix, Sonarr, Radarr, TMDb, QBittorrent
|
||||
|
||||
class Gwendolyn(Client):
|
||||
def __init__(self, testing: bool = True):
|
||||
@ -55,10 +55,11 @@ class Gwendolyn(Client):
|
||||
def _add_functions(self):
|
||||
self.other = Other(self)
|
||||
self.better_netflix = BetterNetflix(
|
||||
Radarr(getenv("RADARR_IP"),getenv("RADARR_PORT"),getenv("RADARR_API_KEY")),
|
||||
Sonarr(getenv("SONARR_IP"),getenv("SONARR_PORT"),getenv("SONARR_API_KEY")),
|
||||
TMDb(getenv("TMDB_API_ACCESS_TOKEN")),
|
||||
self
|
||||
self,
|
||||
radarr=Radarr(getenv("RADARR_IP"),getenv("RADARR_PORT"),getenv("RADARR_API_KEY")),
|
||||
sonarr=Sonarr(getenv("SONARR_IP"),getenv("SONARR_PORT"),getenv("SONARR_API_KEY")),
|
||||
tmdb=TMDb(getenv("TMDB_API_ACCESS_TOKEN")),
|
||||
qbittorrent=QBittorrent(getenv("QBITTORRENT_IP"),getenv("QBITTORRENT_PORT"),getenv("QBITTORRENT_USERNAME"),getenv("QBITTORRENT_PASSWORD"))
|
||||
)
|
||||
|
||||
def _add_extensions(self):
|
||||
|
Reference in New Issue
Block a user