From 2b6eab744950590c9c019e9a4eb07aaaa26d7dc4 Mon Sep 17 00:00:00 2001 From: Keith Lamprecht Date: Sun, 26 Nov 2017 23:27:35 -0500 Subject: [PATCH 1/2] Update For Mobile --- scripts/plexEmail.py | 618 ++++++++++++++++++++++++------------------- 1 file changed, 345 insertions(+), 273 deletions(-) diff --git a/scripts/plexEmail.py b/scripts/plexEmail.py index 610fa53..1ecbf52 100644 --- a/scripts/plexEmail.py +++ b/scripts/plexEmail.py @@ -27,255 +27,258 @@ SCRIPT_VERSION = 'v0.9.3' +reload(sys) +sys.setdefaultencoding("utf-8") + def replaceConfigTokens(): ## The below code is for backwards compatibility if ('filter_include_original_title' not in config): config['filter_include_original_title'] = True - + if ('logging_enabled' not in config): config['logging_enabled'] = True - + if ('plex_web_server_guid' not in config): config['plex_web_server_guid'] = '' - + if ('upload_cloudinary_use_https' not in config): config['upload_cloudinary_use_https'] = True - + if ('logging_retain_previous_logs' not in config): config['logging_retain_previous_logs'] = True - + if ('logging_debug_level' not in config): config['logging_debug_level'] = 'INFO' - + if ('logging_file_location' not in config): config['logging_file_location'] = '' - + if ('upload_cloudinary_api_secret' not in config): config['upload_cloudinary_api_secret'] = True - + if ('artist_sort_1' not in config.keys() or config['artist_sort_1'] == ""): config['artist_sort_1'] = 'title_sort' - + if ('artist_sort_1_reverse' not in config.keys() or config['artist_sort_1_reverse'] == ""): config['artist_sort_1_reverse'] = False if ('artist_sort_2_reverse' not in config.keys() or config['artist_sort_2_reverse'] == ""): config['artist_sort_2_reverse'] = False if ('artist_sort_3_reverse' not in config.keys() or config['artist_sort_3_reverse'] == ""): config['artist_sort_3_reverse'] = False - + if ('album_sort_1' not in config.keys() or config['album_sort_1'] == ""): config['album_sort_1'] = 'title_sort' - + if ('album_sort_1_reverse' not in config.keys() or config['album_sort_1_reverse'] == ""): config['album_sort_1_reverse'] = False if ('album_sort_2_reverse' not in config.keys() or config['album_sort_2_reverse'] == ""): config['album_sort_2_reverse'] = False if ('album_sort_3_reverse' not in config.keys() or config['album_sort_3_reverse'] == ""): config['album_sort_3_reverse'] = False - + if ('msg_new_artists_header' not in config): config['msg_new_artists_header'] = 'New Artists' - + if ('msg_new_albums_header' not in config): config['msg_new_albums_header'] = 'New Albums' - + if ('msg_new_songs_header' not in config): config['msg_new_songs_header'] = 'New Songs' - + if ('msg_artists_link' not in config): config['msg_artists_link'] = 'Artists' - + if ('msg_albums_link' not in config): config['msg_albums_link'] = 'Albums' - + if ('msg_songs_link' not in config): config['msg_songs_link'] = 'Songs' - + if ('filter_show_artists' not in config): config['filter_show_artists'] = True - + if ('filter_show_albums' not in config): config['filter_show_albums'] = True - + if ('filter_show_songs' not in config): config['filter_show_songs'] = False - + if ('filter_sections_Music' not in config): config['filter_sections_Music'] = {'tagline':{'order':1,'show':False,'preText':'','postText':'','include':[],'exclude':[]},'summary':{'order':2,'show':True,'preText':'','postText':'','include':[],'exclude':[]},'tags_genre':{'order':3,'show':True,'preText':'Genre(s): ','postText':'','include':[],'exclude':[]},'tags_director':{'order':4,'show':False,'preText':'Director: ','postText':'','include':[],'exclude':[]},'tags_star':{'order':5,'show':False,'preText':'Star(s): ','postText':'','include':[],'exclude':[]},'content_rating':{'order':6,'show':False,'preText':'ContentRating: ','postText':'','include':[],'exclude':[]},'duration':{'order':7,'show':True,'preText':'Runtime: ','postText':' minutes','include':[],'exclude':[]},'year':{'order':8,'show':False,'preText':'Year: ','postText':'','include':[],'exclude':[]},'studio':{'order':9,'show':True,'preText':'Network: ','postText':'','include':[],'exclude':[]},'rating':{'order':10,'show':False,'preText':'Rating: ','postText':'%','include':[],'exclude':[]},'air_date':{'order':11,'show': True,'preText':'Release Date: ','postText':'','include':[],'exclude':[],'format': '%B %d, %Y'},'track_list':{'order':12,'show': True,'headerText':{'trackNumber':'Track#','songName':'Song Name','artistName':'Artist(s)','duration':'Duration'}}} - + if ('filter_artists_include' not in config): config['filter_artists_include'] = [] - + if ('filter_artists_exclude' not in config): config['filter_artists_exclude'] = [] - + if ('filter_albums_include' not in config): config['filter_albums_include'] = [] - + if ('filter_albums_exclude' not in config): config['filter_albums_exclude'] = [] - + if ('filter_songs_include' not in config): config['filter_songs_include'] = [] - + if ('filter_songs_exclude' not in config): config['filter_songs_exclude'] = [] - + if ('filter_song_thumbnail_type' not in config): config['filter_song_thumbnail_type'] = 'album' - + if ('filter_movies_include' not in config): config['filter_movies_include'] = [] - + if ('filter_movies_exclude' not in config): config['filter_movies_exclude'] = [] - + if ('filter_shows_include' not in config): config['filter_shows_include'] = [] - + if ('filter_shows_exclude' not in config): config['filter_shows_exclude'] = [] - + if ('filter_seasons_include' not in config): config['filter_seasons_include'] = [] - + if ('filter_seasons_exclude' not in config): config['filter_seasons_exclude'] = [] - + if ('filter_episodes_include' not in config): config['filter_episodes_include'] = [] - + if ('filter_episodes_exclude' not in config): config['filter_episodes_exclude'] = [] - + if ('filter_episode_thumbnail_type' not in config): config['filter_episode_thumbnail_type'] = 'episode' - + if ('email_unsubscribe' not in config): config['email_unsubscribe'] = [] - + if ('email_use_bcc' not in config): config['email_use_bcc'] = False - + if ('email_to_send_to_shared_users' not in config): config['email_to_send_to_shared_users'] = False - + if ('plex_username' not in config): config['plex_username'] = '' - + if ('plex_password' not in config): config['plex_password'] = '' - + if ('filter_show_email_images' not in config): config['filter_show_email_images'] = True - + if ('msg_notice' not in config): config['msg_notice'] = '' - + if ('email_use_ssl' not in config): config['email_use_ssl'] = False - + if ('filter_include_plex_web_link' not in config): config['filter_include_plex_web_link'] = True - + if ('filter_libraries' not in config): config['filter_libraries'] = [] - + if ('filter_sections_movies' not in config): config['filter_include_sections_movies'] = {'tagline':{'order':1,'show':True,'preText':'','postText':'','include':[],'exclude':[]},'summary':{'order':2,'show':True,'preText':'','postText':'','include':[],'exclude':[]},'tags_genre':{'order':3,'show':True,'preText':'Genre(s): ','postText':'','include':[],'exclude':[]},'tags_director':{'order':4,'show':False,'preText':'Director: ','postText':'','include':[],'exclude':[]},'tags_star':{'order':5,'show':True,'preText':'Star(s): ','postText':'','include':[],'exclude':[]},'content_rating':{'order':6,'show':False,'preText':'ContentRating: ','postText':'','include':[],'exclude':[]},'duration':{'order':7,'show':True,'preText':'Runtime: ','postText':' minutes','include':[],'exclude':[]},'year':{'order':8,'show':True,'preText':'Year: ','postText':'','include':[],'exclude':[]},'studio':{'order':9,'show':False,'preText':'Studio: ','postText':'','include':[],'exclude':[]},'rating':{'order':10,'show':True,'preText':'Rating: ','postText':'%','include':[],'exclude':[]}} - + if ('filter_sections_TV' not in config): config['filter_include_sections_TV'] = {'tagline':{'order':1,'show':True,'preText':'','postText':'','include':[],'exclude':[]},'summary':{'order':2,'show':True,'preText':'','postText':'','include':[],'exclude':[]},'tags_genre':{'order':3,'show':False,'preText':'Genre(s): ','postText':'','include':[],'exclude':[]},'tags_director':{'order':4,'show':False,'preText':'Director: ','postText':'','include':[],'exclude':[]},'tags_star':{'order':5,'show':False,'preText':'Star(s): ','postText':'','include':[],'exclude':[]},'content_rating':{'order':6,'show':False,'preText':'ContentRating: ','postText':'','include':[],'exclude':[]},'duration':{'order':7,'show':True,'preText':'Runtime: ','postText':' minutes','include':[],'exclude':[]},'year':{'order':8,'show':False,'preText':'Year: ','postText':'','include':[],'exclude':[]},'studio':{'order':9,'show':True,'preText':'Network: ','postText':'','include':[],'exclude':[]},'rating':{'order':10,'show':False,'preText':'Rating: ','postText':'%','include':[],'exclude':[]}} - + if ('web_only_save_images' not in config): config['web_only_save_images'] = False - + if ('filter_show_movies' not in config): config['filter_show_movies'] = True - + if ('filter_show_shows' not in config): config['filter_show_shows'] = True - + if ('filter_show_seasons' not in config): config['filter_show_seasons'] = True - + if ('filter_show_episodes' not in config): config['filter_show_episodes'] = True - + if ('date_minutes_back_to_search' not in config): config['date_minutes_back_to_search'] = 0 - + if ('msg_no_new_content' not in config): config['msg_no_new_content'] = 'There have been no new additions to Plex from {past_day} through {current_day}.' - + if ('email_skip_if_no_additions' not in config): config['email_skip_if_no_additions'] = False - + if ('web_skip_if_no_additions' not in config): config['web_skip_if_no_additions'] = False - + if ('date_days_back_to_search' not in config and 'days_back_to_search' in config): config['date_days_back_to_search'] = config['days_back_to_search'] - + if ('movie_sort_1' not in config.keys() or config['movie_sort_1'] == ""): config['movie_sort_1'] = 'rating' if ('movie_sort_2' not in config.keys() or config['movie_sort_2'] == ""): config['movie_sort_2'] = 'title_sort' - + if ('movie_sort_1_reverse' not in config.keys() or config['movie_sort_1_reverse'] == ""): config['movie_sort_1_reverse'] = True if ('movie_sort_2_reverse' not in config.keys() or config['movie_sort_2_reverse'] == ""): config['movie_sort_2_reverse'] = False if ('movie_sort_3_reverse' not in config.keys() or config['movie_sort_3_reverse'] == ""): config['movie_sort_3_reverse'] = False - + if ('show_sort_1' not in config.keys() or config['show_sort_1'] == ""): config['show_sort_1'] = 'title_sort' - + if ('show_sort_1_reverse' not in config.keys() or config['show_sort_1_reverse'] == ""): config['show_sort_1_reverse'] = False if ('show_sort_2_reverse' not in config.keys() or config['show_sort_2_reverse'] == ""): config['show_sort_2_reverse'] = False if ('show_sort_3_reverse' not in config.keys() or config['show_sort_3_reverse'] == ""): config['show_sort_3_reverse'] = False - + if ('season_sort_1' not in config.keys() or config['season_sort_1'] == ""): config['season_sort_1'] = 'title_sort' if ('season_sort_2' not in config.keys() or config['season_sort_2'] == ""): config['season_sort_2'] = 'index' - + if ('season_sort_1_reverse' not in config.keys() or config['season_sort_1_reverse'] == ""): config['season_sort_1_reverse'] = False if ('season_sort_2_reverse' not in config.keys() or config['season_sort_2_reverse'] == ""): config['season_sort_2_reverse'] = False if ('season_sort_3_reverse' not in config.keys() or config['season_sort_3_reverse'] == ""): config['season_sort_3_reverse'] = False - + if ('episode_sort_1' not in config.keys() or config['episode_sort_1'] == ""): config['episode_sort_1'] = 'show_title_sort' if ('episode_sort_2' not in config.keys() or config['episode_sort_2'] == ""): config['episode_sort_2'] = 'season_index' if ('episode_sort_3' not in config.keys() or config['episode_sort_3'] == ""): config['episode_sort_3'] = 'index' - + if ('episode_sort_1_reverse' not in config.keys() or config['episode_sort_1_reverse'] == ""): config['episode_sort_1_reverse'] = False if ('episode_sort_2_reverse' not in config.keys() or config['episode_sort_2_reverse'] == ""): config['episode_sort_2_reverse'] = False if ('episode_sort_3_reverse' not in config.keys() or config['episode_sort_3_reverse'] == ""): config['episode_sort_3_reverse'] = False - + # The below code is replacing tokens if (config['web_domain'].rfind('/') < len(config['web_domain']) - len('/')): config['web_domain'] = config['web_domain'] + '/' - + if (config['date_days_back_to_search'] == 31): now = datetime.datetime.now() if (now.month == 1): config['date_days_back_to_search'] = calendar.monthrange(now.year - 1, 12)[1] else: config['date_days_back_to_search'] = calendar.monthrange(now.year, now.month - 1)[1] - + for value in config: if (isinstance(config[value], str)): config[value] = config[value].replace('{past_day}', str((date.today() - timedelta(days=config['date_days_back_to_search'], hours=config['date_hours_back_to_search'], minutes=config['date_minutes_back_to_search'])).strftime(config['date_format']))) @@ -285,20 +288,20 @@ def replaceConfigTokens(): if (config['plex_data_folder'].rfind(os.path.sep) < len(config['plex_data_folder']) - len(os.path.sep)): config['plex_data_folder'] = config['plex_data_folder'] + os.path.sep - + if (config['plex_data_folder'].find('Plex Media Server') >= 0): config['plex_data_folder'] = config['plex_data_folder'][0:config['plex_data_folder'].find('Plex Media Server')] - + if (config['web_folder'].rfind(os.path.sep) < len(config['web_folder']) - len(os.path.sep)): config['web_folder'] = config['web_folder'] + os.path.sep - + if (config['web_domain'] != '' and config['web_domain'].rfind('/') < len(config['web_domain']) - len('/')): config['web_domain'] = config['web_domain'] + '/' - + if (config['logging_file_location'].rfind(os.path.sep) < len(config['logging_file_location']) - len(os.path.sep)): config['logging_file_location'] = config['logging_file_location'] + os.path.sep - - + + def convertToHumanReadable(valuesToConvert): convertedValues = {} for value in valuesToConvert: @@ -323,7 +326,7 @@ def getSharedUserEmails(): emails = [] if (config['plex_username'] == '' or config['plex_password'] == ''): return emails - + url = 'https://my.plexapp.com/users/sign_in.json' logging.info('getSharedUserEmails: url = ' + url) base64string = 'Basic ' + base64.encodestring('%s:%s' % (config['plex_username'], config['plex_password'])).replace('\n', '') @@ -334,7 +337,7 @@ def getSharedUserEmails(): logging.info('getSharedUserEmails: response = ' + str(response.text)) token = json.loads(response.text)['user']['authentication_token']; logging.info('getSharedUserEmails: token = ' + token) - + url = 'https://plex.tv/pms/friends/all' logging.info('getSharedUserEmails: url = ' + url) headers = {'Accept': 'application/json', 'X-Plex-Token': token} @@ -342,14 +345,14 @@ def getSharedUserEmails(): response = requests.get(url, headers=headers) logging.info('getSharedUserEmails: response = ' + str(response)) logging.info('getSharedUserEmails: response = ' + str(response.text.encode('ascii', 'ignore'))) - + parsed = XML(response.text.encode('ascii', 'ignore')) for elem in parsed: for name, value in sorted(elem.attrib.items()): if (name == 'email'): logging.info('getSharedUserEmails: adding email - ' + value.lower()) emails.append(value.lower()) - + logging.info('getSharedUserEmails: Returning shared emails') logging.debug('getSharedUserEmails: email list - ' + ' '.join(emails)) return emails @@ -363,7 +366,7 @@ def deleteImages(): logging.debug('deleteImages: deleting image: ' + folder + file) os.remove(folder + file) logging.info('deleteImages: end') - + def processImage(imageHash, thumb, mediaType, seasonIndex, episodeIndex): logging.info('processImage: begin') logging.info('processImage: imageHash = ' + imageHash + ' - thumb = ' + thumb + ' - mediaType = ' + mediaType + ' - seasonIndex = ' + str(seasonIndex) + ' - episodeIndex = ' + str(episodeIndex)) @@ -374,7 +377,7 @@ def processImage(imageHash, thumb, mediaType, seasonIndex, episodeIndex): thumbObj['webImgPath'] = '' thumbObj['emailImgPath'] = '' return thumbObj - + if (thumb.find('http://') >= 0 or thumb.find('https://') >= 0): logging.info('processImage: thumb is already an externally hosted image') thumbObj['webImgPath'] = thumb @@ -421,12 +424,12 @@ def processImage(imageHash, thumb, mediaType, seasonIndex, episodeIndex): imgName += '_' + imageHash webImgFullPath = config['web_domain'] + config['web_path'] + '/images/' + imgName + '.jpg' img = config['web_folder'] + config['web_path'] + os.path.sep + 'images' + os.path.sep + imgName + '.jpg' - + logging.info('processImage: imgLocation = ' + imgLocation) logging.info('processImage: webImgFullPath = ' + webImgFullPath) logging.info('processImage: img = ' + img) - - + + cloudinaryURL = '' if ('upload_use_cloudinary' in config and config['upload_use_cloudinary']): logging.info('processImage: Uploading to cloudinary') @@ -443,7 +446,7 @@ def processImage(imageHash, thumb, mediaType, seasonIndex, episodeIndex): else: logging.info('processImage: No email image') thumbObj['emailImgPath'] = '' - + if (cloudinaryURL != ''): logging.info('processImage: Setting image paths to cloudinary') thumbObj['webImgPath'] = cloudinaryURL @@ -460,16 +463,16 @@ def processImage(imageHash, thumb, mediaType, seasonIndex, episodeIndex): thumbObj['webImgPath'] = 'images/' + imgName + '.jpg' else: thumbObj['webImgPath'] = '' - + return thumbObj - + def uploadToImgur(imgToUpload, nameOfUpload): client_id = 'a0c7b089b62b220' headers = {"Authorization": "Client-ID " + client_id} url = "https://api.imgur.com/3/upload.json" if (os.path.isfile(imgToUpload)): response = requests.post( - url, + url, headers = headers, data = { 'image': b64encode(open(imgToUpload, 'rb').read()), @@ -482,7 +485,7 @@ def uploadToImgur(imgToUpload, nameOfUpload): return data['link'] else: return '' - + def uploadToCloudinary(imgToUpload): logging.info('uploadToCloudinary: begin') if (os.path.isfile(imgToUpload)): @@ -501,16 +504,16 @@ def uploadToCloudinary(imgToUpload): else: logging.info('uploadToCloudinary: file not located') return '' - + def containsnonasciicharacters(str): - return not all(ord(c) < 128 for c in str) + return not all(ord(c) < 128 for c in str) def addheader(message, headername, headervalue): if containsnonasciicharacters(headervalue): h = Header(headervalue, 'utf-8') message[headername] = h else: - message[headername] = headervalue + message[headername] = headervalue return message def sendMail(email): @@ -534,18 +537,18 @@ def sendMail(email): # Create the body of the message (a plain-text and an HTML version). text = config['msg_email_teaser'] - + # Record the MIME types of both parts - text/plain and text/html. if containsnonasciicharacters(emailHTML): htmltext = MIMEText(emailHTML, 'html','utf-8') else: - htmltext = MIMEText(emailHTML, 'html') + htmltext = MIMEText(emailHTML, 'html') if(containsnonasciicharacters(text)): - plaintext = MIMEText(text,'plain','utf-8') + plaintext = MIMEText(text,'plain','utf-8') else: plaintext = MIMEText(text,'plain') - + #Create image headers for image in imgNames: fp = open(imgNames[image], 'rb') @@ -574,9 +577,9 @@ def sendMail(email): server.login(gmail_user, gmail_pwd) server.sendmail(FROM, TO, msg.as_string()) server.close() - + return 1; - + def createEmailHTML(): emailText = """ @@ -596,7 +599,7 @@ def createEmailHTML(): - + @@ -604,18 +607,70 @@ def createEmailHTML(): @@ -638,7 +693,7 @@ def createEmailHTML():
""" - + emailText += emailNotice if (movieCount > 0 and config['filter_show_movies']): emailText += emailMovies + '
 ' @@ -654,18 +709,18 @@ def createEmailHTML(): emailText += emailAlbums + '
 ' if (songCount > 0 and config['filter_show_songs']): emailText += emailSongs - + if(not hasNewContent): emailText += """

