-
Notifications
You must be signed in to change notification settings - Fork 5
/
not-cutoff-radarr.py
246 lines (211 loc) · 8.18 KB
/
not-cutoff-radarr.py
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
import argparse
import os
import random
import sys
from datetime import datetime
import requests
"""
Author: soup
Description: This script will check for movies in Radarr that do not have the given custom format assigned and are considered released.
It then asks you if you want to trigger a search for upgrades for those movies. It will ask you how many movies you want to search for.
"""
RADARR_URL = os.getenv(
"RADARR_URL", "http://localhost:7878/radarr"
) # Change this to your Radarr URL
RADARR_API_KEY = os.getenv(
"RADARR_API_KEY", "api_key"
) # Change this to your Radarr API key
CUSTOM_FORMAT_NAMES = [
"HD Bluray Tier 01",
"HD Bluray Tier 02",
] # Change this to the names of the custom formats you want to filter by
def is_movie_available(movie):
current_date = datetime.now().date()
if movie["status"] == "released":
if "physicalRelease" in movie:
physical_release_date = datetime.strptime(
movie["physicalRelease"], "%Y-%m-%dT%H:%M:%SZ"
).date()
if physical_release_date <= current_date:
return True
if "digitalRelease" in movie:
digital_release_date = datetime.strptime(
movie["digitalRelease"], "%Y-%m-%dT%H:%M:%SZ"
).date()
if digital_release_date <= current_date:
return True
return False
def monitor_movie(movie):
update_url = (
f'{RADARR_URL}/api/v3/movie/{movie["id"]}?apiKey={RADARR_API_KEY}'
)
headers = {"Content-Type": "application/json"}
payload = movie
payload["monitored"] = True
response = requests.put(update_url, json=payload, headers=headers)
if response.status_code not in [200, 202]:
print(
f"Error updating monitored status for movie ID {movie['id']}: {response.status_code}"
)
return False
return True
def fetch_custom_formats():
response = requests.get(
f"{RADARR_URL}/api/v3/customformat", params={"apiKey": RADARR_API_KEY}
)
if response.status_code == 200:
return response.json()
else:
print(f"Error fetching custom formats: {response.status_code}")
return []
def find_custom_format_ids(custom_formats, custom_format_names):
custom_format_ids = []
for custom_format_name in custom_format_names:
for custom_format in custom_formats:
if custom_format["name"] == custom_format_name:
custom_format_ids.append(custom_format["id"])
break
else:
print(f'Error: Custom format "{custom_format_name}" not found')
return custom_format_ids
def fetch_movies():
response = requests.get(
f"{RADARR_URL}/api/v3/movie", params={"apiKey": RADARR_API_KEY}
)
if response.status_code == 200:
return response.json()
else:
print(f"Error fetching movies: {response.status_code}")
return []
def filter_movies(movies, custom_format_ids, match):
filtered_movies = []
for movie in movies:
if not is_movie_available(movie):
continue
movie_custom_format_ids = [] # default to empty list
if "movieFile" in movie:
movie_file_response = requests.get(
f'{RADARR_URL}/api/v3/moviefile/{movie["movieFile"]["id"]}',
params={"apiKey": RADARR_API_KEY},
)
if movie_file_response.status_code == 200:
movie_file = movie_file_response.json()
movie_custom_format_ids = [
format["id"]
for format in movie_file.get("customFormats", [])
]
else:
print(
f'Error fetching movie file for {movie["title"]}: {movie_file_response.status_code}'
)
if match == "any":
if not any(
custom_format_id in movie_custom_format_ids
for custom_format_id in custom_format_ids
):
filtered_movies.append(movie)
else:
if not all(
custom_format_id in movie_custom_format_ids
for custom_format_id in custom_format_ids
):
filtered_movies.append(movie)
return filtered_movies
def monitor_filtered_movies(filtered_movies):
unmonitored_count = 0
filtered_count = len(filtered_movies)
for movie in filtered_movies:
if not movie["monitored"]:
if monitor_movie(movie):
movie["monitored"] = True
unmonitored_count += 1
return unmonitored_count, filtered_count
def parse_args():
parser = argparse.ArgumentParser(
description="Check for custom format, monitor, and search for upgrades in Radarr."
)
parser.add_argument(
"--unattended",
type=int,
metavar="N",
help="Run the script unattended and search for N movies at the end without user interaction.",
)
parser.add_argument(
"--match",
choices=["any", "all"],
default="all",
help="Choose whether any or all custom formats need to match ('any' or 'all' defaults to 'all').",
)
return parser.parse_args()
def main():
# If the script is not called with --help or -h, print the check statement
args = parse_args()
if all(arg not in sys.argv for arg in ("--help", "-h")):
print(
f'Checking for movies in Radarr that do not have {args.match} of the custom formats "{CUSTOM_FORMAT_NAMES}" assigned and are considered available...'
)
args = parse_args()
custom_formats = fetch_custom_formats()
custom_format_ids = find_custom_format_ids(
custom_formats, CUSTOM_FORMAT_NAMES
)
if not custom_format_ids:
print(
f"Error: None of the custom formats {CUSTOM_FORMAT_NAMES} were found"
)
else:
movies = fetch_movies()
filtered_movies = filter_movies(movies, custom_format_ids, args.match)
# Add this line to print the total count of filtered movies
print(
f"Found {len(filtered_movies)} movies without the custom format '{CUSTOM_FORMAT_NAMES}'."
)
if args.unattended is None:
save_answer = input(
"Save the list of movies to not-cutoff.txt and continue to search? (Y/n): "
)
if save_answer.lower() != "y" and save_answer != "":
print("Exiting program.")
sys.exit(0)
num_search = input(
"How many movies do you want to search? (Enter 0 to skip): "
)
else:
save_answer = "y"
num_search = args.unattended
if save_answer.lower() != "y" and save_answer != "":
print("Skipping saving the list of movies.")
else:
with open("not-cutoff.txt", "w") as f:
for movie in filtered_movies:
f.write(movie["title"] + "\n")
print("List of movies has been saved to not-cutoff.txt")
try:
num_search = int(num_search)
except ValueError:
num_search = 0
if num_search > 0:
random_movies = random.sample(filtered_movies, num_search)
for movie in random_movies:
if not movie["monitored"]:
monitor_movie(movie)
search_url = f"{RADARR_URL}/api/v3/command"
search_payload = {
"name": "MoviesSearch",
"movieIds": [movie["id"]],
}
response = requests.post(
search_url,
json=search_payload,
params={"apiKey": RADARR_API_KEY},
)
if response.status_code == 201:
print(
f"Search for upgraded version of \"{movie['title']}\" has been triggered."
)
else:
print(
f"Error searching for upgraded version of \"{movie['title']}\": {response.status_code}"
)
if __name__ == "__main__":
main()