-
Notifications
You must be signed in to change notification settings - Fork 58
/
Copy pathplex_tools.py
executable file
·157 lines (147 loc) · 6.21 KB
/
plex_tools.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
from plexapi.video import Movie
from plexapi import exceptions as PlexExceptions
import imdb_tools
def get_movie(plex, data):
# If an int is passed as data, assume it is a movie's rating key
if isinstance(data, int):
try:
return plex.Server.fetchItem(data)
except PlexExceptions.BadRequest:
return "Nothing found"
elif isinstance(data, Movie):
return data
else:
print(data)
movie_list = plex.MovieLibrary.search(title=data)
if movie_list:
return movie_list
else:
return "Movie: " + data + " not found"
def get_actor_rkey(plex, data):
"""Takes in actors name as str and returns as Plex's corresponding rating key ID"""
search = data
# We must first perform standard search against the Plex Server
# Searching in the Library via Actor only works if the ratingKey is already known
results = plex.Server.search(search)
for entry in results:
entry = str(entry)
entry = entry.split(":")
entry[0] = entry[0][1:]
if entry[0] == "Movie":
movie_id = int(entry[1])
break
try:
# We need to pull details from a movie to correspond the actor's name to their Plex Rating Key
movie_roles = plex.Server.fetchItem(movie_id).roles
for role in movie_roles:
role = str(role).split(":")
movie_actor_id = role[1]
movie_actor_name = role[2][:-1].upper()
if search.upper().replace(" ", "-") == movie_actor_name:
actor_id = movie_actor_id
return int(actor_id)
except UnboundLocalError:
return "Actor: " + search + " not found"
def get_all_movies(plex):
return plex.MovieLibrary.all()
def get_collection(plex, data, exact=None):
collection_list = plex.MovieLibrary.search(title=data, libtype="collection")
if len(collection_list) > 1:
if exact:
for collection in collection_list:
if collection.title == data:
return collection
else:
c_names = [(str(i + 1) + ") " + collection.title) for i, collection in enumerate(collection_list)]
print("\n".join(c_names))
while True:
try:
selection = int(input("Choose collection number: ")) - 1
if selection >= 0:
return collection_list[selection]
elif selection == "q":
return
else:
print("Invalid entry")
except (IndexError, ValueError) as E:
print("Invalid entry")
elif len(collection_list) == 1:
if exact:
if collection_list[0] == data:
return collection_list[0]
else:
return "Collection not in Plex, please update from config first"
else:
return collection_list[0]
else:
return "No collection found"
def add_to_collection(plex, method, value, c, subfilters=None):
if method in Movie.__doc__ or hasattr(Movie, method):
try:
movies = plex.MovieLibrary.search(**{method: value})
except PlexExceptions.BadRequest:
# If last character is "s" remove it and try again
if method[-1:] == "s":
movies = plex.MovieLibrary.search(**{method[:-1]: value})
movies = [m.ratingKey for m in movies if movies]
else:
if method == "imdb-list":
movies, missing = imdb_tools.imdb_get_movies(plex, value)
elif method == "tmdb-list":
movies, missing = imdb_tools.tmdb_get_movies(plex, value)
if movies:
# Check if already in collection
cols = plex.MovieLibrary.search(title=c, libtype="collection")
try:
fs = cols[0].children
except IndexError:
fs = []
for rk in movies:
current_m = get_movie(plex, rk)
current_m.reload()
if current_m in fs:
print("{} is already in collection: {}".format(current_m.title, c))
elif subfilters:
match = True
for sf in subfilters:
method = sf[0]
terms = str(sf[1]).split(", ")
try:
mv_attrs = getattr(current_m, method)
# If it returns a list, get the 'tag' attribute
# Otherwise, it's a string. Make it a list.
if isinstance(mv_attrs, list) and "-" not in method:
mv_attrs = [getattr(x, 'tag') for x in mv_attrs]
else:
mv_attrs = [str(mv_attrs)]
except AttributeError:
for media in current_m.media:
if method == "video-resolution":
mv_attrs = [media.videoResolution]
for part in media.parts:
if method == "audio-language":
mv_attrs = ([audio_stream.language for audio_stream in part.audioStreams()])
if method == "subtitle-language":
mv_attrs = ([subtitle_stream.language for subtitle_stream in part.subtitleStreams()])
# Get the intersection of the user's terms and movie's terms
# If it's empty, it's not a match
if not list(set(terms) & set(mv_attrs)):
match = False
break
if match:
print("+++ Adding {} to collection {}".format(current_m.title, c))
current_m.addCollection(c)
elif not subfilters:
print("+++ Adding {} to collection: {}".format(current_m.title, c))
current_m.addCollection(c)
try:
missing
except UnboundLocalError:
return
else:
return missing
def delete_collection(data):
confirm = input("{} selected. Confirm deletion (y/n):".format(data.title))
if confirm == "y":
data.delete()
print("Collection deleted")