""" + config['msg_no_new_content'] + """

""" - + emailText += """ -
@@ -795,7 +850,7 @@ def createWebHTML():
""" - + htmlText += htmlNotice if (movieCount > 0 and config['filter_show_movies']): htmlText += htmlMovies + '
 ' @@ -811,12 +866,12 @@ def createWebHTML(): htmlText += htmlAlbums + '
 ' if (songCount > 0 and config['filter_show_songs']): htmlText += htmlSongs - + if(not hasNewContent): htmlText += """

""" + config['msg_no_new_content'] + """

""" - + htmlText += """
@@ -839,9 +894,9 @@ def createWebHTML(): """ - + return htmlText - + def exceptionHandler(type, value, tb): logging.error("Logging an uncaught exception", exc_info=(type, value, tb)) @@ -868,7 +923,7 @@ def exceptionHandler(type, value, tb): if (not os.path.isfile(configFile)): print configFile + ' does not exist' sys.exit() - + config = {} execfile(configFile, config) replaceConfigTokens() @@ -918,12 +973,12 @@ def exceptionHandler(type, value, tb): logging.info('Including Plex Web Link - Getting machine identifier from the DLNA DB') DLNA_DB_FILE = config['plex_data_folder'] + 'Plex Media Server' + os.path.sep + 'Plug-in Support' + os.path.sep + 'Databases' + os.path.sep + 'com.plexapp.dlna.db' logging.info('DLNA_DB_FILE = ' + DLNA_DB_FILE) - + if (os.path.isfile(DLNA_DB_FILE)): try: shutil.copyfile(DLNA_DB_FILE, DLNA_DB_FILE + '_plexemail') con = sqlite3.connect(DLNA_DB_FILE + '_plexemail') - cur = con.cursor() + cur = con.cursor() cur.execute('SELECT machine_identifier FROM remote_servers WHERE url LIKE "http://127.0.0.1%";') for row in cur: plexWebLink = 'http://plex.tv/web/app#!/server/' + row[0] + '/details?key=%2Flibrary%2Fmetadata%2F' @@ -938,12 +993,12 @@ def exceptionHandler(type, value, tb): logging.warning(DLNA_DB_FILE + ' does not exist') DATABASE_FILE = config['plex_data_folder'] + 'Plex Media Server' + os.path.sep + 'Plug-in Support' + os.path.sep + 'Databases' + os.path.sep + 'com.plexapp.plugins.library.db' - + if (not os.path.isfile(DATABASE_FILE)): logging.error(DATABASE_FILE + ' does not exist. Please make sure the plex_data_folder value is correct.') print DATABASE_FILE + ' does not exist. Please make sure the plex_data_folder value is correct.' sys.exit() - + shutil.copyfile(DATABASE_FILE, DATABASE_FILE + '_plexemail') con = sqlite3.connect(DATABASE_FILE + '_plexemail') con.text_factory = str @@ -964,80 +1019,87 @@ def exceptionHandler(type, value, tb): if (libraryFilter != ''): libraryFilter += ') ' logging.debug('libraryFilter = ' + libraryFilter) - + cur.close() del cur - + dateSearch = 'datetime(\'now\', \'localtime\', \'-' + str(config['date_days_back_to_search']) + ' days\', \'-' + str(config['date_hours_back_to_search']) + ' hours\', \'-' + str(config['date_minutes_back_to_search']) + ' minutes\')' logging.debug('dateSearch for DB query = ' + dateSearch) dbQuery = "SELECT MD.id, MD.parent_id, MD.metadata_type, MD.title, MD.title_sort, MD.original_title, MD.rating, MD.tagline, MD.summary, MD.content_rating, MD.duration, MD.user_thumb_url, MD.tags_genre, MD.tags_director, MD.tags_star, MD.year, MD.hash, MD.[index], MD.studio, ME.duration, MD.originally_available_at FROM metadata_items MD LEFT OUTER JOIN media_items ME ON MD.id = ME.metadata_item_id WHERE added_at >= " + dateSearch + " AND metadata_type >= 1 AND metadata_type <= 10 " + libraryFilter + " ORDER BY title_sort;" logging.info('Executing DB query: ' + dbQuery) - cur = con.cursor() + cur = con.cursor() cur.execute(dbQuery) response = {}; logging.debug('Response:') for row in cur: response[row[0]] = {'id': row[0], 'parent_id': row[1], 'metadata_type': row[2], 'title': row[3], 'title_sort': row[4], 'original_title': row[5], 'rating': row[6], 'tagline': row[7], 'summary': row[8], 'content_rating': row[9], 'duration': row[10], 'user_thumb_url': row[11], 'tags_genre': row[12], 'tags_director': row[13], 'tags_star': row[14], 'year': row[15], 'hash': row[16], 'index': row[17], 'studio': row[18], 'real_duration': row[19], 'air_date': row[20]} - logging.debug(response[row[0]]) - + logging.debug(response[row[0]]) + cur.close() del cur - + emailNotice = '' htmlNotice = '' if (config['msg_notice']): logging.info('Generating html for the notice: ' + config['msg_notice']) emailNotice = """
 
