forked from AustinHasten/PlexHolidays
/
main.py
172 lines (148 loc) · 5.38 KB
/
main.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
# Saul Femm
# Initial Commit - November 16th, 2017
import sys
import getpass
import plexapi.utils
from tqdm import tqdm
from imdb import IMDb
from plexapi.myplex import MyPlexAccount
from plexapi.playlist import Playlist
from plexapi.exceptions import BadRequest
class Plex():
def __init__(self):
self.account = self.get_account()
self.server = self.get_account_server(self.account)
self.section = self.get_server_section(self.server)
self.media = self.get_flat_media()
def get_account(self):
"""
Sign into Plex account.
"""
while True:
username = input("Plex Username: ")
password = getpass.getpass()
print('Signing into Plex... ', end='', flush=True)
try:
account = MyPlexAccount(username, password)
except BadRequest:
print('Invalid Username/Password.')
continue
print('Done')
break
return account
def get_account_server(self, account):
"""
Select server from Plex account.
"""
servers = [ _ for _ in account.resources() if _.product == 'Plex Media Server' ]
if not servers:
print('No available servers.')
sys.exit()
return plexapi.utils.choose('Select server index', servers, "name").connect()
def get_server_section(self, server):
"""
Select section from Plex server.
"""
sections = [ _ for _ in server.library.sections() if _.type in {'movie', 'show'} ]
if not sections:
print('No available sections.')
sys.exit()
return plexapi.utils.choose('Select section index', sections, 'title')
def get_flat_media(self):
"""
Flatten this object's section's media list."
"""
# Movie sections are already flat
if self.section.type == 'movie':
return self.section.all()
# TV sections are not
else:
flattened = []
for show in self.section.all():
for episode in show.episodes():
flattened.append(episode)
return flattened
def create_playlist(self, name, media):
"""
Create or update playlist with list of media.
"""
for playlist in self.server.playlists():
if name == playlist.title:
playlist.addItems(media)
break
else:
Playlist.create(self.server, name, media)
class PlexHolidays():
def __init__(self):
self.plex = Plex()
self.imdb = IMDb()
keyword = input('Keyword (i.e. Holiday name): ')
keyword_matches = []
print('Scanning', self.plex.section.title, '...')
for plex_medium in tqdm(self.plex.media):
imdb_medium = self.plex2imdb(plex_medium)
if not imdb_medium:
continue
keywords = self.get_keywords(imdb_medium)
if keyword.lower() in keywords:
keyword_matches.append(plex_medium)
if keyword_matches:
print('Titles matching\"', keyword, '\" :')
for match in keyword_matches:
print('\t', match.title)
self.plex.create_playlist(input('Playlist name: '), keyword_matches)
else:
print('No matches found. D:')
print('Happy Holidays!')
def plex2imdb(self, medium):
"""
Get the IMDbPy object for a given Plex object.
"""
# Set appropriate search method and acceptable results based on section type
if self.plex.section.type == 'movie':
kinds = {'movie', 'short', 'tv movie', 'tv short'}
search_function = self.imdb.search_movie
else:
kinds = {'episode'}
search_function = self.imdb.search_episode
# Perform IMDb search for the Plex object
while True:
try:
results = [ _ for _ in search_function(medium.title) if _['kind'] in kinds ]
break
# Time out, try again.
except OSError:
print('Timed out while downloading', medium.title)
continue
# No IMDb results whatsoever
if not results:
return None
# Plex has no year listed, return first search result
elif not medium.year:
return results[0]
closest_result, closest_year = None, 9999
for result in results:
# This result has no year listed, ignore it.
if not result.get('year'):
continue
# Exact match found
if result['year'] == medium.year:
return result
# Track match with closest year in case exact match is not found
elif (medium.year - result['year']) < closest_year:
closest_result = result
# No exact match found, use result with closest year
else:
return closest_result
def get_keywords(self, imdb_obj):
"""
Get the plot keywords for a given IMDbPy object.
"""
if not imdb_obj:
return []
data = self.imdb.get_movie_keywords(imdb_obj.movieID)['data']
if not 'keywords' in data:
return []
return data['keywords']
if __name__ == "__main__":
PH = PlexHolidays()