""" + config['msg_notice'] + """

 """ htmlNotice = """

""" + config['msg_notice'] + """
""" - emailMovies = """
+ emailMovies = """
+

""" + config['msg_new_movies_header'] + """

-


 """ +
""" htmlMovies = """
-
+

""" + config['msg_new_movies_header'] + """

""" - emailTVShows = """
+ emailTVShows = """
+

""" + config['msg_new_shows_header'] + """

-


 """ +
""" htmlTVShows = """
-
+

""" + config['msg_new_shows_header'] + """

""" - emailTVSeasons = """
+ emailTVSeasons = """
+

""" + config['msg_new_seasons_header'] + """

-


 """ +
""" htmlTVSeasons = """
-
+

""" + config['msg_new_seasons_header'] + """

""" - emailTVEpisodes = """
+ emailTVEpisodes = """
+

""" + config['msg_new_episodes_header'] + """

-


 """ +
""" htmlTVEpisodes = """
-
+

""" + config['msg_new_episodes_header'] + """

""" - emailArtists = """
+ emailArtists = """
+

""" + config['msg_new_artists_header'] + """

-


 """ +
""" htmlArtists = """
-
+

""" + config['msg_new_artists_header'] + """

""" - emailAlbums = """
+ emailAlbums = """
+

""" + config['msg_new_albums_header'] + """

-


 """ +
""" htmlAlbums= """
-
+

""" + config['msg_new_albums_header'] + """

""" - emailSongs = """
+ emailSongs = """
+

""" + config['msg_new_songs_header'] + """

-


 """ +
""" htmlSongs = """
-
+

""" + config['msg_new_songs_header'] + """

""" movies = {} @@ -1061,34 +1123,34 @@ def exceptionHandler(type, value, tb): #Handle New Movies if (response[item]['metadata_type'] == 1): movies[response[item]['id']] = response[item] - + #TV if (response[item]['metadata_type'] == 2): tvShows[response[item]['id']] = response[item] - + if (response[item]['metadata_type'] == 3): tvSeasons[response[item]['id']] = response[item] - + if (response[item]['metadata_type'] == 4): tvEpisodes[response[item]['id']] = response[item] - - #Music + + #Music if (response[item]['metadata_type'] == 8): artists[response[item]['id']] = response[item] - + if (response[item]['metadata_type'] == 9): albums[response[item]['id']] = response[item] - + if (response[item]['metadata_type'] == 10): songs[response[item]['id']] = response[item] - + if ('movie_sort_3' in config and config['movie_sort_3'] != ''): movies = OrderedDict(sorted(movies.iteritems(), key=lambda t: t[1][config['movie_sort_3']], reverse=config['movie_sort_3_reverse'])) if ('movie_sort_2' in config and config['movie_sort_2'] != ''): movies = OrderedDict(sorted(movies.iteritems(), key=lambda t: t[1][config['movie_sort_2']], reverse=config['movie_sort_2_reverse'])) if ('movie_sort_1' in config and config['movie_sort_1'] != ''): movies = OrderedDict(sorted(movies.iteritems(), key=lambda t: t[1][config['movie_sort_1']], reverse=config['movie_sort_1_reverse'])) - + for movie in movies: movies[movie] = convertToHumanReadable(movies[movie]) title = '' @@ -1099,7 +1161,7 @@ def exceptionHandler(type, value, tb): imageInfo = {} imageInfo['thumb'] = movies[movie]['user_thumb_url'] imageInfo = processImage(hash, imageInfo['thumb'], 'movie', 0, 0) - + skipItem = False emailText = '' htmlText = '' @@ -1107,17 +1169,18 @@ def exceptionHandler(type, value, tb): pwLink = plexWebLink + str(movies[movie]['id']) else: pwLink = '' - - emailText += '' + + emailText += '
' if (config['filter_show_email_images']): - emailText += '' + emailText += '' - emailText += '
' emailText += '' - emailText += '

' + title.decode('utf-8') + '

' + emailText += '
' + emailText += '
' + emailText += '

' + title.decode('utf-8') + '

' htmlText += '
' htmlText += '' htmlText += '

' + title.decode('utf-8') + '

' - + sections = config['filter_sections_movies'] for section in sorted(sections.iteritems(), key=lambda t: t[1]['order']): if (movies[movie][section[0]] in sections[section[0]]['exclude'] or len(set(movies[movie][section[0] + '_filter']).intersection(sections[section[0]]['exclude'])) > 0 or (sections[section[0]]['include'] and movies[movie][section[0]] not in sections[section[0]]['include'] and len(set(movies[movie][section[0] + '_filter']).intersection(sections[section[0]]['include'])) == 0)): @@ -1128,27 +1191,27 @@ def exceptionHandler(type, value, tb): displayText = time.strftime(sections[section[0]]['format'], time.strptime(displayText, '%Y-%m-%d %H:%M:%S')) emailText += '

' + sections[section[0]]['preText'].decode('utf-8') + displayText.decode('utf-8') + sections[section[0]]['postText'].decode('utf-8') + '

' htmlText += '

' + sections[section[0]]['preText'].decode('utf-8') + displayText.decode('utf-8') + sections[section[0]]['postText'].decode('utf-8') + '

' - - emailText += '

 
 ' + + emailText += '

 
 ' htmlText += '

 
 ' - + titleFilter = [] - + if (movies[movie]['title'] in config['filter_movies_exclude'] or len(set(titleFilter).intersection(config['filter_movies_exclude'])) > 0 or (config['filter_movies_include'] and movies[movie]['title'] not in config['filter_movies_include'] and len(set(titleFilter).intersection(config['filter_movies_include'])) == 0)): skipItem = True - + if (not skipItem): movieCount += 1 emailMovies += emailText htmlMovies += htmlText - + if ('show_sort_3' in config and config['show_sort_3'] != ''): tvShows = OrderedDict(sorted(tvShows.iteritems(), key=lambda t: t[1][config['show_sort_3']], reverse=config['show_sort_3_reverse'])) if ('show_sort_2' in config and config['show_sort_2'] != ''): tvShows = OrderedDict(sorted(tvShows.iteritems(), key=lambda t: t[1][config['show_sort_2']], reverse=config['show_sort_2_reverse'])) if ('show_sort_1' in config and config['show_sort_1'] != ''): tvShows = OrderedDict(sorted(tvShows.iteritems(), key=lambda t: t[1][config['show_sort_1']], reverse=config['show_sort_1_reverse'])) - + for show in tvShows: tvShows[show] = convertToHumanReadable(tvShows[show]) title = '' @@ -1159,7 +1222,7 @@ def exceptionHandler(type, value, tb): imageInfo = {} imageInfo['thumb'] = tvShows[show]['user_thumb_url'] imageInfo = processImage(hash, imageInfo['thumb'], 'show', 0, 0) - + skipItem = False emailText = '' htmlText = '' @@ -1167,15 +1230,18 @@ def exceptionHandler(type, value, tb): pwLink = plexWebLink + str(tvShows[show]['id']) else: pwLink = '' - - emailText += '' + + emailText += '
' - emailText += '
' if (config['filter_show_email_images']): - emailText += '

' + title.decode('utf-8') + '

' + emailText += '
' + emailText += '' + emailText += '
' + emailText += '
' + emailText += '

' + title.decode('utf-8') + '

' htmlText += '
' htmlText += '' htmlText += '

' + title.decode('utf-8') + '

' - + sections = config['filter_sections_TV'] for section in sorted(sections.iteritems(), key=lambda t: t[1]['order']): if (tvShows[show][section[0]] in sections[section[0]]['exclude'] or len(set(tvShows[show][section[0] + '_filter']).intersection(sections[section[0]]['exclude'])) > 0 or (sections[section[0]]['include'] and tvShows[show][section[0]] not in sections[section[0]]['include'] and len(set(tvShows[show][section[0] + '_filter']).intersection(sections[section[0]]['include'])) == 0)): @@ -1186,20 +1252,20 @@ def exceptionHandler(type, value, tb): displayText = time.strftime(sections[section[0]]['format'], time.strptime(displayText, '%Y-%m-%d %H:%M:%S')) emailText += '

' + sections[section[0]]['preText'].decode('utf-8') + displayText.decode('utf-8') + sections[section[0]]['postText'].decode('utf-8') + '

' htmlText += '

' + sections[section[0]]['preText'].decode('utf-8') + displayText.decode('utf-8') + sections[section[0]]['postText'].decode('utf-8') + '

' - - emailText += '

 
 ' + + emailText += '

 
 ' htmlText += '

 
 ' - + titleFilter = [] - + if (tvShows[show]['title'] in config['filter_shows_exclude'] or len(set(titleFilter).intersection(config['filter_shows_exclude'])) > 0 or (config['filter_shows_include'] and tvShows[show]['title'] not in config['filter_shows_include'] and len(set(titleFilter).intersection(config['filter_shows_include'])) == 0)): skipItem = True - + if (not skipItem): showCount += 1 emailTVShows += emailText htmlTVShows += htmlText - + for season in tvSeasons: cur2 = con.cursor() cur2.execute("SELECT title, title_sort, original_title, rating, tagline, summary, content_rating, duration, tags_genre, tags_director, tags_star, year, hash, user_thumb_url, studio FROM metadata_items WHERE id = " + str(tvSeasons[season]['parent_id']) + ";") @@ -1220,17 +1286,17 @@ def exceptionHandler(type, value, tb): tvSeasons[season]['parent_hash'] = row[12] tvSeasons[season]['parent_thumb_url'] = row[13] tvSeasons[season]['studio'] = row[14] - + cur2.close() del cur2 - + if ('season_sort_3' in config and config['season_sort_3'] != ''): tvSeasons = OrderedDict(sorted(tvSeasons.iteritems(), key=lambda t: t[1][config['season_sort_3']], reverse=config['season_sort_3_reverse'])) if ('season_sort_2' in config and config['season_sort_2'] != ''): tvSeasons = OrderedDict(sorted(tvSeasons.iteritems(), key=lambda t: t[1][config['season_sort_2']], reverse=config['season_sort_2_reverse'])) if ('season_sort_1' in config and config['season_sort_1'] != ''): tvSeasons = OrderedDict(sorted(tvSeasons.iteritems(), key=lambda t: t[1][config['season_sort_1']], reverse=config['season_sort_1_reverse'])) - + for season in tvSeasons: tvSeasons[season] = convertToHumanReadable(tvSeasons[season]) title = '' @@ -1246,7 +1312,7 @@ def exceptionHandler(type, value, tb): imageInfo['thumb'] = tvSeasons[season]['parent_thumb_url'] hash = str(tvSeasons[season]['parent_hash']) imageInfo = processImage(hash, imageInfo['thumb'], 'show', 0, 0) - + skipItem = False emailText = '' htmlText = '' @@ -1254,17 +1320,20 @@ def exceptionHandler(type, value, tb): pwLink = plexWebLink + str(tvSeasons[season]['id']) else: pwLink = '' - - emailText += '' - if (config['filter_show_email_images']): - emailText += '' - emailText += '

' + title.decode('utf-8') + '

' + + emailText += '
' + if (config['filter_show_email_images'] and len(imageInfo) != 0): + emailText += '' + emailText += '
' + emailText += '
' + emailText += '
' + emailText += '

' + title.decode('utf-8') + '

' emailText += '

Season ' + str(tvSeasons[season]['index']) + '

' htmlText += '
' htmlText += '' htmlText += '

' + title.decode('utf-8') + '

' - htmlText += '

Season ' + str(tvSeasons[season]['index']) + '

' - + htmlText += '

Season ' + str(tvSeasons[season]['index']) + '

' + sections = config['filter_sections_TV'] for section in sorted(sections.iteritems(), key=lambda t: t[1]['order']): if (tvSeasons[season][section[0]] in sections[section[0]]['exclude'] or len(set(tvSeasons[season][section[0] + '_filter']).intersection(sections[section[0]]['exclude'])) > 0 or (sections[section[0]]['include'] and tvSeasons[season][section[0]] not in sections[section[0]]['include'] and len(set(tvSeasons[season][section[0] + '_filter']).intersection(sections[section[0]]['include'])) == 0)): @@ -1275,20 +1344,20 @@ def exceptionHandler(type, value, tb): displayText = time.strftime(sections[section[0]]['format'], time.strptime(displayText, '%Y-%m-%d %H:%M:%S')) emailText += '

' + sections[section[0]]['preText'].decode('utf-8') + displayText.decode('utf-8') + sections[section[0]]['postText'].decode('utf-8') + '

' htmlText += '

' + sections[section[0]]['preText'].decode('utf-8') + displayText.decode('utf-8') + sections[section[0]]['postText'].decode('utf-8') + '

' - - emailText += '

 
 ' + + emailText += '

 
 ' htmlText += '

 
 ' - + titleFilter = [] - + if (tvSeasons[season]['title'] in config['filter_seasons_exclude'] or len(set(titleFilter).intersection(config['filter_seasons_exclude'])) > 0 or (config['filter_seasons_include'] and tvSeasons[season]['title'] not in config['filter_seasons_include'] and len(set(titleFilter).intersection(config['filter_seasons_include'])) == 0)): skipItem = True - + if (not skipItem): seasonCount += 1 emailTVSeasons += emailText htmlTVSeasons += htmlText - + modifiedTVEpisodes = dict(tvEpisodes) for episode in tvEpisodes: logging.debug('main: hash = ' + tvEpisodes[episode]['hash']) @@ -1305,10 +1374,10 @@ def exceptionHandler(type, value, tb): tvEpisodes[episode]['season_hash'] = row[3] logging.debug('main: season_hash = ' + row[3]) logging.debug('main: season_thumb_url = ' + row[0]) - + cur3 = con.cursor() cur3.execute("SELECT title, title_sort, original_title, content_rating, duration, tags_genre, tags_star, hash, user_thumb_url, studio FROM metadata_items WHERE id = " + str(parent_id) + ";") - + for row2 in cur3: tvEpisodes[episode]['show_title'] = row2[0] tvEpisodes[episode]['show_title_sort'] = row2[1] @@ -1322,25 +1391,25 @@ def exceptionHandler(type, value, tb): tvEpisodes[episode]['show_thumb_url'] = row2[8] logging.debug('main: show_thumb_url = ' + row2[8]) tvEpisodes[episode]['studio'] = row2[9] - + cur3.close() del cur3 else: logging.info('main: tvEpisodes[episode][\'parent_id\'] = None') del modifiedTVEpisodes[episode] - + cur2.close() del cur2 - + tvEpisodes = dict(modifiedTVEpisodes) - + if ('episode_sort_3' in config and config['episode_sort_3'] != ''): tvEpisodes = OrderedDict(sorted(tvEpisodes.iteritems(), key=lambda t: t[1][config['episode_sort_3']], reverse=config['episode_sort_3_reverse'])) if ('episode_sort_2' in config and config['episode_sort_2'] != ''): tvEpisodes = OrderedDict(sorted(tvEpisodes.iteritems(), key=lambda t: t[1][config['episode_sort_2']], reverse=config['episode_sort_2_reverse'])) if ('episode_sort_1' in config and config['episode_sort_1'] != ''): tvEpisodes = OrderedDict(sorted(tvEpisodes.iteritems(), key=lambda t: t[1][config['episode_sort_1']], reverse=config['episode_sort_1_reverse'])) - + for episode in tvEpisodes: if (tvEpisodes[episode]['parent_id'] not in tvSeasons): tvEpisodes[episode] = convertToHumanReadable(tvEpisodes[episode]) @@ -1367,7 +1436,7 @@ def exceptionHandler(type, value, tb): imageInfo['thumb'] = tvEpisodes[episode]['show_thumb_url'] hash = str(tvEpisodes[episode]['show_hash']) imageInfo = processImage(hash, imageInfo['thumb'], 'show', 0, 0) - + skipItem = False emailText = '' htmlText = '' @@ -1375,18 +1444,21 @@ def exceptionHandler(type, value, tb): pwLink = plexWebLink + str(tvEpisodes[episode]['id']) else: pwLink = '' - - emailText += '' + + emailText += '
' - emailText += '
' if (config['filter_show_email_images'] and len(imageInfo) != 0): - emailText += '

' + showTitle.decode('utf-8') + '

' - emailText += '

S' + str(tvEpisodes[episode]['season_index']) + ' E' + str(tvEpisodes[episode]['index']) + ': ' + title.decode('utf-8') + '

' + emailText += '' + emailText += '
' + emailText += '
' + emailText += '
' + emailText += '

' + showTitle.decode('utf-8') + '

' + emailText += '

S' + str(tvEpisodes[episode]['season_index']) + ' E' + str(tvEpisodes[episode]['index']) + ': ' + title.decode('utf-8') + '

' htmlText += '
' if (len(imageInfo) != 0): htmlText += '' htmlText += '

' + showTitle.decode('utf-8') + '

' htmlText += '

S' + str(tvEpisodes[episode]['season_index']) + ' E' + str(tvEpisodes[episode]['index']) + ': ' + title.decode('utf-8') + '

' - + sections = config['filter_sections_TV'] for section in sorted(sections.iteritems(), key=lambda t: t[1]['order']): if (tvEpisodes[episode][section[0]] in sections[section[0]]['exclude'] or len(set(tvEpisodes[episode][section[0] + '_filter']).intersection(sections[section[0]]['exclude'])) > 0 or (sections[section[0]]['include'] and tvEpisodes[episode][section[0]] not in sections[section[0]]['include'] and len(set(tvEpisodes[episode][section[0] + '_filter']).intersection(sections[section[0]]['include'])) == 0)): @@ -1397,15 +1469,15 @@ def exceptionHandler(type, value, tb): displayText = time.strftime(sections[section[0]]['format'], time.strptime(displayText, '%Y-%m-%d %H:%M:%S')) emailText += '

' + sections[section[0]]['preText'].decode('utf-8') + displayText.decode('utf-8') + sections[section[0]]['postText'].decode('utf-8') + '

' htmlText += '

' + sections[section[0]]['preText'].decode('utf-8') + displayText.decode('utf-8') + sections[section[0]]['postText'].decode('utf-8') + '

' - - emailText += '

 
 ' + + emailText += '

 
 ' htmlText += '

 
 ' - + titleFilter = [] - + if (tvEpisodes[episode]['show_title'] in config['filter_episodes_exclude'] or len(set(titleFilter).intersection(config['filter_episodes_exclude'])) > 0 or (config['filter_episodes_include'] and tvEpisodes[episode]['show_title'] not in config['filter_episodes_include'] and len(set(titleFilter).intersection(config['filter_episodes_include'])) == 0)): skipItem = True - + if (not skipItem): episodeCount += 1 emailTVEpisodes += emailText @@ -1417,7 +1489,7 @@ def exceptionHandler(type, value, tb): artists = OrderedDict(sorted(artists.iteritems(), key=lambda t: t[1][config['artist_sort_2']], reverse=config['artist_sort_2_reverse'])) if ('artist_sort_1' in config and config['artist_sort_1'] != ''): artists = OrderedDict(sorted(artists.iteritems(), key=lambda t: t[1][config['artist_sort_1']], reverse=config['artist_sort_1_reverse'])) - + for artist in artists: artists[artist] = convertToHumanReadable(artists[artist]) title = '' @@ -1428,7 +1500,7 @@ def exceptionHandler(type, value, tb): imageInfo = {} imageInfo['thumb'] = artists[artist]['user_thumb_url'] imageInfo = processImage(hash, imageInfo['thumb'], 'artist', 0, 0) - + skipItem = False emailText = '' htmlText = '' @@ -1436,7 +1508,7 @@ def exceptionHandler(type, value, tb): pwLink = plexWebLink + str(artists[artist]['id']) else: pwLink = '' - + emailText += '' if (config['filter_show_email_images']): emailText += '' @@ -1444,7 +1516,7 @@ def exceptionHandler(type, value, tb): htmlText += '
' htmlText += '' htmlText += '

' + title.decode('utf-8') + '

' - + sections = config['filter_sections_Music'] for section in sorted(sections.iteritems(), key=lambda t: t[1]['order']): if (section[0] != 'track_list'): @@ -1456,20 +1528,20 @@ def exceptionHandler(type, value, tb): displayText = time.strftime(sections[section[0]]['format'], time.strptime(displayText, '%Y-%m-%d %H:%M:%S')) emailText += '

' + sections[section[0]]['preText'].decode('utf-8') + displayText.decode('utf-8') + sections[section[0]]['postText'].decode('utf-8') + '

' htmlText += '

' + sections[section[0]]['preText'].decode('utf-8') + displayText.decode('utf-8') + sections[section[0]]['postText'].decode('utf-8') + '

' - + emailText += '

 
 ' htmlText += '

 
 ' - + titleFilter = [] - + if (artists[artist]['title'] in config['filter_artists_exclude'] or len(set(titleFilter).intersection(config['filter_artists_exclude'])) > 0 or (config['filter_artists_include'] and artists[artist]['title'] not in config['filter_artists_include'] and len(set(titleFilter).intersection(config['filter_artists_include'])) == 0)): skipItem = True - + if (not skipItem): artistCount += 1 emailArtists += emailText htmlArtists += htmlText - + for album in albums: cur2 = con.cursor() cur2.execute("SELECT title, title_sort, original_title, rating, tagline, summary, content_rating, duration, tags_genre, tags_director, tags_star, year, hash, user_thumb_url, studio FROM metadata_items WHERE id = " + str(albums[album]['parent_id']) + ";") @@ -1490,13 +1562,13 @@ def exceptionHandler(type, value, tb): albums[album]['parent_hash'] = row[12] albums[album]['parent_thumb_url'] = row[13] albums[album]['studio'] = row[14] - + cur2.close() del cur2 - + cur2 = con.cursor() cur2.execute("SELECT MD.id, MD.title, MD.title_sort, MD.original_title, MD.[index], ME.duration, ME.audio_codec FROM metadata_items MD LEFT OUTER JOIN media_items ME ON MD.id = ME.metadata_item_id WHERE parent_id = " + str(albums[album]['id']) + ";") - + albums[album]['tracks'] = {} for row in cur2: duration = row[5] @@ -1512,7 +1584,7 @@ def exceptionHandler(type, value, tb): except TypeError: duration = 'N/A' albums[album]['tracks'][row[4]] = {'id': row[0], 'title': row[1], 'title_sort': row[2], 'original_title': row[3], 'index': row[4], 'duration': duration, 'codec': row[6]} - + cur2.close() del cur2 if ('album_sort_3' in config and config['album_sort_3'] != ''): @@ -1521,7 +1593,7 @@ def exceptionHandler(type, value, tb): albums = OrderedDict(sorted(albums.iteritems(), key=lambda t: t[1][config['album_sort_2']], reverse=config['album_sort_2_reverse'])) if ('album_sort_1' in config and config['album_sort_1'] != ''): albums = OrderedDict(sorted(albums.iteritems(), key=lambda t: t[1][config['album_sort_1']], reverse=config['album_sort_1_reverse'])) - + for album in albums: albums[album] = convertToHumanReadable(albums[album]) title = '' @@ -1543,7 +1615,7 @@ def exceptionHandler(type, value, tb): pwLink = plexWebLink + str(albums[album]['id']) else: pwLink = '' - + emailText += '' if (config['filter_show_email_images']): emailText += '' @@ -1551,7 +1623,7 @@ def exceptionHandler(type, value, tb): htmlText += '
' htmlText += '' htmlText += '

' + title.decode('utf-8') + '

' - + tracklistEmailText = '' tracklistHTMLText = '' sections = config['filter_sections_Music'] @@ -1576,19 +1648,19 @@ def exceptionHandler(type, value, tb): displayText = time.strftime(sections[section[0]]['format'], time.strptime(displayText, '%Y-%m-%d %H:%M:%S')) emailText += '

' + sections[section[0]]['preText'].decode('utf-8') + displayText.decode('utf-8') + sections[section[0]]['postText'].decode('utf-8') + '

' htmlText += '

' + sections[section[0]]['preText'].decode('utf-8') + displayText.decode('utf-8') + sections[section[0]]['postText'].decode('utf-8') + '

' - + emailText += '
' emailText += tracklistEmailText if (trackCount > 0) else '' emailText += '
 
 ' htmlText += '' htmlText += tracklistHTMLText if (trackCount > 0) else '' htmlText += '
 
 ' - + titleFilter = [] - + if (albums[album]['title'] in config['filter_albums_exclude'] or len(set(titleFilter).intersection(config['filter_albums_exclude'])) > 0 or (config['filter_albums_include'] and albums[album]['title'] not in config['filter_albums_include'] and len(set(titleFilter).intersection(config['filter_albums_include'])) == 0)): skipItem = True - + if (not skipItem): albumCount += 1 emailAlbums += emailText @@ -1602,10 +1674,10 @@ def exceptionHandler(type, value, tb): # songs[song]['season_thumb_url'] = row[0] # parent_id = row[1] # songs[song]['season_index'] = row[2] - + # cur3 = con.cursor() # cur3.execute("SELECT title, title_sort, original_title, content_rating, duration, tags_genre, tags_star, hash, user_thumb_url, studio FROM metadata_items WHERE id = " + str(parent_id) + ";") - + # for row2 in cur3: # songs[song]['show_title'] = row2[0] # songs[song]['show_title_sort'] = row2[1] @@ -1617,14 +1689,14 @@ def exceptionHandler(type, value, tb): # songs[song]['hash'] = row2[7] # songs[song]['show_thumb_url'] = row2[8] # songs[song]['studio'] = row2[9] - + # if ('song_sort_3' in config and config['song_sort_3'] != ''): # songs = OrderedDict(sorted(songs.iteritems(), key=lambda t: t[1][config['song_sort_3']], reverse=config['song_sort_3_reverse'])) # if ('song_sort_2' in config and config['song_sort_2'] != ''): # songs = OrderedDict(sorted(songs.iteritems(), key=lambda t: t[1][config['song_sort_2']], reverse=config['song_sort_2_reverse'])) # if ('song_sort_1' in config and config['song_sort_1'] != ''): # songs = OrderedDict(sorted(songs.iteritems(), key=lambda t: t[1][config['song_sort_1']], reverse=config['song_sort_1_reverse'])) - + # for song in songs: # if (songs[song]['parent_id'] not in tvSeasons): # songs[song] = convertToHumanReadable(songs[song]) @@ -1650,9 +1722,9 @@ def exceptionHandler(type, value, tb): # elif (imageTypeToUse == 'artist'): # imageInfo['thumb'] = songs[song]['show_thumb_url'] # imageInfo = processImage(hash, imageInfo['thumb'], 'show', 0, 0) - + # print imageInfo - # print + # print # skipItem = False # emailText = '' # htmlText = '' @@ -1660,7 +1732,7 @@ def exceptionHandler(type, value, tb): # pwLink = plexWebLink + str(songs[song]['id']) # else: # pwLink = '' - + # emailText += '' # if (config['filter_show_email_images']): # emailText += '' @@ -1670,7 +1742,7 @@ def exceptionHandler(type, value, tb): # htmlText += '' # htmlText += '

' + showTitle.decode('utf-8') + '

' # htmlText += '

S' + str(songs[song]['season_index']) + ' E' + str(songs[song]['index']) + ': ' + title.decode('utf-8') + '

' - + # sections = config['filter_sections_TV'] # for section in sorted(sections.iteritems(), key=lambda t: t[1]['order']): # if (songs[song][section[0]] in sections[section[0]]['exclude'] or len(set(songs[song][section[0] + '_filter']).intersection(sections[section[0]]['exclude'])) > 0 or (sections[section[0]]['include'] and songs[song][section[0]] not in sections[section[0]]['include'] and len(set(songs[song][section[0] + '_filter']).intersection(sections[section[0]]['include'])) == 0)): @@ -1681,25 +1753,25 @@ def exceptionHandler(type, value, tb): # displayText = time.strftime(sections[section[0]]['format'], time.strptime(displayText, '%Y-%m-%d %H:%M:%S')) # emailText += '

' + sections[section[0]]['preText'].decode('utf-8') + displayText.decode('utf-8') + sections[section[0]]['postText'].decode('utf-8') + '

' # htmlText += '

' + sections[section[0]]['preText'].decode('utf-8') + displayText.decode('utf-8') + sections[section[0]]['postText'].decode('utf-8') + '

' - + # emailText += '

 
 ' # htmlText += '
 
 ' - + # titleFilter = [] - + # if (songs[song]['show_title'] in config['filter_songs_exclude'] or len(set(titleFilter).intersection(config['filter_songs_exclude'])) > 0 or (config['filter_songs_include'] and songs[song]['show_title'] not in config['filter_songs_include'] and len(set(titleFilter).intersection(config['filter_songs_include'])) == 0)): # skipItem = True - + # if (not skipItem): # songCount += 1 # emailSongs += emailText # htmlSongs += htmlText - + if ((movieCount > 0 and config['filter_show_movies']) or (showCount > 0 and config['filter_show_shows']) or (seasonCount > 0 and config['filter_show_seasons']) or (episodeCount > 0 and config['filter_show_episodes']) or (artistCount > 0 and config['filter_show_artists']) or (albumCount > 0 and config['filter_show_albums']) or (songCount > 0 and config['filter_show_songs'])): hasNewContent = True else: hasNewContent = False - + emailHTML = createEmailHTML() webHTML = createWebHTML() @@ -1711,7 +1783,7 @@ def exceptionHandler(type, value, tb): print 'Web page was not created because the option is disabled in the config file.' else: print 'Web page was not created because there were no new additions in the timeframe specified.' - + if (config['email_enabled'] and (not config['email_skip_if_no_additions'] or hasNewContent)): # try: if (config['email_to_send_to_shared_users']): @@ -1720,7 +1792,7 @@ def exceptionHandler(type, value, tb): #Remove duplicates by converting to a set config['email_to'] = set(config['email_to']) - + emailCount = 0 if (testMode): success = sendMail([config['email_from']]) @@ -1742,4 +1814,4 @@ def exceptionHandler(type, value, tb): print 'Emails were not sent because there were no new additions in the timeframe specified.' con.close() -os.remove(DATABASE_FILE + '_plexemail') \ No newline at end of file +os.remove(DATABASE_FILE + '_plexemail') From bbd241b59a538b34cd5d2a0479daeaa1a1a3a58f Mon Sep 17 00:00:00 2001 From: Keith Lamprecht Date: Sun, 26 Nov 2017 23:29:17 -0500 Subject: [PATCH 2/2] Update CSS For Mobile --- web/css/one-page-wonder.css | 45 +++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/web/css/one-page-wonder.css b/web/css/one-page-wonder.css index e7ff0c0..dbc1a0f 100644 --- a/web/css/one-page-wonder.css +++ b/web/css/one-page-wonder.css @@ -40,6 +40,10 @@ body { margin: 80px 0; } +.featurette-divider:first-of-type { + margin: 0 !important; +} + .featurette { overflow: hidden; } @@ -59,6 +63,7 @@ body { footer { margin: 50px 0; + text-align: center; } .info { @@ -190,4 +195,44 @@ footer { margin-bottom: 10px; margin-left: 0; } +} + +@media(max-width:767px) { + .headline { + padding: 75px 0 75px 0 !important; + } + + .featurette { + text-align: justify; + } + + .featurette > div { + margin-left: 0 !important; + } + + .pull-left { + float: none !important; + } + + .pull-right { + float: none !important; + } + + .featurette-image { + margin-right: auto !important; + margin-bottom: 30px !important; + margin-left: auto !important; + } + + .featurette-heading { + text-align: center; + } + + .subtitle { + text-align: center; + } + + .lead:first-of-type { + text-align: center; + } } \ No newline at end of file