From 395a8efb9376f33a3bdfc5762582ce44ff13a4cb Mon Sep 17 00:00:00 2001 From: Moe Fwacky Date: Sat, 6 Feb 2021 23:33:54 -0800 Subject: [PATCH] Python 3 migration changes --- both-dir/PseudoChannel.py | 979 +++++++++++++----- both-dir/pseudo_config.py | 18 +- both-dir/src/PseudoChannelCommercial.py | 51 +- both-dir/src/PseudoChannelDatabase.py | 231 +++-- both-dir/src/PseudoChannelRandomMovie.py | 16 +- both-dir/src/PseudoDailyScheduleController.py | 431 +++++--- channel-dir/report_MediaFolders.py | 6 +- main-dir/Global_DatabaseUpdate.py | 43 +- main-dir/controls.py | 224 ++++ main-dir/setup.py | 86 ++ 10 files changed, 1539 insertions(+), 546 deletions(-) create mode 100644 main-dir/controls.py create mode 100644 main-dir/setup.py diff --git a/both-dir/PseudoChannel.py b/both-dir/PseudoChannel.py index a2e6016..a7bbe09 100644 --- a/both-dir/PseudoChannel.py +++ b/both-dir/PseudoChannel.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# import importlib +import sys import signal import datetime from datetime import time @@ -11,8 +11,7 @@ import calendar import itertools import argparse import textwrap -import os -import sys +import os, sys from xml.dom import minidom import xml.etree.ElementTree as ET import json @@ -32,9 +31,10 @@ from src import PseudoDailyScheduleController from src import PseudoChannelCommercial from src import PseudoChannelRandomMovie import pseudo_config as config +from importlib import reload -# importlib.reload(sys) -# sys.setdefaultencoding('utf-8') +reload(sys) +#sys.setdefaultencoding('utf-8') class PseudoChannel(): @@ -43,7 +43,7 @@ class PseudoChannel(): GKEY = config.gkey USING_COMMERCIAL_INJECTION = config.useCommercialInjection DAILY_UPDATE_TIME = config.dailyUpdateTime - APP_TIME_FORMAT_STR = '%I:%M:%S %p' + APP_TIME_FORMAT_STR = '%H:%M:%S' COMMERCIAL_PADDING_IN_SECONDS = config.commercialPadding CONTROLLER_SERVER_PATH = config.controllerServerPath CONTROLLER_SERVER_PORT = config.controllerServerPort @@ -94,15 +94,15 @@ class PseudoChannel(): filled_length = int(round(bar_length * iteration / float(total))) bar = '█' * filled_length + '-' * (bar_length - filled_length) - sys.stdout.write('\r%s |%s| %s%s %s' % (prefix, bar, percents, '%', suffix)), + sys.stdout.write('\x1b[2K\r%s |%s| %s%s %s' % (prefix, bar, percents, '%', suffix)), - if iteration == total: - sys.stdout.write('\n') + #if iteration == total: + # sys.stdout.write('\n') sys.stdout.flush() def update_db(self): - print("#### Updating Local Database") + print("NOTICE: Updating Local Database") self.db.create_tables() libs_dict = config.plexLibraries sections = self.PLEX.library.sections() @@ -116,38 +116,28 @@ class PseudoChannel(): self.print_progress( i + 1, len(sectionMedia), - prefix = 'Progress '+section.title+": ", - suffix = 'Complete', + prefix = 'Progress '+section.title+": ", + suffix = 'Complete ['+media.title+']', bar_length = 40 ) + #print('') elif correct_lib_name == "TV Shows": sectionMedia = self.PLEX.library.section(section.title).all() for i, media in enumerate(sectionMedia): - backgroundImagePath = self.PLEX.library.section(section.title).get(media.title) - backgroundImgURL = '' - if isinstance(backgroundImagePath.art, str): - backgroundImgURL = config.baseurl+backgroundImagePath.art+"?X-Plex-Token="+config.token self.db.add_shows_to_db( 2, media.title, media.duration if media.duration else 1, '', - backgroundImgURL, + '', media.key, section.title ) - self.print_progress( - i + 1, - len(sectionMedia), - prefix = 'Progress '+section.title+": ", - suffix = 'Complete', - bar_length = 40 - ) #add all episodes of each tv show to episodes table episodes = self.PLEX.library.section(section.title).get(media.title).episodes() - for episode in episodes: + for j, episode in enumerate(episodes): duration = episode.duration if duration: self.db.add_episodes_to_db( @@ -171,9 +161,15 @@ class PseudoChannel(): episode.key, section.title ) - + self.print_progress( + j + 1, + len(episodes), + prefix = 'Progress TV Show '+str(i+1)+' of '+str(len(sectionMedia))+': ', + suffix = 'Complete ['+media.title+']', + bar_length = 40 + ) + #print('') elif correct_lib_name == "Commercials": - print("user_lib_name", section.title) sectionMedia = self.PLEX.library.section(section.title).all() media_length = len(sectionMedia) for i, media in enumerate(sectionMedia): @@ -182,13 +178,139 @@ class PseudoChannel(): i + 1, media_length, prefix = 'Progress '+section.title+":", - suffix = 'Complete', + suffix = 'Complete['+media.title[0:12]+']', bar_length = 40 ) - + #print('') + dothething = "yes" + if dothething == "yes": + playlists = self.PLEX.playlists() + for i, playlist in enumerate(playlists): + duration_average = playlist.duration / playlist.leafCount + self.db.add_shows_to_db( + 2, + playlist.title, + duration_average, + '', + '', + playlist.key, + playlist.type + ) + # add all entries of playlist to episodes table + episodes = self.PLEX.playlist(playlist.title).items() + for j, episode in enumerate(episodes): + duration = episode.duration + sectionTitle = "Playlists" + itemID = str(episode.playlistItemID) + itemData = self.PLEX.fetchItem(episode.key) + if itemData.type == "episode": + sNo = str(itemData.parentIndex) + eNo = str(itemData.index) + plTitle = episode.grandparentTitle +" - "+ episode.title + " (S" + sNo + "E" + eNo + ")" + else: + sNo = "0" + eNo = "0" + plTitle = episode.title + " ("+str(episode.year)+")" + if duration: + self.db.add_playlist_entries_to_db( + 5, + plTitle, + duration, + eNo, + sNo, + playlist.title, + episode.key, + sectionTitle + ) + else: + self.db.add_playlist_entries_to_db( + 5, + episode.title, + 0, + eNo, + sNo, + playlist.title, + episode.key, + sectionTitle + ) + self.print_progress( + j + 1, + len(episodes), + prefix = 'Progress Playlist '+str(i+1)+' of '+str(len(playlists))+': ', + suffix = 'Complete ['+playlist.title+']', + bar_length = 40 + ) + print('', end='\r') + sys.stdout.write("\033[K") + sys.stdout.write('NOTICE: Database Update Complete!') + print('') + def update_db_playlist(self): + dothething = "yes" + if dothething == "yes": + playlists = self.PLEX.playlists() + for i, playlist in enumerate(playlists): + duration_average = playlist.duration / playlist.leafCount + self.db.add_shows_to_db( + 2, + playlist.title, + duration_average, + '', + '', + playlist.key, + playlist.type + ) + # add all entries of playlist to episodes table + episodes = self.PLEX.playlist(playlist.title).items() + for j, episode in enumerate(episodes): + duration = episode.duration + sectionTitle = "Playlists" + itemID = str(episode.playlistItemID) + itemData = self.PLEX.fetchItem(episode.key) + if itemData.type == "episode": + sNo = str(itemData.parentIndex) + eNo = str(itemData.index) + plTitle = episode.grandparentTitle +" - "+ episode.title + " (S" + sNo + "E" + eNo + ")" + else: + sNo = "0" + eNo = "0" + plTitle = episode.title + " ("+str(episode.year)+")" + if duration: + self.db.add_playlist_entries_to_db( + 5, + plTitle, + duration, + eNo, + sNo, + playlist.title, + episode.key, + sectionTitle + ) + else: + self.db.add_playlist_entries_to_db( + 5, + episode.title, + 0, + eNo, + sNo, + playlist.title, + episode.key, + sectionTitle + ) + self.print_progress( + j + 1, + len(episodes), + prefix = 'Progress Playlist '+str(i+1)+' of '+str(len(playlists))+': ', + suffix = 'Complete ['+playlist.title+']', + bar_length = 40 + ) + print('', end='\r') + sys.stdout.write("\033[K") + sys.stdout.write('NOTICE: Playlist Database Update Complete!') + print('') + def update_db_movies(self): - print("#### Updating Local Database, MOVIES ONLY") + print("NOTICE: Updating Local Database, MOVIES ONLY") self.db.create_tables() libs_dict = config.plexLibraries sections = self.PLEX.library.sections() @@ -202,14 +324,17 @@ class PseudoChannel(): self.print_progress( i + 1, len(sectionMedia), - prefix = 'Progress '+section.title+": ", - suffix = 'Complete', + prefix = 'Progress '+section.title+": ", + suffix = 'Complete ['+media.title+']', bar_length = 40 ) - + print('', end='\r') + sys.stdout.write("\033[K") + print('NOTICE: Movies Database Update Complete!') + print('') def update_db_tv(self): - print("#### Updating Local Database, TV ONLY") + print("NOTICE: Updating Local Database, TV ONLY") self.db.create_tables() libs_dict = config.plexLibraries sections = self.PLEX.library.sections() @@ -232,18 +357,9 @@ class PseudoChannel(): media.key, section.title ) - self.print_progress( - i + 1, - len(sectionMedia), - prefix = 'Progress '+section.title+": ", - suffix = 'Complete', - bar_length = 40 - ) #add all episodes of each tv show to episodes table episodes = self.PLEX.library.section(section.title).get(media.title).episodes() - - - for episode in episodes: + for j, episode in enumerate(episodes): duration = episode.duration if duration: self.db.add_episodes_to_db( @@ -267,10 +383,20 @@ class PseudoChannel(): episode.key, section.title ) - + self.print_progress( + j + 1, + len(episodes), + prefix = 'Progress TV Show '+str(i+1)+' of '+str(len(sectionMedia))+': ', + suffix = 'Complete ['+media.title+']', + bar_length = 40 + ) + print('', end='\r') + sys.stdout.write("\033[K") + sys.stdout.write('NOTICE: TV Shows Database Update Complete!') + print('') def update_db_comm(self): - print("#### Updating Local Database, COMMERCIALS ONLY") + print("NOTICE: Updating Local Database, COMMERCIALS ONLY") self.db.create_tables() libs_dict = config.plexLibraries sections = self.PLEX.library.sections() @@ -278,7 +404,6 @@ class PseudoChannel(): for correct_lib_name, user_lib_name in libs_dict.items(): if section.title.lower() in [x.lower() for x in user_lib_name]: if correct_lib_name == "Commercials": - print("user_lib_name", section.title) sectionMedia = self.PLEX.library.section(section.title).all() media_length = len(sectionMedia) for i, media in enumerate(sectionMedia): @@ -287,10 +412,13 @@ class PseudoChannel(): i + 1, media_length, prefix = 'Progress '+section.title+":", - suffix = 'Complete', + suffix = 'Complete ['+media.title[0:12]+']', bar_length = 40 ) - + print('', end='\r') + sys.stdout.write("\033[K") + sys.stdout.write('NOTICE: Commercials Database Update Complete!') + print('') def update_schedule(self): """Changing dir to the schedules dir.""" @@ -328,14 +456,17 @@ class PseudoChannel(): natural_start_time = self.translate_time(time.text) natural_end_time = 0 section = key - if section == "TV Shows" and time.attrib['type'] == "random": + if section == "TV Shows" and time.attrib['title'] == "random": + mediaID_place=999 + elif time.attrib['type'] == "random": mediaID_place=9999 else: mediaID_place=0 day_of_week = child.tag + duration = time.attrib['duration'] if 'duration' in time.attrib else '0,43200000' strict_time = time.attrib['strict-time'] if 'strict-time' in time.attrib else 'false' time_shift = time.attrib['time-shift'] if 'time-shift' in time.attrib else '1' - overlap_max = time.attrib['overlap-max'] if 'overlap-max' in time.attrib else '' + overlap_max = time.attrib['overlap-max'] if 'overlap-max' in time.attrib else '0' seriesOffset = time.attrib['series-offset'] if 'series-offset' in time.attrib else '' xtra = time.attrib['xtra'] if 'xtra' in time.attrib else '' @@ -354,7 +485,7 @@ class PseudoChannel(): self.db.add_schedule_to_db( mediaID_place, # mediaID title, # title - 0, # duration + duration, # duration natural_start_time, # startTime natural_end_time, # endTime day_of_week, # dayOfWeek @@ -400,8 +531,8 @@ class PseudoChannel(): * Getting the offest by comparing both times from the unix epoch time and getting the difference. * ''' - timeA = datetime.datetime.strptime(time1, '%I:%M:%S %p') - timeB = datetime.datetime.strptime(time2, '%I:%M:%S %p') + timeA = datetime.datetime.strptime(time1, pseudo_channel.APP_TIME_FORMAT_STR) + timeB = datetime.datetime.strptime(time2, pseudo_channel.APP_TIME_FORMAT_STR) timeAEpoch = calendar.timegm(timeA.timetuple()) timeBEpoch = calendar.timegm(timeB.timetuple()) tdelta = abs(timeAEpoch) - abs(timeBEpoch) @@ -420,12 +551,11 @@ class PseudoChannel(): self.TIME_GAP = timeGap self.OVERLAP_GAP = timeGap self.OVERLAP_MAX = overlapMax - time1 = prevEndTime.strftime('%I:%M:%S %p') - timeB = datetime.datetime.strptime(intendedStartTime, '%I:%M:%S %p').strftime(self.APP_TIME_FORMAT_STR) - print("++++ Previous End Time: ", time1, "Intended start time: ", timeB) + time1 = prevEndTime.strftime(self.APP_TIME_FORMAT_STR) + timeB = datetime.datetime.strptime(intendedStartTime, self.APP_TIME_FORMAT_STR).strftime(self.APP_TIME_FORMAT_STR) + print("INFO: Previous End Time: ", time1, "Intended start time: ", timeB) timeDiff = self.time_diff(time1, timeB) - print("++++timeDiff "+ str(timeDiff)) - # print("++++startTimeUNIX: "+ str(intendedStartTime)) + print("INFO: Time Difference = "+ str(timeDiff)) newTimeObj = timeB newStartTime = timeB @@ -439,19 +569,19 @@ class PseudoChannel(): * If this doesn't apply, simply move on to the regular "checks" * ''' - time1A=prevEndTime.strftime('%H:%M') - time1A_comp = datetime.datetime.strptime(time1A, '%H:%M') # there was an issue with the date changing to 1/2, so we had to do this for correct comparison - timeset=[datetime.time(h,m).strftime("%H:%M") for h,m in itertools.product(range(0,24),range(0,60,int(self.OVERLAP_GAP)))] + time1A=prevEndTime.strftime('%H:%M:%S') + time1A_comp = datetime.datetime.strptime(time1A, '%H:%M:%S') # there was an issue with the date changing to 1/2, so we had to do this for correct comparison + timeset=[datetime.time(h,m).strftime("%H:%M:%S") for h,m in itertools.product(range(0,24),range(0,60,int(self.OVERLAP_GAP)))] timeset_last = timeset[-1] - theTimeSetInterval_last = datetime.datetime.strptime(timeset_last, '%H:%M') + theTimeSetInterval_last = datetime.datetime.strptime(timeset_last, '%H:%M:%S') prevEndTime = time1A_comp #maybe this will change things? - print("++++ Previous End Time: ", time1A_comp) - print("++++ Last Element of the Day: ", theTimeSetInterval_last) + print("INFO: Previous End Time: ", time1A_comp) + print("INFO: Last Element of the Day: ", theTimeSetInterval_last) if time1A_comp > theTimeSetInterval_last: - print("++++ We are starting a show with the new day. Using first element of the next day") - theTimeSetInterval = datetime.datetime.strptime(timeset[0], '%H:%M') #This must be the element we are looking for + print("NOTICE: We are starting a show with the new day. Using first element of the next day") + theTimeSetInterval = datetime.datetime.strptime(timeset[0], '%H:%M:%S') #This must be the element we are looking for newStartTime = theTimeSetInterval ''' * @@ -464,17 +594,13 @@ class PseudoChannel(): * If there is an overlap, then the overlapGap var in config will determine the next increment. If it is set to "15", then the show will will bump up to the next 15 minute interval past the hour. * ''' - #hourToUse = self.DAILY_UPDATE_TIME.split(':')[0] - #minuteToUse = self.DAILY_UPDATE_TIME.split(':')[1] - #now = datetime.datetime(1900, 1, 1, int(hourToUse), int(minuteToUse)) - #timeset = [(now + datetime.timedelta(minutes=int(self.OVERLAP_GAP)*n)).strftime('%H:%M') for n in range((60*24)/int(self.OVERLAP_GAP))] - #timeset=[datetime.time(h,m).strftime("%H:%M") for h,m in itertools.product(xrange(0,24),xrange(0,60,int(self.OVERLAP_GAP)))] - #print timeset + print("NOTICE: OVERLAP DETECTED - elif timeDiff < 0") timeSetToUse = None for time in timeset: - theTimeSetInterval = datetime.datetime.strptime(time, '%H:%M') + theTimeSetInterval = datetime.datetime.strptime(time, '%H:%M:%S') + print("INFO: Time Set Interval: "+str(theTimeSetInterval)) if theTimeSetInterval >= prevEndTime: - print("++++ There is overlap. Setting new time-interval:", theTimeSetInterval) + print("NOTICE: There is overlap. Setting new time-interval:", theTimeSetInterval) newStartTime = theTimeSetInterval break elif (timeDiff >= 0) and (self.TIME_GAP != -1): @@ -484,27 +610,23 @@ class PseudoChannel(): * If it is set to "15", then the show will will bump up to the next 15 minute interval past the hour. * ''' - #hourToUse = self.DAILY_UPDATE_TIME.split(':')[0] - #minuteToUse = self.DAILY_UPDATE_TIME.split(':')[1] - #now = datetime.datetime(1900, 1, 1, int(hourToUse), int(minuteToUse)) - #timeset = [(now + datetime.timedelta(minutes=int(self.OVERLAP_GAP)*n)).strftime('%H:%M') for n in range((60*24)/int(self.OVERLAP_GAP))] - #timeset=[datetime.time(h,m).strftime("%H:%M") for h,m in itertools.product(xrange(0,24),xrange(0,60,int(self.TIME_GAP)))] - #print timeset + print("NOTICE: OVERLAP DETECTED - (timeDiff >= 0) and (self.TIME_GAP != -1)") for time in timeset: - theTimeSetInterval = datetime.datetime.strptime(time, '%H:%M') - tempTimeTwoStr = datetime.datetime.strptime(time1, self.APP_TIME_FORMAT_STR).strftime('%H:%M') - formatted_time_two = datetime.datetime.strptime(tempTimeTwoStr, '%H:%M') + theTimeSetInterval = datetime.datetime.strptime(time, '%H:%M:%S') + tempTimeTwoStr = datetime.datetime.strptime(time1, self.APP_TIME_FORMAT_STR).strftime('%H:%M:%S') + formatted_time_two = datetime.datetime.strptime(tempTimeTwoStr, '%H:%M:%S') if theTimeSetInterval >= formatted_time_two: - print("++++ Setting new time-interval:", theTimeSetInterval) + print("INFO: Setting new time-interval:", theTimeSetInterval) newStartTime = theTimeSetInterval break else: - print("Not sure what to do here") - return newStartTime.strftime('%I:%M:%S %p') + print("NOTICE: time1A_comp < theTimeSetInterval_last") + print("INFO: New Start Time = "+newStartTime.strftime(self.APP_TIME_FORMAT_STR)) + return newStartTime.strftime(self.APP_TIME_FORMAT_STR) def get_end_time_from_duration(self, startTime, duration): - time = datetime.datetime.strptime(startTime, '%I:%M:%S %p') + time = datetime.datetime.strptime(startTime, self.APP_TIME_FORMAT_STR) show_time_plus_duration = time + datetime.timedelta(milliseconds=duration) return show_time_plus_duration @@ -524,7 +646,7 @@ class PseudoChannel(): self.COMMERCIAL_PADDING_IN_SECONDS, self.USE_DIRTY_GAP_FIX ) - schedule = self.db.get_schedule() + schedule = self.db.get_schedule_alternate(config.dailyUpdateTime) weekday_dict = { "0" : ["mondays", "weekdays", "everyday"], "1" : ["tuesdays", "weekdays", "everyday"], @@ -536,22 +658,214 @@ class PseudoChannel(): } weekno = datetime.datetime.today().weekday() schedule_advance_watcher = 0 + xtraSeason = None + xtraEpisode = None for entry in schedule: schedule_advance_watcher += 1 section = entry[9] - for key, val in weekday_dict.items(): + for key, val in weekday_dict.items(): if str(entry[7]) in str(val) and int(weekno) == int(key): if section == "TV Shows": + minmax = entry[4].split(",") + min = int(minmax[0]) + min = min * 60000 + max = int(minmax[1]) + max = max * 60000 if str(entry[3]).lower() == "random": - next_episode = self.db.get_random_episode() + sections = self.PLEX.library.sections() + shows_list = [] + libs_dict = config.plexLibraries + for theSection in sections: + for correct_lib_name, user_lib_name in libs_dict.items(): + if theSection.title.lower() in [x.lower() for x in user_lib_name]: + if correct_lib_name == "TV Shows" and entry[13] != "": + print("NOTICE: XTRA ARGS FOUND") + shows = self.PLEX.library.section(theSection.title) + xtra = '[]' + d = {} + #thestr = entry[13] + if ";" in xtra: + xtra = entry[13].split(';') + else: + if xtra != None: + xtra = str(entry[13]) + ';' + xtra = xtra.split(';') + try: + for thestr in xtra: + print("ARGUMENT = "+thestr) + strsplit = thestr.split(':') + if strsplit[0] == "decade": + decade = strsplit[1] + lastdigit = 0 + thestr = "year:" + while lastdigit <= 9: + thestr = thestr+decade[0]+decade[1]+decade[2]+str(lastdigit) + lastdigit = lastdigit + 1 + if lastdigit < 10: + thestr = thestr+"," + print("ARGUMENT = "+thestr) + #d.update(strsplit[0],strsplit[1]) + elif strsplit[0] == "season": + xtraSeason = strsplit[1] + thestr = "" + elif strsplit[0] == "episode": + xtraEpisode = strsplit[1] + thestr = "" + if thestr != "": + regex = re.compile(r"\b(\w+)\s*:\s*([^:]*)(?=\s+\w+\s*:|$)") + d.update(regex.findall(thestr)) + #d = dict(regex.findall(thestr)) + print(d) + #turn values into a list + for key, val in d.items(): + d[key] = val.split(',') + for show in shows.search(None, **d): + shows_list.append(show) + except: + pass + if (len(shows_list) > 0): + #print shows_list + print("ACTION: Using xtra args to choose a random show") + the_show = self.db.get_shows(random.choice(shows_list).title) + else: + print("ACTION: Getting random show") + the_show = self.db.get_random_show_duration(int(min), int(max)) + try: + print("INFO: "+str(the_show[3])) + except: + print("NOTICE: FAILED TO GET RANDOM SHOW") + if (the_show is None): + print("ACTION: Getting random episode of random show") + next_episode = self.db.get_random_episode_duration(int(min), int(max)) + attempt = 1 + episode_duration = next_episode[4] + while episode_duration < min or episode_duration > max: + print("NOTICE: EPISODE LENGTH OUTSIDE PARAMETERS") + print("ACTION: Getting random episode of random show") + next_episode = self.db.get_random_episode_duration(int(min), int(max)) + episode_duration = int(next_episode[4]) + attempt = attempt + 1 + if attempt > 1000: + episode_duration = max + else: + episode_duration = int(next_episode[4]) + print("INFO: Random Selection: "+next_episode[7]+" - S"+str(next_episode[6])+"E"+str(next_episode[5])+" - "+next_episode[3]) + else: + i = 0 + while i < 1000: + i += 1 + try: + if xtraSeason is None and xtraEpisode is None: + print("ACTION: Choosing random episode of "+the_show[3].upper()) + next_episode = self.db.get_random_episode_of_show(the_show[3]) + elif xtraEpisode is None: + print("ACTION: Choosing random episode of "+the_show[3].upper()+" Season "+xtraSeason) + next_episode = self.db.get_specific_episode(the_show[3], xtraSeason) + elif xtraSeason is None: + print("ACTION: Choosing random episode of "+the_show[3].upper()+" Episode "+xtraEpisode) + next_episode = self.db.get_specific_episode(the_show[3], None, xtraEpisode) + else: + print("ACTION: Choosing random episode of "+the_show[3].upper()+" Season "+xtraSeason+" Episode "+xtraEpisode) + next_episode = self.db.get_specific_episode(the_show[3], xtraSeason, xtraEpisode) + print("INFO: Episode Selected: S"+str(next_episode[6])+"E"+str(next_episode[5])+" "+next_episode[3].upper()) + break + except TypeError as e: + print (e) + if (len(shows_list) > 0): + #print shows_list + print("ACTION: Using xtra args to choose a random show") + the_show = self.db.get_shows(random.choice(shows_list).title) + else: + print("ACTION: Getting random show") + the_show = self.db.get_random_show_duration(int(min), int(max)) + print("INFO: "+str(the_show[3])) + if (the_show is None): + print("ACTION: Getting random episode of random show") + next_episode = self.db.get_random_episode_duration(int(min), int(max)) + continue + episode_duration = int(next_episode[4]) + attempt = 1 + while episode_duration < min or episode_duration > max or next_episode == None: + i = 0 + while i < 1000: + i += 1 + try: + print("NOTICE: DURATION OUTSIDE PARAMETERS") + if (len(shows_list) > 0): + print("ACTION: Using xtra args to choose a random show") + the_show = self.db.get_shows(random.choice(shows_list).title) + else: + print("ACTION: Getting random show") + the_show = self.db.get_random_show_duration(int(min), int(max)) + print("INFO: "+str(the_show)) + if xtraSeason is None and xtraEpisode is None: + print("ACTION: Choosing random episode of "+the_show[3].upper()) + next_episode = self.db.get_random_episode_of_show(the_show[3]) + elif xtraEpisode is None: + print("ACTION: Choosing random episode of "+the_show[3].upper()+" Season "+xtraSeason) + next_episode = self.db.get_specific_episode(the_show[3], xtraSeason) + elif xtraSeason is None: + print("ACTION: Choosing random episode of "+the_show[3].upper()+" Episode "+xtraEpisode) + next_episode = self.db.get_specific_episode(the_show[3], None, xtraEpisode) + else: + print("ACTION: Choosing random episode of "+the_show[3].upper()+" Season "+xtraSeason+" Episode "+xtraEpisode) + next_episode = self.db.get_specific_episode(the_show[3], xtraSeason, xtraEpisode) + print("INFO: Episode Selected: S"+str(next_episode[6])+"E"+str(next_episode[5])+" "+next_episode[3].upper()) + break + except TypeError as e: + print(e) + if (len(shows_list) > 0): + #print shows_list + print("ACTION: Using xtra args to choose a random show") + the_show = self.db.get_shows(random.choice(shows_list).title) + else: + print("ACTION: Getting random show") + the_show = self.db.get_random_show_duration(int(min), int(max)) + print("INFO: "+the_show[3]) + if (the_show is None): + next_episode = self.db.get_random_episode_duration(int(min), int(max)) + continue + attempt = attempt + 1 + episode_duration = int(next_episode[4]) + if attempt > 1000: + episode_duration = max + else: + episode_duration = int(next_episode[4]) + show_title = next_episode[7] + xtraSeason = None + xtraEpisode = None + print("----------------------------------") + elif entry[2] == 9999: - next_episode = self.db.get_random_episode_alternate(entry[3]) + print("ACTION: Getting random episode of "+entry[3]) + try: + next_episode = self.db.get_random_episode_of_show_alt(entry[3]) + except TypeError as e: + print(e) + next_episode = self.db.get_random_episode_of_show_alt(entry[3]) + print("INFO: Episode Selected: S"+str(next_episode[6])+"E"+str(next_episode[5])+" "+next_episode[3].upper()) + show_title = next_episode[7] + episode_duration = next_episode[4] + attempt = 1 + while int(episode_duration) < min or episode_duration > max: + print("ACTION: Getting random episode of "+entry[3]) + next_episode = self.db.get_random_episode_of_show(entry[3]) + print("INFO: Episode Selected: S"+str(next_episode[6])+"E"+str(next_episode[5])+" "+next_episode[3].upper()) + attempt = attempt + 1 + if attempt > 500: + episode_duration = max + else: + episode_duration = next_episode[4] + show_title = next_episode[7] else: - next_episode = self.db.get_next_episode(entry[3]) + next_episode = self.db.get_next_episode(entry[3]) #get next episode + try: + print("INFO: Scheduled: "+next_episode[7]+" - (S"+str(next_episode[6])+"E"+str(next_episode[5])+") "+next_episode[3]) + except: + pass + show_title = entry[3] if next_episode != None: - customSectionName = next_episode[9] - episode = Episode( section, # section_type next_episode[3], # title @@ -562,84 +876,105 @@ class PseudoChannel(): entry[10], # is_strict_time entry[11], # time_shift entry[12], # overlap_max - next_episode[8] if len(next_episode) >= 9 else '', # plex id + #next_episode[8] if len(next_episode) >= 9 else '', # plex id + next_episode[8], #plex id customSectionName, # custom lib name - entry[3], # show_series_title + show_title, # show_series_title next_episode[5], # episode_number next_episode[6], # season_number ) self.MEDIA.append(episode) else: - print("Cannot find TV Show Episode, {} in the local db".format(entry[3])) + print("ERROR: Cannot find TV Show Episode, {} in the local db".format(entry[3])) elif section == "Movies": if str(entry[3]).lower() == "random": + minmax = entry[4].split(",") + min = int(minmax[0]) + min = min * 60000 + max = int(minmax[1]) + max = max * 60000 + movies_list = [] if(entry[13] != ''): # xtra params - """ Using specified Movies library names """ - movies_list = [] libs_dict = config.plexLibraries sections = self.PLEX.library.sections() for theSection in sections: for correct_lib_name, user_lib_name in libs_dict.items(): if theSection.title.lower() in [x.lower() for x in user_lib_name]: - print("correct_lib_name", correct_lib_name) - if correct_lib_name == "Movies": - - print("entry[13]", entry[13]) + if correct_lib_name == "Movies" and entry[13] != "": + print("xtra args: ", entry[13]) movies = self.PLEX.library.section(theSection.title) - - try: - thestr = entry[13] - regex = re.compile(r"\b(\w+)\s*:\s*([^:]*)(?=\s+\w+\s*:|$)") - d = dict(regex.findall(thestr)) - # turn values into list - for key, val in d.items(): - d[key] = val.split(',') - for movie in movies.search(None, **d): - movies_list.append(movie) - - """the_movie = self.db.get_movie(self.movieMagic.get_random_movie_xtra( - self.db.get_movies(),# Movies DB - movies_list # XTRA List - ) - )""" - - except: - - pass - - if (len(movies_list) > 0): - + xtra = [] + d = {} + if ";" in xtra: + xtra = entry[13].split(';') + else: + if xtra != None: + xtra = str(entry[13]) + ';' + xtra = xtra.split(';') + print(xtra) + try: + for thestr in xtra: + print ("INFO: "+thestr) + regex = re.compile(r"\b(\w+)\s*:\s*([^:]*)(?=\s+\w+\s*:|$)") + d.update(regex.findall(thestr)) + # turn values into list + for key, val in d.items(): + d[key] = val.split(',') + for movie in movies.search(None, **d): + movies_list.append(movie) + except: + pass + if (len(movies_list) > 0): + the_movie = self.db.get_movie(random.choice(movies_list).title) + movie_duration = the_movie[4] + attempt = 1 + while int(movie_duration) < min or movie_duration > max: the_movie = self.db.get_movie(random.choice(movies_list).title) - - """Updating movies table in the db with lastPlayedDate entry""" - self.db.update_movies_table_with_last_played_date(the_movie[3]) - - else: - - print("movies_list", movies_list) - - print("For some reason, I've failed getting movie with xtra args.") - the_movie = self.db.get_random_movie() - - """Updating movies table in the db with lastPlayedDate entry""" - self.db.update_movies_table_with_last_played_date(the_movie[3]) - - else: - - """the_movie = self.db.get_movie(self.movieMagic.get_random_movie( - self.db.get_movies(),# Movies DB - ) - )""" - - the_movie = self.db.get_random_movie() - + attempt = attempt + 1 + if attempt > 500: + movie_duration = max + else: + movie_duration = the_movie[4] """Updating movies table in the db with lastPlayedDate entry""" self.db.update_movies_table_with_last_played_date(the_movie[3]) - + else: + print("ERROR - xtra args not found, getting random movie") + the_movie = self.db.get_random_movie_duration(int(min), int(max)) + movie_duration = the_movie[4] + attempt = 1 + while int(movie_duration) < min or movie_duration > max: + the_movie = self.db.get_random_movie_duration(int(min), int(max)) + attempt = attempt + 1 + if attempt > 500: + movie_duration = max + else: + movie_duration = the_movie[4] + """Updating movies table in the db with lastPlayedDate entry""" + self.db.update_movies_table_with_last_played_date(the_movie[3]) + minmax = str(entry[4]).split(",") + min = int(minmax[0]) + min = min * 60000 + max = int(minmax[1]) + max = max * 60000 + the_movie = self.db.get_random_movie_duration(int(min), int(max)) + movie_duration = the_movie[4] + attempt = 1 + while int(movie_duration) < min or movie_duration > max: + the_movie = self.db.get_random_movie_duration(int(min), int(max)) + attempt = attempt + 1 + if attempt > 500: + movie_duration = max + else: + movie_duration = the_movie[4] + movies_list = [] + libs_dict = config.plexLibraries + sections = self.PLEX.library.sections() + """Updating movies table in the db with lastPlayedDate entry""" + self.db.update_movies_table_with_last_played_date(the_movie[3]) else: the_movie = self.db.get_movie(entry[3]) if the_movie != None: @@ -703,16 +1038,16 @@ class PseudoChannel(): """ if schedule_advance_watcher >= len(schedule): - print("+++++ Finished processing time entries, recreating daily_schedule") + print("INFO: Finished processing time entries, recreating daily_schedule") previous_episode = None for entry in self.MEDIA: if previous_episode != None: natural_start_time = datetime.datetime.strptime(entry.natural_start_time, self.APP_TIME_FORMAT_STR) natural_end_time = entry.natural_end_time if entry.is_strict_time.lower() == "true": - print("++++ Strict-time: {}".format(str(entry.title))) + print("INFO: Strict-time: {}".format(str(entry.title))) entry.end_time = self.get_end_time_from_duration( - self.translate_time(entry.start_time), + self.translate_time(entry.start_time), entry.duration ) """Get List of Commercials to inject""" @@ -720,44 +1055,78 @@ class PseudoChannel(): list_of_commercials = self.commercials.get_commercials_to_place_between_media( previous_episode, entry, - entry.is_strict_time.lower() + entry.is_strict_time.lower(), + config.dailyUpdateTime ) for commercial in list_of_commercials: self.db.add_media_to_daily_schedule(commercial) self.db.add_media_to_daily_schedule(entry) previous_episode = entry + elif entry.is_strict_time.lower() == "secondary": #This mode starts a show "already in progress" if the previous episode or movie runs past the start time of this one + print("INFO Pre-empt Allowed: {}".format(str(entry.title))) + try: + prev_end_time = datetime.datetime.strptime(str(previous_episode.end_time), '%Y-%m-%d %H:%M:%S.%f') + except ValueError: + prev_end_time = datetime.datetime.strptime(str(previous_episode.end_time), '%Y-%m-%d %H:%M:%S') + prev_end_time = prev_end_time.strftime(self.APP_TIME_FORMAT_STR) + start_time_difference=self.time_diff(str(entry.natural_start_time),str(prev_end_time)) + start_time_difference=start_time_difference*60 + print("Entry Duration = {}".format(str(entry.duration))) + print("Start Time Difference = {}".format(str(start_time_difference))) + if start_time_difference > 0: + running_duration = entry.duration - abs(start_time_difference) + print("Running Duration = {}".format(str(running_duration))) + entry.start_time = datetime.datetime.strptime(entry.natural_start_time, self.APP_TIME_FORMAT_STR) + datetime.timedelta(seconds=abs(start_time_difference)) + entry.start_time = datetime.datetime.strftime(entry.start_time, self.APP_TIME_FORMAT_STR) + print("New Start Time = {}".format(str(entry.start_time))) + entry.end_time = self.get_end_time_from_duration( + self.translate_time(natural_start_time.strftime(self.APP_TIME_FORMAT_STR)), + entry.duration + ) + print("End Time = {}".format(str(entry.end_time))) + overlap_max_seconds=int(entry.overlap_max) * 60 + print(("Overlap Max is "+str(overlap_max_seconds))) + max_end_time=datetime.datetime.strptime(entry.natural_start_time, self.APP_TIME_FORMAT_STR) + datetime.timedelta(seconds=overlap_max_seconds) + if datetime.datetime.strptime(entry.start_time, self.APP_TIME_FORMAT_STR) > max_end_time or datetime.datetime.strptime(entry.start_time, self.APP_TIME_FORMAT_STR) > entry.end_time: + print("NOTICE: START TIME PAST MAXIMUM ALLOWED TIME, SKIPPING ENTRY") + pass + else: + """Get List of Commercials to Inject""" + if self.USING_COMMERCIAL_INJECTION: + list_of_commercials = self.commercials.get_commercials_to_place_between_media( + previous_episode, + entry, + entry.is_strict_time.lower(), + config.dailyUpdateTime + ) + for commercial in list_of_commercials: + self.db.add_media_to_daily_schedule(commercial) + self.db.add_media_to_daily_schedule(entry) + previous_episode = entry else: try: - print("++++ NOT strict-time: {}".format(str(entry.title).encode(sys.stdout.encoding, errors='replace'))) + print("INFO: Variable Time: {}".format(str(entry.title).encode(sys.stdout.encoding, errors='replace'))) except: pass - - if pseudo_channel.DEBUG: + try: new_starttime = self.calculate_start_time( previous_episode.end_time, entry.natural_start_time, previous_episode.time_shift, "" ) - else: - try: - new_starttime = self.calculate_start_time( - previous_episode.end_time, - entry.natural_start_time, - previous_episode.time_shift, - "" - ) - except: - print("Error in calculate_start_time") - print("++++ New start time:", new_starttime) - entry.start_time = datetime.datetime.strptime(new_starttime, self.APP_TIME_FORMAT_STR).strftime('%I:%M:%S %p') + except: + print("ERROR: Error in calculate_start_time") + print("INFO: New start time:", new_starttime) + entry.start_time = datetime.datetime.strptime(new_starttime, self.APP_TIME_FORMAT_STR).strftime(self.APP_TIME_FORMAT_STR) entry.end_time = self.get_end_time_from_duration(entry.start_time, entry.duration) """Get List of Commercials to inject""" if self.USING_COMMERCIAL_INJECTION: list_of_commercials = self.commercials.get_commercials_to_place_between_media( previous_episode, entry, - entry.is_strict_time.lower() + entry.is_strict_time.lower(), + config.dailyUpdateTime ) for commercial in list_of_commercials: self.db.add_media_to_daily_schedule(commercial) @@ -766,7 +1135,17 @@ class PseudoChannel(): else: self.db.add_media_to_daily_schedule(entry) previous_episode = entry - #self.make_xml_schedule() + + if self.USING_COMMERCIAL_INJECTION: + list_of_commercials = self.commercials.get_commercials_to_place_between_media( + previous_episode, + "reset", + "true", + config.dailyUpdateTime + ) + for commercial in list_of_commercials: + self.db.add_media_to_daily_schedule(commercial) + print("NOTICE: END OF DAY - RESET TIME REACHED") def run_commercial_injection(self): @@ -778,16 +1157,57 @@ class PseudoChannel(): def show_clients(self): - print("##### Connected Clients:") + print("Connected Clients:") for i, client in enumerate(self.PLEX.clients()): - print("+++++", str(i + 1)+".", "Client:", client.title) + print("INFO: ", str(i + 1)+".", "Client:", client.title) def show_schedule(self): - print("##### Daily Pseudo Schedule:") + print("Daily Pseudo Schedule:") daily_schedule = self.db.get_daily_schedule() for i , entry in enumerate(daily_schedule): - print(str("+++++ {} {} {} {} {} {}".format(str(i + 1)+".", entry[8], entry[11], entry[6], " - ", entry[3])).encode(sys.stdout.encoding, errors='replace')) + print(str("INFO {} {} {} {} {} {}".format(str(i + 1)+".", entry[8], entry[11], entry[6], " - ", entry[3])).encode(sys.stdout.encoding, errors='replace')) + + def last_episode(self): + print("----- Change the 'Last Episode' set for a show. -----") + print("Enter the name of the show.") + showName = input("Show Name: ") + showData = self.db.get_shows(showName) + #print("SHOW SELECTED: "+showData[3]) + if(showData is not None): + print("Enter the season and episode numbers for the 'last episode' (episode previous to the episode you wish to be scheduled on next -g run") + sNo = input("Season Number: ") + eNo = input("Episode Number: ") + episodeData = self.db.get_episode_from_season_episode(showName,sNo,eNo) + if(episodeData is not None): + print("Setting "+episodeData[7]+" - "+episodeData[3]+" S"+str(episodeData[6])+"E"+str(episodeData[5])+" as the Last Episode in the Shows Database") + self.db.update_shows_table_with_last_episode(episodeData[7], episodeData[8]) + else: + print("ERROR: EPISODE NOT FOUND IN PSEUDO CHANNEL DATABASE") + sys.exit(1) + else: + print("ERROR: SHOW NOT FOUND IN PSEUDO CHANNEL DATABASE") + sys.exit(1) + + + def episode_randomizer(self): + all_shows = list(self.db.get_shows_titles()) + shows_list = [] + for one_show in all_shows: + shows_list.append(str(one_show[0])) + for a_show in shows_list: + a_show = str(a_show) + try: + random_episode = self.db.get_random_episode_of_show(a_show) + print(a_show + " - " + random_episode[3]) + self.db.update_shows_table_with_last_episode(a_show, random_episode[8]) + except TypeError as e: + print("ERROR: "+a_show) + print(e) + random_episode = self.db.get_random_episode_of_show_alt(a_show) + print(a_show + " - " + random_episode[3]) + self.db.update_shows_table_with_last_episode_alt(a_show, random_episode[8]) + continue def write_json_to_file(self, data, fileName): @@ -803,9 +1223,9 @@ class PseudoChannel(): shows_table = self.db.get_shows_table() json_string = json.dumps(shows_table) - print("+++++ Exporting queue ") + print("NOTICE: Exporting queue ") self.write_json_to_file(json_string, "pseudo-queue.json") - print("+++++ Done.") + print("NOTICE: Done.") self.export_daily_schedule() def import_queue(self): @@ -825,16 +1245,16 @@ class PseudoChannel(): row[6], row[7], ) - print("+++++ Done. Imported queue.") + print("NOTICE: Queue Import Complete") self.import_daily_schedule() def export_daily_schedule(self): daily_schedule_table = self.db.get_daily_schedule() json_string = json.dumps(daily_schedule_table) - print("+++++ Exporting Daily Schedule ") + print("NOTICE: Exporting Daily Schedule ") self.write_json_to_file(json_string, "pseudo-daily_schedule.json") - print("+++++ Done.") + print("NOTICE: Done.") def import_daily_schedule(self): @@ -842,7 +1262,7 @@ class PseudoChannel(): self.db.remove_all_daily_scheduled_items() with open('pseudo-daily_schedule.json') as data_file: data = json.load(data_file) - #print(data) + #pprint(data) for row in data: """print row""" self.db.import_daily_schedule_table_by_row( @@ -859,7 +1279,7 @@ class PseudoChannel(): row[12], row[13], ) - print("+++++ Done. Imported Daily Schedule.") + print("NOTICE: Daily Schedule Import Complete") def get_daily_schedule_cache_as_json(self): @@ -868,15 +1288,16 @@ class PseudoChannel(): with open('../.pseudo-cache/daily-schedule.json') as data_file: data = json.load(data_file) #pprint(data) - except IOError: - print("----- Having issues opening the pseudo-cache file.") + except IOError as e: + print("ERROR: Having issues opening the pseudo-cache file.") + print(e) return data def save_daily_schedule_as_json(self): daily_schedule_table = self.db.get_daily_schedule() json_string = json.dumps(daily_schedule_table) - print("+++++ Saving Daily Schedule Cache ") + print("NOTICE: Saving Daily Schedule Cache ") self.save_file(json_string, 'daily-schedule.json', '../.pseudo-cache/') def save_file(self, data, filename, path="./"): @@ -904,14 +1325,14 @@ class PseudoChannel(): def signal_term_handler(self, signal, frame): - logging.info('+++++ got SIGTERM') + logging.info('NOTICE: got SIGTERM') self.controller.stop_media() self.exit_app() sys.exit(0) def exit_app(self): - logging.info(' - Exiting Pseudo TV & cleaning up.') + logging.info('NOTICE: - Exiting Pseudo TV & cleaning up.') for i in self.MEDIA: del i self.MEDIA = None @@ -947,6 +1368,9 @@ if __name__ == '__main__': parser.add_argument('-utv', '--update_tv', action='store_true', help='Update the local database with Plex TV libraries ONLY.') + parser.add_argument('-up', '--update_playlist', + action='store_true', + help='Update the local database with Plex PLAYLIST libraries ONLY.') parser.add_argument('-uc', '--update_commercials', action='store_true', help='Update the local database with Plex COMMERCIAL libraries ONLY.') @@ -959,6 +1383,12 @@ if __name__ == '__main__': parser.add_argument('-r', '--run', action='store_true', help='Run this program.') + parser.add_argument('-ep', '--episode_randomizer', + action='store_true', + help='Randomize all shows episode progress.') + parser.add_argument('-le', '--last_episode', + action='store_true', + help='Set last episode for a show. The next time -g is run, it will start with the episode after the one set.') ''' * * Show connected clients: "python PseudoChannel.py -c" @@ -1021,12 +1451,18 @@ if __name__ == '__main__': pseudo_channel.update_db() if args.update_movies: pseudo_channel.update_db_movies() + if args.update_playlist: + pseudo_channel.update_db_playlist() if args.update_tv: pseudo_channel.update_db_tv() if args.update_commercials: pseudo_channel.update_db_comm() if args.xml: pseudo_channel.update_schedule() + if args.episode_randomizer: + pseudo_channel.episode_randomizer() + if args.last_episode: + pseudo_channel.last_episode() if args.show_clients: pseudo_channel.show_clients() if args.show_schedule: @@ -1046,13 +1482,13 @@ if __name__ == '__main__': try: pseudo_channel.generate_daily_schedule() except: - print("----- Recieved error when running generate_daily_schedule()") + print("ERROR: Recieved error when running generate_daily_schedule()") if args.make_html: pseudo_channel.make_xml_schedule() if args.run: print(banner) - print("+++++ To run this in the background:") - print("+++++", "screen -d -m bash -c 'python PseudoChannel.py -r; exec sh'") + print("INFO: To run this in the background:") + print("screen -d -m bash -c 'python PseudoChannel.py -r; exec sh'") """Every minute on the minute check the DB startTimes of all media to determine whether or not to play. Also, check the now_time to see if it's midnight (or 23.59), if so then generate a new daily_schedule @@ -1061,95 +1497,112 @@ if __name__ == '__main__': """Every rotate log""" dayToRotateLog = pseudo_channel.ROTATE_LOG.lower() schedule.every().friday.at("00:00").do(pseudo_channel.rotate_log) - logging.info("+++++ Running PseudoChannel.py -r") + logging.info("NOTICE: Running PseudoChannel.py -r") def trigger_what_should_be_playing_now(): def nearest(items, pivot): return min(items, key=lambda x: abs(x - pivot)) - daily_schedule = pseudo_channel.db.get_daily_schedule() - dates_list = [datetime.datetime.strptime(''.join(str(date[8])), "%I:%M:%S %p") for date in daily_schedule] + #dates_list = [datetime.datetime.strptime(''.join(str(date[8])), pseudo_channel.APP_TIME_FORMAT_STR) for date in daily_schedule] now = datetime.datetime.now() now = now.replace(year=1900, month=1, day=1) - closest_media = nearest(dates_list, now) - print(closest_media) + #closest_media = nearest(dates_list, now) + #print closest_media prevItem = None - - for item in daily_schedule: - item_time = datetime.datetime.strptime(''.join(str(item[8])), "%I:%M:%S %p") - - if item_time == closest_media: - #print "Line 1088, Here", item - elapsed_time = closest_media - now - print(elapsed_time.total_seconds()) - try: - endTime = datetime.datetime.strptime(item[9], '%Y-%m-%d %H:%M:%S.%f') - except ValueError: - endTime = datetime.datetime.strptime(item[9], '%Y-%m-%d %H:%M:%S') - # we need to play the content and add an offest - if elapsed_time.total_seconds() < 0 and \ - endTime > now: - print(str("+++++ Queueing up {} to play right away.".format(item[3])).encode('UTF-8')) - offset = int(abs(elapsed_time.total_seconds() * 1000)) - pseudo_channel.controller.play(item, daily_schedule, offset) - break - elif elapsed_time.total_seconds() >= 0: - for itemTwo in daily_schedule: - item_timeTwo = datetime.datetime.strptime(''.join(str(itemTwo[8])), "%I:%M:%S %p") - try: - endTime = datetime.datetime.strptime(itemTwo[9], '%Y-%m-%d %H:%M:%S.%f') - except ValueError: - endTime = datetime.datetime.strptime(itemTwo[9], '%Y-%m-%d %H:%M:%S') - if item_timeTwo == closest_media and prevItem != None and \ - endTime > now: - prevItem_time = datetime.datetime.strptime(''.join(str(prevItem[8])), "%I:%M:%S %p") - elapsed_timeTwo = prevItem_time - now - offsetTwo = int(abs(elapsed_timeTwo.total_seconds() * 1000)) - if prevItem_time.hour > now.hour: - print("we have a day skip") - now = now.replace(hour=23,minute=59,second=59) - elapsed_timeTwo = prevItem_time-now - mnight = now.replace(hour=0,minute=0,second=0) - now = datetime.datetime.now() - now = now.replace(year=1900, month=1, day=1) - elapsed_timeTwo = elapsed_timeTwo + (mnight-now) - print(elapsed_timeTwo.total_seconds()) - offsetTwo = int(abs(elapsed_timeTwo.total_seconds() * 1000)) - if pseudo_channel.DEBUG: - print("+++++ Closest media was the next media " \ - "but we were in the middle of something so triggering that instead.") - print(str("+++++ Queueing up '{}' to play right away.".format(prevItem[3])).encode('UTF-8')) - pseudo_channel.controller.play(prevItem, daily_schedule, offsetTwo) - break - prevItem = itemTwo + db = PseudoChannelDatabase("pseudo-channel.db") + item = db.get_now_playing() + item_time = datetime.datetime.strptime(''.join(str(item[8])), pseudo_channel.APP_TIME_FORMAT_STR) + #if item_time == closest_media: + #print "Line 1088, Here", item + elapsed_time = item_time - now + print("INFO: "+str(elapsed_time.total_seconds())) + try: + endTime = datetime.datetime.strptime(item[9], '%Y-%m-%d %H:%M:%S.%f') + except ValueError: + endTime = datetime.datetime.strptime(item[9], '%Y-%m-%d %H:%M:%S') + # we need to play the content and add an offest + if elapsed_time.total_seconds() < 0 and \ + endTime > now: + print(str("NOTICE: Queueing up {} to play right away.".format(item[3])).encode('UTF-8')) + offset = int(abs(elapsed_time.total_seconds() * 1000)) + try: + nat_start = datetime.datetime.strptime(item[9], '%Y-%m-%d %H:%M:%S.%f') - datetime.timedelta(milliseconds=item[7]) + except: + nat_start = datetime.datetime.strptime(item[9], '%Y-%m-%d %H:%M:%S') - datetime.timedelta(milliseconds=item[7]) + schedule_offset = nat_start - datetime.datetime.strptime(item[8], pseudo_channel.APP_TIME_FORMAT_STR) + schedule_offset = schedule_offset.total_seconds() + print("INFO: Schedule Offset = " + str(schedule_offset)) + nat_start = nat_start.strftime(pseudo_channel.APP_TIME_FORMAT_STR) + print("INFO: Natural Start Time:") + print(nat_start) + daily_schedule = pseudo_channel.db.get_daily_schedule() + if schedule_offset < 0: + schedule_offset_ms = abs(schedule_offset) * 1000 + offset_plus = int(offset + abs(schedule_offset_ms)) + print("INFO: Updated Offset = " + str(offset_plus)) + pseudo_channel.controller.play(item, daily_schedule, offset_plus) + else: + print("INFO: No Offset Update") + pseudo_channel.controller.play(item, daily_schedule, offset) def job_that_executes_once(item, schedulelist): - print(str("##### Readying media: '{}'".format(item[3])).encode('UTF-8')) - next_start_time = datetime.datetime.strptime(item[8], "%I:%M:%S %p") + print(str("NOTICE: Readying media: '{}'".format(item[3])).encode('UTF-8')) + next_start_time = datetime.datetime.strptime(item[8], pseudo_channel.APP_TIME_FORMAT_STR) now = datetime.datetime.now() now = now.replace(year=1900, month=1, day=1) time_diff = next_start_time - now - + nat_start = datetime.datetime.strptime(item[9], '%Y-%m-%d %H:%M:%S.%f') - datetime.timedelta(milliseconds=item[7]) + schedule_offset = nat_start - datetime.datetime.strptime(item[8], pseudo_channel.APP_TIME_FORMAT_STR) + schedule_offset = schedule_offset.total_seconds() + print("INFO: Schedule Offset = " + str(schedule_offset)) + nat_start = nat_start.strftime(pseudo_channel.APP_TIME_FORMAT_STR) + print("INFO: Natural Start Time: " + str(nat_start)) + daily_schedule = pseudo_channel.db.get_daily_schedule() if time_diff.total_seconds() > 0: - print("+++++ Sleeping for {} seconds before playing: '{}'".format(time_diff.total_seconds(), item[3])) + nat_start = datetime.datetime.strptime(item[9], '%Y-%m-%d %H:%M:%S.%f') - datetime.timedelta(milliseconds=item[7]) + schedule_offset = nat_start - datetime.datetime.strptime(item[8], pseudo_channel.APP_TIME_FORMAT_STR) + schedule_offset = schedule_offset.total_seconds() + print("INFO: Schedule Offset = " + str(schedule_offset)) + nat_start = nat_start.strftime(pseudo_channel.APP_TIME_FORMAT_STR) + print("INFO: Natural Start Time: " + str(nat_start)) + print("NOTICE: Sleeping for {} seconds before playing: '{}'".format(time_diff.total_seconds(), item[3])) sleep(int(time_diff.total_seconds())) if pseudo_channel.DEBUG: - print("+++++ Woke up!") - pseudo_channel.controller.play(item, schedulelist) + print("NOTICE: Woke up!") + if schedule_offset < 0: #OFFSET CHECKER + schedule_offset_ms = abs(schedule_offset) * 1000 + print("INFO: Updated Offset = " + str(schedule_offset_ms)) + pseudo_channel.controller.play(item, daily_schedule, schedule_offset_ms) + else: + print("INFO: job_that_executes_once - No offset") + pseudo_channel.controller.play(item, daily_schedule) else: - pseudo_channel.controller.play(item, schedulelist) + nat_start = datetime.datetime.strptime(item[9], '%Y-%m-%d %H:%M:%S.%f') - datetime.timedelta(milliseconds=item[7]) + schedule_offset = nat_start - datetime.datetime.strptime(item[8], pseudo_channel.APP_TIME_FORMAT_STR) + schedule_offset = schedule_offset.total_seconds() + print("INFO: Schedule Offset = " + str(schedule_offset)) + nat_start = nat_start.strftime(pseudo_channel.APP_TIME_FORMAT_STR) + print("INFO: Natural Start Time: " + str(nat_start)) + if schedule_offset < 0: + schedule_offset_ms = int(abs(schedule_offset) * 1000) + print("INFO: Updated Offset = " + str(schedule_offset_ms)) + pseudo_channel.controller.play(item, daily_schedule, schedule_offset_ms) + else: + print("INFO: job_that_executes_once - No offset 2") + pseudo_channel.controller.play(item, daily_schedule) return schedule.CancelJob + def generate_memory_schedule(schedulelist, isforupdate=False): - print("##### Generating Memory Schedule.") + print("NOTICE: Generating Memory Schedule.") now = datetime.datetime.now() now = now.replace(year=1900, month=1, day=1) pseudo_cache = pseudo_channel.get_daily_schedule_cache_as_json() prev_end_time_to_watch_for = None if pseudo_channel.USE_OVERRIDE_CACHE and isforupdate: for cached_item in pseudo_cache: - prev_start_time = datetime.datetime.strptime(cached_item[8], "%I:%M:%S %p") + prev_start_time = datetime.datetime.strptime(cached_item[8], pseudo_channel.APP_TIME_FORMAT_STR) try: prev_end_time = datetime.datetime.strptime(cached_item[9], '%Y-%m-%d %H:%M:%S.%f') except ValueError: @@ -1157,26 +1610,26 @@ if __name__ == '__main__': """If update time is in between the prev media start / stop then there is overlap""" if prev_start_time < now and prev_end_time > now: try: - print("+++++ It looks like there is update schedule overlap", cached_item[3]) + print("INFO: It looks like there is update schedule overlap", cached_item[3]) except: pass prev_end_time_to_watch_for = prev_end_time for item in schedulelist: - trans_time = datetime.datetime.strptime(item[8], "%I:%M:%S %p").strftime("%H:%M") - new_start_time = datetime.datetime.strptime(item[8], "%I:%M:%S %p") + trans_time = datetime.datetime.strptime(item[8], pseudo_channel.APP_TIME_FORMAT_STR).strftime("%H:%M") + new_start_time = datetime.datetime.strptime(item[8], pseudo_channel.APP_TIME_FORMAT_STR) if prev_end_time_to_watch_for == None: schedule.every().day.at(trans_time).do(job_that_executes_once, item, schedulelist).tag('daily-tasks') else: """If prev end time is more then the start time of this media, skip it""" if prev_end_time_to_watch_for > new_start_time: try: - print("Skipping scheduling item do to cached overlap.", item[3]) + print("NOTICE: Skipping scheduling item do to cached overlap.", item[3]) except: pass continue else: schedule.every().day.at(trans_time).do(job_that_executes_once, item, schedulelist).tag('daily-tasks') - print("+++++ Done.") + print("NOTICE: Done.") generate_memory_schedule(pseudo_channel.db.get_daily_schedule()) daily_update_time = datetime.datetime.strptime( pseudo_channel.translate_time( @@ -1197,7 +1650,7 @@ if __name__ == '__main__': try: pseudo_channel.generate_daily_schedule() except: - print("----- Recieved error when running generate_daily_schedule()") + print("ERROR: Recieved error when running generate_daily_schedule()") generate_memory_schedule(pseudo_channel.db.get_daily_schedule(), True) """Commenting out below and leaving all updates to be handled by cron task""" @@ -1213,10 +1666,12 @@ if __name__ == '__main__': try: while True: schedule.run_pending() - sleep(1) + sleep(0.1) if sleep_before_triggering_play_now: - logging.info("+++++ Successfully started PseudoChannel.py") + logging.info("NOTICE: Successfully started PseudoChannel.py") trigger_what_should_be_playing_now() sleep_before_triggering_play_now = 0 + #generate_memory_schedule(pseudo_channel.db.get_daily_schedule()) except KeyboardInterrupt: - print(' Manual break by user') \ No newline at end of file + print('ALERT: Manual break by user!') + diff --git a/both-dir/pseudo_config.py b/both-dir/pseudo_config.py index eaa11d1..87906bd 100644 --- a/both-dir/pseudo_config.py +++ b/both-dir/pseudo_config.py @@ -38,18 +38,18 @@ * List of plex clients to use (add multiple clients to control multiple TV's) * ''' -plexClients = ['RasPlex'] +plexClients = ['LivingRoom'] plexLibraries = { - "TV Shows" : ["TV"], - "Movies" : ["Films"], - "Commercials" : ["Commercials", "Smashing Pumpkins - Videos"], + "TV Shows" : ["TV Shows"], + "Movies" : ["Movies"], + "Commercials" : ["00s Commercials", "10s Commercials", "70s Commercials", "80s Commercials", "90s Commercials", "Fake Commercials", "Music Videos", "Netflix Trailers", "Station-ID", "Trailers", "Extras"], } useCommercialInjection = True """How many seconds to pad commercials between each other / other media""" -commercialPadding = 5 +commercialPadding = 1 """ Specify the path to this controller on the network (i.e. 'http://192.168.1.28' - no trailing slash). @@ -58,8 +58,8 @@ schedule will be served at "http://:/" (i.e. "http://192.168 You can also leave the below controllerServerPath empty if you'd like to run your own webserver. """ -controllerServerPath = "http://192.168.1.28" -controllerServerPort = "8000" +controllerServerPath = "" +controllerServerPort = "" """ This variable sets the title for the PseudoChannel.py html page. @@ -73,7 +73,7 @@ override any media that is trying to play while the previous day is finishing. """ useDailyOverlapCache = False -dailyUpdateTime = "12:01 AM" +dailyUpdateTime = "5:00" """When to delete / remake the pseudo-channel.log - right at midnight, (i.e. 'friday') """ rotateLog = "friday" @@ -101,7 +101,7 @@ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) try: import plex_token as plex_token except ImportError as e: - print "+++++ Cannot find plex_token file. Make sure you create a plex_token.py file with the appropriate data." + print("NOTICE: Cannot find plex_token file. Make sure you create a plex_token.py file with the appropriate data.") raise e baseurl = plex_token.baseurl diff --git a/both-dir/src/PseudoChannelCommercial.py b/both-dir/src/PseudoChannelCommercial.py index 8b56732..300c38c 100644 --- a/both-dir/src/PseudoChannelCommercial.py +++ b/both-dir/src/PseudoChannelCommercial.py @@ -41,31 +41,44 @@ class PseudoChannelCommercial(): commercial = tuple(commercial_as_list) return commercial - def get_commercials_to_place_between_media(self, last_ep, now_ep, strict_time): + def get_commercials_to_place_between_media(self, last_ep, now_ep, strict_time, reset_time): + reset_time = datetime.strptime(reset_time,'%H:%M') prev_item_end_time = datetime.strptime(last_ep.end_time.strftime('%Y-%m-%d %H:%M:%S.%f'), '%Y-%m-%d %H:%M:%S.%f') - curr_item_start_time = datetime.strptime(now_ep.start_time, '%I:%M:%S %p') - time_diff = (curr_item_start_time - prev_item_end_time) + if(now_ep != "reset"): + curr_item_start_time = datetime.strptime(now_ep.start_time, '%H:%M:%S') + else: + curr_item_start_time = reset_time + if(curr_item_start_time < prev_item_end_time): + curr_item_start_time = curr_item_start_time.replace(day=1) + else: + curr_item_start_time = curr_item_start_time.replace(day=2) + # mutto233 has added some logic at this point # - All dates are now changed to 1/1/90 so midnight doesn't cause issues # - Issues with day skips again being adressed now = datetime.now() now = now.replace(year=1900, month=1, day=1) midnight = now.replace(hour=0,minute=0,second=0) + if(curr_item_start_time < reset_time): + curr_item_start_time = curr_item_start_time.replace(day=2) + if(prev_item_end_time < reset_time): + prev_item_end_time = prev_item_end_time.replace(day=2) + else: + prev_item_end_time = prev_item_end_time.replace(day=1) + time_diff = (curr_item_start_time - prev_item_end_time) - prev_item_end_time = prev_item_end_time.replace(day=1) - - if prev_item_end_time.replace(second=0,microsecond=0) > curr_item_start_time and strict_time == "false": + if prev_item_end_time.replace(microsecond=0) > curr_item_start_time and strict_time == "false": # NOTE: This is just for the logic of this function, I have noticed that this # may cause other issues in other functions, since now the day is off. - print("WE MUST BE SKIPPING A DAY, ADDING A DAY TO THE START TIME") + print("NOTICE: WE MUST BE SKIPPING A DAY, ADDING A DAY TO THE START TIME") curr_item_start_time = curr_item_start_time.replace(day=2) print("##############################################") print("get_commercials_to_place_between_media DEBUG") print("NOW: %s" % now) - print("prev_item_end_time: %s" % prev_item_end_time.replace(second=0,microsecond=0) ) + print("prev_item_end_time: %s" % prev_item_end_time.replace(microsecond=0)) print("curr_item_start_time: %s" % curr_item_start_time) print("time_diff: %s" % time_diff) print("##############################################") @@ -76,7 +89,7 @@ class PseudoChannelCommercial(): time_diff_milli = self.timedelta_milliseconds(time_diff) last_commercial = None time_watch = prev_item_end_time - new_commercial_start_time = prev_item_end_time + new_commercial_start_time = prev_item_end_time + timedelta(seconds=1) while curr_item_start_time > new_commercial_start_time: random_commercial_without_pad = self.get_random_commercial() """ @@ -85,15 +98,15 @@ class PseudoChannelCommercial(): random_commercial = self.pad_the_commercial_dur(random_commercial_without_pad) new_commercial_milli = int(random_commercial[4]) if last_commercial != None: - new_commercial_start_time = last_commercial.end_time + new_commercial_start_time = last_commercial.end_time + timedelta(seconds=1) new_commercial_end_time = new_commercial_start_time + \ timedelta(milliseconds=int(new_commercial_milli)) else: - new_commercial_start_time = prev_item_end_time + new_commercial_start_time = prev_item_end_time + timedelta(seconds=1) new_commercial_end_time = new_commercial_start_time + \ timedelta(milliseconds=int(new_commercial_milli)) commercial_dur_sum += new_commercial_milli - formatted_time_for_new_commercial = new_commercial_start_time.strftime('%I:%M:%S %p') + formatted_time_for_new_commercial = new_commercial_start_time.strftime('%H:%M:%S') new_commercial = Commercial( "Commercials", random_commercial[3], @@ -104,7 +117,7 @@ class PseudoChannelCommercial(): "true", # is_strict_time "1", # time_shift "0", # overlap_max - "", # plex_media_id + random_commercial[5], # plex_media_id random_commercial[6], # custom lib name ) last_commercial = new_commercial @@ -118,13 +131,13 @@ class PseudoChannelCommercial(): else: # If the gap is smaller than the shortest commercial, break. - gapToFill = curr_item_start_time - datetime.strptime(new_commercial.natural_start_time, '%I:%M:%S %p') + gapToFill = curr_item_start_time - datetime.strptime(new_commercial.natural_start_time, '%H:%M:%S') if int(self.commercials[0][4]) > self.timedelta_milliseconds(gapToFill): break else: - print("===== Finding correct FINAL commercial to add to List.") + print("NOTICE: Finding correct FINAL commercial to add to List.") last_comm = None for comm in self.commercials: @@ -133,9 +146,9 @@ class PseudoChannelCommercial(): random_final_comm = last_comm - formatted_time_for_final_commercial = datetime.strptime(new_commercial.natural_start_time, '%I:%M:%S %p').strftime('%I:%M:%S %p') + formatted_time_for_final_commercial = datetime.strptime(new_commercial.natural_start_time, '%H:%M:%S').strftime('%H:%M:%S') - final_commercial_end_time = datetime.strptime(new_commercial.natural_start_time, '%I:%M:%S %p') + \ + final_commercial_end_time = datetime.strptime(new_commercial.natural_start_time, '%H:%M:%S') + \ timedelta(milliseconds=int(random_final_comm[4])) final_commercial = Commercial( @@ -148,7 +161,7 @@ class PseudoChannelCommercial(): "true", # is_strict_time "1", # time_shift "0", # overlap_max - "", # plex_media_id + random_final_comm[5], # plex_media_id random_final_comm[6], # custom lib name ) commercial_list.append(final_commercial) @@ -156,4 +169,4 @@ class PseudoChannelCommercial(): last_comm = comm break commercial_list.append(new_commercial) - return commercial_list \ No newline at end of file + return commercial_list diff --git a/both-dir/src/PseudoChannelDatabase.py b/both-dir/src/PseudoChannelDatabase.py index 5f2899d..81a7d1f 100644 --- a/both-dir/src/PseudoChannelDatabase.py +++ b/both-dir/src/PseudoChannelDatabase.py @@ -51,7 +51,7 @@ class PseudoChannelDatabase(): self.cursor.execute('CREATE TABLE IF NOT EXISTS ' 'app_settings(id INTEGER PRIMARY KEY AUTOINCREMENT, version TEXT)') #index - self.cursor.execute('CREATE UNIQUE INDEX IF NOT EXISTS idx_episode_plexMediaID ON episodes (plexMediaID);') + self.cursor.execute('CREATE INDEX IF NOT EXISTS idx_episode_plexMediaID ON episodes (plexMediaID);') self.cursor.execute('CREATE UNIQUE INDEX IF NOT EXISTS idx_movie_plexMediaID ON movies (plexMediaID);') self.cursor.execute('CREATE UNIQUE INDEX IF NOT EXISTS idx_shows_plexMediaID ON shows (plexMediaID);') self.cursor.execute('CREATE UNIQUE INDEX IF NOT EXISTS idx_video_plexMediaID ON videos (plexMediaID);') @@ -182,6 +182,29 @@ class PseudoChannelDatabase(): self.conn.rollback() raise e + def add_playlist_entries_to_db( + self, + mediaID, + title, + duration, + episodeNumber, + seasonNumber, + showTitle, + plexMediaID, + customSectionName): + + unix = int(time.time()) + try: + self.cursor.execute("INSERT INTO episodes " + "(unix, mediaID, title, duration, episodeNumber, seasonNumber, showTitle, plexMediaID, customSectionName) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", + (unix, mediaID, title, duration, episodeNumber, seasonNumber, showTitle, plexMediaID, customSectionName)) + self.conn.commit() + # Catch the exception + except Exception as e: + # Roll back any change if something goes wrong + self.conn.rollback() + raise e + def add_episodes_to_db( self, mediaID, @@ -221,7 +244,8 @@ class PseudoChannelDatabase(): self.conn.commit() # Catch the exception except Exception as e: - print(plexMediaID) + print("ERROR: "+str(plexMediaID)) + print(e) # Roll back any change if something goes wrong self.conn.rollback() raise e @@ -268,8 +292,8 @@ class PseudoChannelDatabase(): customSectionName ): - print("sectionType", sectionType) - print("customSectionName", customSectionName) + print("INFO: sectionType "+str(sectionType)) + print("INFO: customSectionName"+str(customSectionName)) unix = int(time.time()) try: self.cursor.execute("INSERT OR REPLACE INTO daily_schedule " @@ -301,11 +325,11 @@ class PseudoChannelDatabase(): def add_media_to_daily_schedule(self, media): try: - print(str("#### Adding media to db: {} {}".format(media.title, media.start_time)).encode('UTF-8')) + print(str("NOTICE: Adding media to db: {} {}".format(media.title, media.start_time)).encode('UTF-8')) except: - print("----- Not outputting media info due to ascii code issues.") + print("ERROR: Not outputting media info due to ascii code issues.") - print("media.custom_section_name", media.custom_section_name) + print("INFO: media.custom_section_name", media.custom_section_name) self.add_daily_schedule_to_db( 0, media.title, @@ -396,11 +420,15 @@ class PseudoChannelDatabase(): Updaters, etc. """ def update_shows_table_with_last_episode(self, showTitle, lastEpisodeTitle): - sql1 = "UPDATE shows SET lastEpisodeTitle = ? WHERE title LIKE ? COLLATE NOCASE" self.cursor.execute(sql1, (lastEpisodeTitle, showTitle, )) self.conn.commit() + def update_shows_table_with_last_episode_alt(self, showTitle, lastEpisodeTitle): + sql1 = "UPDATE shows SET lastEpisodeTitle = ? WHERE title LIKE ? COLLATE NOCASE" + self.cursor.execute(sql1, (lastEpisodeTitle, '%'+showTitle+'%', )) + self.conn.commit() + def update_movies_table_with_last_played_date(self, movieTitle): now = datetime.datetime.now() @@ -412,15 +440,26 @@ class PseudoChannelDatabase(): """Database functions. Getters, etc. """ + + def get_shows_titles(self): + self.cursor.execute("SELECT title FROM shows") + datalist = self.cursor.fetchall() + return datalist + def get_shows_table(self): sql = "SELECT * FROM shows" self.cursor.execute(sql) return self.cursor.fetchall() + def get_episode_from_season_episode(self, title, seasonNumber, episodeNumber): + sql = "SELECT * FROM episodes WHERE (showTitle LIKE ?) AND (seasonNumber LIKE ?) AND (episodeNumber LIKE ?) LIMIT 1" + self.cursor.execute(sql, (title, seasonNumber, episodeNumber, )) + return self.cursor.fetchone() + def get_media(self, title, mediaType): - print("+++++ title:", title) + print("INFO: title:", title) if(title is not None): media = mediaType sql = "SELECT * FROM "+media+" WHERE (title LIKE ?) COLLATE NOCASE" @@ -432,16 +471,27 @@ class PseudoChannelDatabase(): def get_schedule(self): - self.cursor.execute("SELECT * FROM schedule ORDER BY datetime(startTimeUnix) ASC") + self.cursor.execute("SELECT * FROM schedule ORDER BY datetime(startTime) ASC") datalist = list(self.cursor.fetchall()) return datalist + def get_schedule_alternate(self,time): + t = str("%02d"%int(time[0])) + sql = ("SELECT * FROM schedule WHERE substr(startTime,1,2) >= ? ORDER BY datetime(startTime) ASC") + self.cursor.execute(sql, [t]) + datalist = list(self.cursor.fetchall()) + sql = ("SELECT * FROM schedule WHERE substr(startTime,1,2) < ? ORDER BY datetime(startTime) ASC") + self.cursor.execute(sql, [t]) + secondHalf = list(self.cursor.fetchall()) + datalist.extend(secondHalf) + return datalist + def get_daily_schedule(self): - print("##### Getting Daily Schedule from DB.") + print("NOTICE Getting Daily Schedule from DB.") self.cursor.execute("SELECT * FROM daily_schedule ORDER BY datetime(startTime) ASC") datalist = list(self.cursor.fetchall()) - print("+++++ Done.") + print("NOTICE: Done.") return datalist def get_movie(self, title): @@ -481,6 +531,26 @@ class PseudoChannelDatabase(): datalist = list(self.cursor.fetchall()) return datalist + def get_specific_episode(self, tvshow, season=None, episode=None): + if season is None and episode is None: + print("ERROR: Season and Episode Numbers Not Found") + pass + elif season is None: + episode = str(episode) + sql = ("SELECT * FROM episodes WHERE ( showTitle LIKE ? and episodeNumber LIKE ?) ORDER BY RANDOM()") + self.cursor.execute(sql, (tvshow, "%"+episode+"&", )) + elif episode is None: + season = str(season) + sql = ("SELECT * FROM episodes WHERE ( showTitle LIKE ? and seasonNumber LIKE ?) ORDER BY RANDOM()") + self.cursor.execute(sql, (tvshow, "%"+season+"%", )) + else: + episode = str(episode) + season = str(season) + sql = ("SELECT * FROM episodes WHERE ( showTitle LIKE ? and seasonNumber LIKE ? and episodeNumber LIKE ?) ORDER BY RANDOM()") + self.cursor.execute(sql, (tvshow, "%"+season+"%", "%"+episode+"%", )) + media_item = self.cursor.fetchone() + return media_item + def get_first_episode(self, tvshow): sql = ("SELECT id, unix, mediaID, title, duration, MIN(episodeNumber), MIN(seasonNumber), " @@ -500,10 +570,10 @@ class PseudoChannelDatabase(): episode_id = self.cursor.fetchone() return episode_id - ####mutto233 made this one#### - def get_episode_id_alternate(self, plexMediaID): - sql = "SELECT id FROM episodes WHERE( plexMediaID LIKE ?) COLLATE NOCASE" - self.cursor.execute(sql, (plexMediaID, )) + ####mutto233 made this one#### UPDATED 5/2/2020 + def get_episode_id_alternate(self,plexMediaID,series): + sql = "SELECT id FROM episodes WHERE (showTitle LIKE ? AND plexMediaID LIKE ?) COLLATE NOCASE" + self.cursor.execute(sql, (series,plexMediaID, )) episode_id = self.cursor.fetchone() return episode_id ####mutto233 made this one#### @@ -513,7 +583,12 @@ class PseudoChannelDatabase(): sql = "SELECT * FROM episodes WHERE id IN (SELECT id FROM episodes ORDER BY RANDOM() LIMIT 1)" self.cursor.execute(sql) return self.cursor.fetchone() - + + def get_random_episode_duration(self,min,max): + sql = "SELECT * FROM episodes WHERE (customSectionName NOT LIKE 'playlist' AND duration BETWEEN ? and ?) ORDER BY RANDOM() LIMIT 1" + self.cursor.execute(sql, (min, max, )) + return self.cursor.fetchone() + ####mutto233 made this one#### def get_random_episode_alternate(self,series): @@ -527,7 +602,40 @@ class PseudoChannelDatabase(): sql = "SELECT * FROM movies WHERE id IN (SELECT id FROM movies ORDER BY RANDOM() LIMIT 1)" self.cursor.execute(sql) return self.cursor.fetchone() - + + def get_random_movie_duration(self,min,max): + + sql = "SELECT * FROM movies WHERE (duration BETWEEN ? and ?) ORDER BY RANDOM() LIMIT 1" + self.cursor.execute(sql, (min, max, )) + return self.cursor.fetchone() + + ###added 5/4/2020### + def get_random_episode_of_show(self,series): + print(series.upper()) + sql = "SELECT * FROM episodes WHERE (showTitle LIKE ?) ORDER BY RANDOM() LIMIT 1" + self.cursor.execute(sql, (series, )) + return self.cursor.fetchone() + + def get_random_episode_of_show_alt(self,series): + sql = "SELECT * FROM episodes WHERE (showTitle LIKE '%"+series+"%') ORDER BY RANDOM() LIMIT 1" + self.cursor.execute(sql) + return self.cursor.fetchone() + + def get_random_episode_of_show_duration(self,series,min,max): + sql = "SELECT * FROM episodes WHERE (showTitle LIKE '%"+series+"%' AND duration BETWEEN ? and ?) ORDER BY RANDOM() LIMIT 1" + self.cursor.execute(sql (min, max, )) + return self.cursor.fetchone() + + def get_random_show(self): + sql = "SELECT * FROM shows WHERE (customSectionName NOT LIKE 'playlist' AND id IN (SELECT id FROM shows ORDER BY RANDOM() LIMIT 1))" + self.cursor.execute(sql) + return self.cursor.fetchone() + ### + def get_random_show_duration(self,min,max): + sql = "SELECT * FROM shows WHERE (customSectionName NOT LIKE 'playlist' AND duration BETWEEN ? and ?) ORDER BY RANDOM() LIMIT 1" + self.cursor.execute(sql, (min, max, )) + return self.cursor.fetchone() + ####mutto233 made this one#### def get_next_episode(self, series): ''' @@ -536,7 +644,7 @@ class PseudoChannelDatabase(): * determine what has been previously scheduled for each show * ''' - self.cursor.execute("SELECT lastEpisodeTitle FROM shows WHERE title LIKE ? COLLATE NOCASE", (series, )) + self.cursor.execute("SELECT lastEpisodeTitle FROM shows WHERE title LIKE ? COLLATE NOCASE", (series, )) last_title_list = self.cursor.fetchone() ''' * @@ -572,16 +680,18 @@ class PseudoChannelDatabase(): * """ try: - sql = ("SELECT * FROM episodes WHERE ( id > "+str(self.get_episode_id_alternate(last_title_list[0])[0])+ + print("NOTICE: Getting next episode of "+series.upper()+ " by matching ID and series or playlist name") + sql = ("SELECT * FROM episodes WHERE ( id > "+str(self.get_episode_id_alternate(last_title_list[0],series)[0])+ " AND showTitle LIKE ? ) ORDER BY seasonNumber LIMIT 1 COLLATE NOCASE") except TypeError: try: + print("NOTICE: Getting next episode by matching title") sql = ("SELECT * FROM episodes WHERE ( id > "+str(self.get_episode_id(last_title_list[0])[0])+ " AND showTitle LIKE ? ) ORDER BY seasonNumber LIMIT 1 COLLATE NOCASE") - print("+++++ We have an old school last episode title. Using old method, then converting to new method") + print("NOTICE: We have an old school last episode title. Using old method, then converting to new method") except TypeError: sql = "" - print("+++++ For some reason, episode was not stored correctly. Maybe you updated your database and lost last episode? Reverting to first episode") + print("ERROR: For some reason, episode was not stored correctly. Maybe you updated your database and lost last episode? Reverting to first episode") if sql=="": first_episode = self.get_first_episode(series) self.update_shows_table_with_last_episode(series, first_episode[8]) @@ -605,74 +715,11 @@ class PseudoChannelDatabase(): self.update_shows_table_with_last_episode(series, next_episode[8]) return next_episode else: - print("+++++ Not grabbing next episode restarting series, series must be over. Restarting from episode 1.") + print("NOTICE: Not grabbing next episode restarting series, series must be over. Restarting from episode 1.") first_episode = self.get_first_episode(series) self.update_shows_table_with_last_episode(series, first_episode[8]) return first_episode - ####mutto233 made this one#### - -# ''' -# * -# * As a way of storing a "queue", I am storing the *next episode title in the "shows" table so I can -# * determine what has been previously scheduled for each show -# * -# ''' -# self.cursor.execute("SELECT lastEpisodeTitle FROM shows WHERE title LIKE ? COLLATE NOCASE", (series, )) -# last_title_list = self.cursor.fetchone() -# ''' -# * -# * If the last episode stored in the "shows" table is empty, then this is probably a first run... -# * -# ''' -# if last_title_list and last_title_list[0] == '': -# -# ''' -# * -# * Find the first episode of the series -# * -# ''' -# first_episode = self.get_first_episode(series) -# first_episode_title = first_episode[3] -# ''' -# * -# * Add this episdoe title to the "shows" table for the queue functionality to work -# * -# ''' -# self.update_shows_table_with_last_episode(series, first_episode_title) -# return first_episode -# -# elif last_title_list: -# ''' -# * -# * The last episode stored in the "shows" table was not empty... get the next episode in the series -# * -# ''' -# """ -# * -# * If this isn't a first run, then grabbing the next episode by incrementing id -# * -# """ -# sql = ("SELECT * FROM episodes WHERE ( id > "+str(self.get_episode_id(last_title_list[0])[0])+ -# " AND showTitle LIKE ? ) ORDER BY seasonNumber LIMIT 1 COLLATE NOCASE") -# self.cursor.execute(sql, (series, )) -# ''' -# * -# * Try and advance to the next episode in the series, if it returns None then that means it reached the end... -# * -# ''' -# next_episode = self.cursor.fetchone() -# print(next_episode) -# print(next_episode[8]) -# raise ValueError("WAHOO") -# if next_episode != None: -# self.update_shows_table_with_last_episode(series, next_episode[3]) -# return next_episode -# else: -# print("+++++ Not grabbing next episode restarting series, series must be over. Restarting from episode 1.") -# first_episode = self.get_first_episode(series) -# self.update_shows_table_with_last_episode(series, first_episode[3]) -# return first_episode - + def get_commercial(self, title): media = "commercials" @@ -683,4 +730,12 @@ class PseudoChannelDatabase(): print(datalist) return datalist else: - return None \ No newline at end of file + return None + + def get_now_playing(self): + print("NOTICE: Getting Now Playing Item from Daily Schedule DB.") + sql = "SELECT * FROM daily_schedule WHERE (time(endTime) >= time('now','localtime') AND time(startTime) <= time('now','localtime')) ORDER BY time(startTime) ASC" + self.cursor.execute(sql) + datalist = list(self.cursor.fetchone()) + print("NOTICE: Done.") + return datalist diff --git a/both-dir/src/PseudoChannelRandomMovie.py b/both-dir/src/PseudoChannelRandomMovie.py index 219e068..3839b64 100644 --- a/both-dir/src/PseudoChannelRandomMovie.py +++ b/both-dir/src/PseudoChannelRandomMovie.py @@ -43,7 +43,7 @@ class PseudoChannelRandomMovie(): if(movie[5] is not None): #lastPlayedDate is recorded - print(movie[5]) + print("INFO: Last Played Date is "+str(movie[5])) now = datetime.datetime.now() lastPlayedDate = datetime.datetime.strptime(movie[5], '%Y-%m-%d') @@ -75,26 +75,24 @@ class PseudoChannelRandomMovie(): shuffle(self.MOVIES_DB) - print("get_random_movie_xtra") + print("NOTICE: get_random_movie_xtra") for movieOne in self.MOVIES_XTRA_LIST: - print("while i < len(self.MOVIES_XTRA_LIST):") + print("INFO: while i < len(self.MOVIES_XTRA_LIST):") movieTitle = movieOne.title - print("movieTitle", movieTitle) + print("INFO: movieTitle", movieTitle) for movie in self.MOVIES_DB: - print("for movie in self.MOVIES_DB:") + print("INFO: for movie in self.MOVIES_DB:") if movie[3] == movieTitle: #title match found if(movie[5] is not None): #lastPlayedDate is recorded - - print("I am here") - + print("INFO: Last Played Date is "+str(movie[5])) now = datetime.datetime.now() lastPlayedDate = datetime.datetime.strptime(movie[5], '%Y-%m-%d') @@ -102,7 +100,7 @@ class PseudoChannelRandomMovie(): if(timeDelta.days >= self.TIME_GAP_DAYS): - print("if(timeDelta.months >= self.TIME_GAP_DAYS):") + print("INFO: if(timeDelta.months >= self.TIME_GAP_DAYS):") return movieTitle diff --git a/both-dir/src/PseudoDailyScheduleController.py b/both-dir/src/PseudoDailyScheduleController.py index b10fdf5..b661dea 100644 --- a/both-dir/src/PseudoDailyScheduleController.py +++ b/both-dir/src/PseudoDailyScheduleController.py @@ -5,15 +5,16 @@ import socket import logging import logging.handlers from datetime import datetime +from datetime import time +from datetime import timedelta +from datetime import tzinfo +import pytz import sqlite3 -import _thread -import socketserver -import http.server +import _thread,socketserver,http.server from plexapi.server import PlexServer from yattag import Doc from yattag import indent import pseudo_config as config - class PseudoDailyScheduleController(): def __init__(self, @@ -57,11 +58,8 @@ class PseudoDailyScheduleController(): # First, we are going to search for movies/commercials try: movies = self.PLEX.library.section(section).search(title=showtitle) - #print "+++++ Checking Duration for a Match: " for item in movies: -# print item.duration if item.duration == durationAmount: - #print "+++++ MATCH FOUND in %s" % item backgroundImagePath = item break except: @@ -85,15 +83,14 @@ class PseudoDailyScheduleController(): web_dir = os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', 'schedules')) os.chdir(web_dir) PORT = int(self.CONTROLLER_SERVER_PORT) - class MyHandler(http.server.SimpleHTTPRequestHandler): + class MyHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): def log_message(self, format, *args): return global httpd try: - #print "Starting webserver at port: ", PORT - # create the httpd handler for the http.server + # create the httpd handler for the simplehttpserver # we set the allow_reuse_address incase something hangs can still bind to port class ReusableTCPServer(SocketServer.TCPServer): allow_reuse_address=True # specify the httpd service on 0.0.0.0 (all interfaces) on port 80 @@ -104,72 +101,185 @@ class PseudoDailyScheduleController(): except KeyboardInterrupt: core.print_info("Exiting the SET web server...") httpd.socket.close() - except(socket.error, exc): - print("Caught exception socket.error : %s" % exc ) + except socket.error as exc: + print("ERROR: Caught exception socket.error : %s" % exc) # handle the rest - #except Exception: - # print "[*] Exiting the SET web server...\n" - # httpd.socket.close() self.webserverStarted = True def get_xml_from_daily_schedule(self, currentTime, bgImageURL, datalist): now = datetime.now() + new_day = now + timedelta(days=1) time = now.strftime("%B %d, %Y") + update_time = datetime.strptime(config.dailyUpdateTime,'%H:%M').replace(year=int(now.strftime('%Y')),month=int(now.strftime('%m')),day=int(now.strftime('%d'))) doc, tag, text, line = Doc( ).ttl() doc.asis('') with tag('schedule', currently_playing_bg_image=bgImageURL if bgImageURL != None else ''): + previous_row = None for row in datalist: - if str(row[11]) == "Commercials" and self.DEBUG == False: - continue - timeB = datetime.strptime(row[8], '%I:%M:%S %p') - if currentTime == None: - with tag('time', - ('key', str(row[12])), - ('current', 'false'), - ('type', str(row[11])), - ('show-title', str(row[6])), - ('show-season', str(row[5])), - ('show-episode', str(row[4])), - ('title', str(row[3])), - ('duration', str(row[7])), - ('time-start', str(row[8])), - ('time-end', str(row[9])), - ('library', str(row[13])), - ): - text(row[8]) - elif currentTime.hour == timeB.hour and currentTime.minute == timeB.minute: - with tag('time', - ('key', str(row[12])), - ('current', 'true'), - ('type', str(row[11])), - ('show-title', str(row[6])), - ('show-season', str(row[5])), - ('show-episode', str(row[4])), - ('title', str(row[3])), - ('duration', str(row[7])), - ('time-start', str(row[8])), - ('time-end', str(row[9])), - ('library', str(row[13])), - ): - text(row[8]) + try: + start_time = datetime.strptime(row[8],'%I:%M:%S %p') + except: + start_time = datetime.strptime(row[8],'%H:%M:%S') + if start_time > update_time: #checking for after midnight but before reset (from config) + try: + current_start_time = datetime.strptime(row[8],'%I:%M:%S %p').replace(year=int(now.strftime('%Y')),month=int(now.strftime('%m')),day=int(now.strftime('%d'))) + except: + current_start_time = datetime.strptime(row[8],'%H:%M:%S').replace(year=int(now.strftime('%Y')),month=int(now.strftime('%m')),day=int(now.strftime('%d'))) else: - with tag('time', - ('key', str(row[12])), - ('current', 'false'), - ('type', str(row[11])), - ('show-title', str(row[6])), - ('show-season', str(row[5])), - ('show-episode', str(row[4])), - ('title', str(row[3])), - ('duration', str(row[7])), - ('time-start', str(row[8])), - ('time-end', str(row[9])), - ('library', str(row[13])), - ): - text(row[8]) + try: + current_start_time = datetime.strptime(row[8],'%I:%M:%S %p').replace(year=int(new_day.strftime('%Y')),month=int(new_day.strftime('%m')),day=int(new_day.strftime('%d'))) + except: + current_start_time = datetime.strptime(row[8],'%H:%M:%S').replace(year=int(new_day.strftime('%Y')),month=int(new_day.strftime('%m')),day=int(new_day.strftime('%d'))) + current_start_time_unix = (current_start_time - datetime(1970,1,1)).total_seconds() + current_start_time_string = current_start_time.strftime('%H:%M:%S') + try: + if_end_time = datetime.strptime(row[9],'%Y-%m-%d %H:%M:%S.%f') + except ValueError: + if_end_time = datetime.strptime(row[9],'%Y-%m-%d %H:%M:%S') + if if_end_time.replace(year=int(now.strftime('%Y')),month=int(now.strftime('%m')),day=int(now.strftime('%d'))) > update_time: #checking for after midnight but before reset (from config) + current_end_time = if_end_time.replace(year=int(now.strftime('%Y')),month=int(now.strftime('%m')),day=int(now.strftime('%d'))) + else: + current_end_time = if_end_time.replace(year=int(new_day.strftime('%Y')),month=int(new_day.strftime('%m')),day=int(new_day.strftime('%d'))) + current_end_time_unix = (current_end_time - datetime(1970,1,1)).total_seconds() + current_end_time_string = current_end_time.strftime('%H:%M:%S') + if previous_row != None: + #compare previous end time to current start time + try: + previous_end_time = datetime.strptime(previous_row[9], '%Y-%m-%d %H:%M:%S.%f') + except ValueError: + previous_end_time = datetime.strptime(previous_row[9], '%Y-%m-%d %H:%M:%S') + if previous_end_time > update_time: #checking for after midnight but before reset (from config) + previous_end_time = previous_end_time.replace(year=int(now.strftime('%Y')),month=int(now.strftime('%m')),day=int(now.strftime('%d'))) + else: + previous_end_time = previous_end_time.replace(year=int(new_day.strftime('%Y')),month=int(new_day.strftime('%m')),day=int(new_day.strftime('%d'))) + if previous_end_time > current_start_time: + #if previous end time is later than start time, change end time + previous_end_time = current_start_time - timedelta(seconds=1) + #convert start and end times to unix + previous_end_time_unix = (previous_end_time - datetime(1970,1,1)).total_seconds() + #convert start and end times to the same readable format + previous_end_time_string = previous_end_time.strftime('%H:%M:%S') + if str(previous_row[11]) == "Commercials" and self.DEBUG == False: + continue + try: + timeB = datetime.strptime(previous_row[8], '%I:%M:%S %p') + except: + timeB = datetime.strptime(previous_row[8], '%H:%M:%S') + if currentTime == None: + with tag('time', + ('key', str(previous_row[12])), + ('current', 'false'), + ('type', str(previous_row[11])), + ('show-title', str(previous_row[6])), + ('show-season', str(previous_row[5])), + ('show-episode', str(previous_row[4])), + ('title', str(previous_row[3])), + ('duration', str(previous_row[7])), + ('time-start', str(previous_start_time_string)), + ('time-end', str(previous_end_time.strftime('%H:%M:%S'))), + ('time-start-unix', str(previous_start_time_unix)), + ('time-end-unix', str(previous_end_time_unix)), + ('library', str(previous_row[13])), + ): + text(previous_row[8]) + elif currentTime.hour == timeB.hour and currentTime.minute == timeB.minute: + with tag('time', + ('key', str(previous_row[12])), + ('current', 'true'), + ('type', str(previous_row[11])), + ('show-title', str(previous_row[6])), + ('show-season', str(previous_row[5])), + ('show-episode', str(previous_row[4])), + ('title', str(previous_row[3])), + ('duration', str(previous_row[7])), + ('time-start', str(previous_start_time_string)), + ('time-end', str(previous_end_time.strftime('%H:%M:%S'))), + ('time-start-unix', str(previous_start_time_unix)), + ('time-end-unix', str(previous_end_time_unix)), + ('library', str(previous_row[13])), + ): + text(previous_row[8]) + else: + with tag('time', + ('key', str(previous_row[12])), + ('current', 'false'), + ('type', str(previous_row[11])), + ('show-title', str(previous_row[6])), + ('show-season', str(previous_row[5])), + ('show-episode', str(previous_row[4])), + ('title', str(previous_row[3])), + ('duration', str(previous_row[7])), + ('time-start', str(previous_start_time_string)), + ('time-end', str(previous_end_time.strftime('%H:%M:%S'))), + ('time-start-unix', str(previous_start_time_unix)), + ('time-end-unix', str(previous_end_time_unix)), + ('library', str(previous_row[13])), + ): + text(previous_row[8]) + previous_start_time = current_start_time + previous_start_time_unix = current_start_time_unix + previous_start_time_string = current_start_time_string + previous_row = row +# if str(row[11]) == "Commercials" and self.DEBUG == False: +# continue + try: + timeB = datetime.strptime(row[8], '%I:%M:%S %p') + except: + timeB = datetime.strptime(row[8], '%H:%M:%S') + if currentTime == None: + with tag('time', + ('key', str(row[12])), + ('current', 'false'), + ('type', str(row[11])), + ('show-title', str(row[6])), + ('show-season', str(row[5])), + ('show-episode', str(row[4])), + ('title', str(row[3])), + ('duration', str(row[7])), + ('time-start', str(current_start_time_string)), + ('time-end', str(current_end_time_string)), + ('time-start-unix', str(current_start_time_unix)), + ('time-end-unix', str(current_end_time_unix)), + ('library', str(row[13])), + ): + text(row[8]) + elif currentTime.hour == timeB.hour and currentTime.minute == timeB.minute: + with tag('time', + ('key', str(row[12])), + ('current', 'true'), + ('type', str(row[11])), + ('show-title', str(row[6])), + ('show-season', str(row[5])), + ('show-episode', str(row[4])), + ('title', str(row[3])), + ('duration', str(row[7])), + ('time-start', str(current_start_time_string)), + ('time-end', str(current_end_time_string)), + ('time-start-unix', str(current_start_time_unix)), + ('time-end-unix', str(current_end_time_unix)), + ('library', str(row[13])), + ): + text(row[8]) + else: + with tag('time', + ('key', str(row[12])), + ('current', 'false'), + ('type', str(row[11])), + ('show-title', str(row[6])), + ('show-season', str(row[5])), + ('show-episode', str(row[4])), + ('title', str(row[3])), + ('duration', str(row[7])), + ('time-start', str(current_start_time_string)), + ('time-end', str(current_end_time_string)), + ('time-start-unix', str(current_start_time_unix)), + ('time-end-unix', str(current_end_time_unix)), + ('library', str(row[13])), + ): + text(row[8]) return indent(doc.getvalue()) ''' @@ -291,7 +401,10 @@ class PseudoDailyScheduleController(): with tag('tbody'): if currentTime != None: currentTime = currentTime.replace(year=1900, month=1, day=1) - timeBStart = datetime.strptime(row[8], '%I:%M:%S %p') + try: + timeBStart = datetime.strptime(row[8], '%I:%M:%S %p') + except: + timeBStart = datetime.strptime(row[8], '%H:%M:%S') timeBStart = timeBStart.replace(year=1900, month=1, day=1) try: timeBEnd = datetime.strptime(row[9], '%Y-%m-%d %H:%M:%S.%f') @@ -299,11 +412,6 @@ class PseudoDailyScheduleController(): except: timeBEnd = datetime.strptime(row[9], '%Y-%m-%d %H:%M:%S') timeBEnd = timeBEnd.replace(day=1) - #print timeBStart - #print "%s" % row[3] - #print "%s, %s, %s, %s, %s" % (currentTime, timeBStart, timeBEnd, midnight,midnight.replace(hour=0,minute=0,second=0)) - #print "%s" % (timeBStart - timeBEnd).total_seconds() - #print "%s, %s, %s, %s" % ((currentTime-timeBStart).total_seconds(),(midnight-currentTime).total_seconds(),(currentTime-midnight.replace(hour=0,minute=0,second=0)).total_seconds(),(timeBEnd-currentTime).total_seconds()) if currentTime == None: with tag('tr'): with tag('th', scope='row'): @@ -324,7 +432,7 @@ class PseudoDailyScheduleController(): ((currentTime-timeBStart).total_seconds() >= 0 and \ (midnight-currentTime).total_seconds() >= 0))): - print("+++++ Currently Playing:", row[3]) + print("INFO: Currently Playing:", row[3]) with tag('tr', klass='bg-info'): with tag('th', scope='row'): @@ -413,7 +521,7 @@ class PseudoDailyScheduleController(): f.seek(0) first_line = f.read() if self.DEBUG: - print("+++++ Html refresh flag: {}".format(first_line)) + print("INFO: Html refresh flag: {}".format(first_line)) if first_line == '' or first_line == "0": f.seek(0) f.truncate() @@ -432,70 +540,117 @@ class PseudoDailyScheduleController(): * @return null * ''' - def play_media(self, mediaType, mediaParentTitle, mediaTitle, offset, customSectionName, durationAmount): + def play_media(self, mediaType, mediaParentTitle, mediaTitle, offset, customSectionName, durationAmount, mediaID): # Check for necessary client override, if we have a folder of "channels_" cwd = os.getcwd() if "channels_" in cwd: head,sep,tail = cwd.partition('channels_') head,sep,tail = tail.partition('/') self.PLEX_CLIENTS = [head] - print("CLIENT OVERRIDE: %s" % self.PLEX_CLIENTS) - - try: - if mediaType == "TV Shows": + print("NOTICE: CLIENT OVERRIDE: %s" % self.PLEX_CLIENTS) + try: + if customSectionName == "Playlists": + try: + print("NOTICE: Fetching PLAYLIST ITEM from MEDIA ID") + item = self.PLEX.fetchItem(mediaID) + for client in self.PLEX_CLIENTS: + clientItem = self.PLEX.client(client) + clientItem.playMedia(item, offset=offset) + except: + print("ERROR: MEDIA ID FETCH FAILED - Falling Back") + mediaItems = self.PLEX.playlist(mediaParentTitle).items() + print("NOTICE: Checking Key for a Match: ") + for item in mediaItems: + if item.key == mediaID: + print("NOTICE: MATCH ID FOUND IN %s" % item) + for client in self.PLEX_CLIENTS: + clientItem = self.PLEX.client(client) + clientItem.playMedia(item, offset=offset) + break + elif mediaType == "TV Shows" and customSectionName != "Playlists": # print "Here, Trying to play custom type: ", customSectionName - print("+++++ Checking Duration for a Match: ") - mediaItems = self.PLEX.library.section(customSectionName).get(mediaParentTitle).episodes() - for item in mediaItems: -# print item.duration - if item.title == mediaTitle and item.duration == durationAmount: - print("+++++ MATCH FOUND in %s" % item) - for client in self.PLEX_CLIENTS: - clientItem = self.PLEX.client(client) - clientItem.playMedia(item, offset=offset) - break + try: + print("NOTICE: Fetching TV Show from MEDIA ID") + item = self.PLEX.fetchItem(mediaID) + for client in self.PLEX_CLIENTS: + clientItem = self.PLEX.client(client) + clientItem.playMedia(item, offset=offset) + except: + print("ERROR: MEDIA ID FETCH FAILED - Falling Back") + mediaItems = self.PLEX.library.section(customSectionName).get(mediaParentTitle).episodes() + for item in mediaItems: +# print item.duration + if item.title == mediaTitle and item.duration == durationAmount: + print("NOTICE: MATCH FOUND in %s" % item) + for client in self.PLEX_CLIENTS: + clientItem = self.PLEX.client(client) + clientItem.playMedia(item, offset=offset) + break + elif item.key == mediaID: + print("NOTICE: MATCHID FOUND IN %s" % item) + for client in self.PLEX_CLIENTS: + clientItem = self.PLEX.client(client) + clientItem.playMedia(item, offset=offset) + break elif mediaType == "Movies": - movies = self.PLEX.library.section(customSectionName).search(title=mediaTitle) - print("+++++ Checking Duration for a Match: ") - for item in movies: -# print item.duration - if item.duration == durationAmount: - print("+++++ MATCH FOUND in %s" % item) - movie = item - break + idNum = mediaID.lstrip('/library/metadata/') + print("INFO: Plex ID Number: "+idNum) + try: + print("NOTICE: Fetching MOVIE from MEDIA ID") + movie = self.PLEX.fetchItem(mediaID) +# movies = self.PLEX.library.section(customSectionName).get(mediaTitle) + except: + print("ERROR: MEDIA ID FETCH FAILED - Falling Back") + movies = self.PLEX.library.section(customSectionName).search(title=mediaTitle) #movie selection + print("NOTICE: Checking ID for a Match: ") + for item in movies: + if item.key == mediaID: + print("NOTICE: ID MATCH FOUND IN %s" % item.title.upper()) + movie = item + break for client in self.PLEX_CLIENTS: clientItem = self.PLEX.client(client) + print("INFO: Playing "+movie.title.upper()) clientItem.playMedia(movie, offset=offset) elif mediaType == "Commercials": # This one is a bit more complicated, since we have the dirty gap fix possible # Basically, we are going to just assume it isn't a dirty gap fix, and if it is, # We will just play the first value COMMERCIAL_PADDING = config.commercialPadding - movies = self.PLEX.library.section(customSectionName).search(title=mediaTitle) - print("+++++ Checking Duration for a Match: ") - for item in movies: - #print item - #print item.duration - if (item.duration+1000*COMMERCIAL_PADDING) == durationAmount or item.duration == durationAmount: - print("+++++ MATCH FOUND in %s" % item) - movie = item - break + try: + print("NOTICE: Fetching COMMERCIAL from MEDIA ID") + movie = self.PLEX.fetchItem(mediaID) +# movies = self.PLEX.library.section(customSectionName).get(mediaTitle) + except: + print("ERROR: MEDIA ID FETCH FAILED - Falling Back") + movies = self.PLEX.library.section(customSectionName).search(title=mediaTitle) + print("NOTICE: Checking for a Match: ") + for item in movies: + if item.key == mediaID: + print("NOTICE: ID MATCH FOUND in %s" % item) + movie = item + break + elif (item.duration+1000*COMMERCIAL_PADDING) == durationAmount or item.duration == durationAmount: + print("NOTICE: DURATION MATCH FOUND in %s" % item) + movie = item + break try: movie except: - print("+++++ Commercial is NOT FOUND, my guess is this is the dirty gap. Picking first one") + print("ERROR: Commercial is NOT FOUND, my guess is this is the dirty gap. Picking first one") + movies = self.PLEX.library.section(customSectionName).search(title=mediaTitle) movie = movies[0] for client in self.PLEX_CLIENTS: clientItem = self.PLEX.client(client) clientItem.playMedia(movie, offset=offset) else: - print("##### Not sure how to play {}".format(customSectionName)) - print("+++++ Done.") + print("NOTICE: Not sure how to play {}".format(customSectionName)) + print("NOTICE: Done.") except Exception as e: print(e.__doc__) print(e.message) - print("##### There was an error trying to play the media.") + print("ERROR: There was an error trying to play the media.") pass def stop_media(self): @@ -532,7 +687,7 @@ class PseudoDailyScheduleController(): if currentTime.minute == endTime.minute: if currentTime.second == endTime.second: if self.DEBUG: - print("Ok end time found") + print("INFO: Ok end time found") self.write_schedule_to_file(self.get_html_from_daily_schedule(None, None, datalist)) self.write_xml_to_file(self.get_xml_from_daily_schedule(None, None, datalist)) self.write_refresh_bool_to_file() @@ -540,15 +695,18 @@ class PseudoDailyScheduleController(): def play(self, row, datalist, offset=0): - print(str("##### Starting Media: '{}'".format(row[3])).encode('UTF-8')) - print(str("##### Media Offset: '{}' seconds.".format(int(offset / 1000))).encode('UTF-8')) + print(str("NOTICE: Starting Media: '{}'".format(row[3])).encode('UTF-8')) + print(str("NOTICE: Media Offset: '{}' seconds.".format(int(offset / 1000))).encode('UTF-8')) if self.DEBUG: print(str(row).encode('UTF-8')) - timeB = datetime.strptime(row[8], '%I:%M:%S %p') + try: + timeB = datetime.strptime(row[8], '%I:%M:%S %p') + except: + timeB = datetime.strptime(row[8], '%H:%M:%S') - print("Here, row[13]", row[13]) + print("INFO: Here, row[13]", row[13]) - self.play_media(row[11], row[6], row[3], offset, row[13], row[7]) + self.play_media(row[11], row[6], row[3], offset, row[13], row[7], row[12]) self.write_schedule_to_file( self.get_html_from_daily_schedule( timeB, @@ -574,7 +732,7 @@ class PseudoDailyScheduleController(): ) ) try: - self.my_logger.debug('Trying to play: ' + row[3]) + self.my_logger.debug('INFO: Trying to play: ' + row[3]) except: pass @@ -596,13 +754,16 @@ class PseudoDailyScheduleController(): except: pass for row in datalist: - timeB = datetime.strptime(row[8], '%I:%M:%S %p') + try: + timeB = datetime.strptime(row[8], '%I:%M:%S %p') + except: + timeB = datetime.strptime(row[8], '%H:%M:%S') if currentTime.hour == timeB.hour: if currentTime.minute == timeB.minute: if currentTime.second == timeB.second: - print("Starting Media: " + row[3]) + print("NOTICE: Starting Media: " + row[3]) print(row) - self.play_media(row[11], row[6], row[3], row[13], row[7]) + self.play_media(row[11], row[6], row[3], row[13], row[7], row[12]) self.write_schedule_to_file( self.get_html_from_daily_schedule( timeB, @@ -647,7 +808,10 @@ class PseudoDailyScheduleController(): #print row[9] if str(row[11]) == "Commercials" and self.DEBUG == False: continue - timeBStart = datetime.strptime(row[8], '%I:%M:%S %p') + try: + timeBStart = datetime.strptime(row[8], '%I:%M:%S %p') + except: + timeBStart = datetime.strptime(row[8], '%H:%M:%S') timeBStart = timeBStart.replace(year=1900, month=1, day=1) try: timeBEnd = datetime.strptime(row[9], '%Y-%m-%d %H:%M:%S.%f') @@ -655,13 +819,6 @@ class PseudoDailyScheduleController(): except: timeBEnd = datetime.strptime(row[9], '%Y-%m-%d %H:%M:%S') timeBEnd = timeBEnd.replace(day=1) - - #print ((currentTime - timeBStart).total_seconds() >= 0 and \ - # (timeBEnd - currentTime).total_seconds() >= 0) - - #print currentTime.minute - #print timeBStart.minute - if ((currentTime - timeBStart).total_seconds() >= 0 and \ (timeBEnd - currentTime).total_seconds() >= 0) or \ ((timeBStart - timeBEnd).total_seconds() >= 0 and \ @@ -670,7 +827,7 @@ class PseudoDailyScheduleController(): ((currentTime-timeBStart).total_seconds() >= 0 and \ (midnight-currentTime).total_seconds() >= 0))): - print("+++++ Made the conditional & found item: {}".format(row[6])) + print("INFO: Made the conditional & found item: {}".format(row[6])) return self.get_show_photo( row[13], @@ -684,7 +841,7 @@ class PseudoDailyScheduleController(): increase_var += 1 if len(datalist) >= increase_var: - print("+++++ In 'manually_get_now_playing_bg_image()'. " + print("INFO: In 'manually_get_now_playing_bg_image()'. " "Reached the end of the schedule. No bgImages found.") return None @@ -695,11 +852,12 @@ class PseudoDailyScheduleController(): increase_var = 0 for row in datalist: - #print row[8] - #print row[9] """if str(row[11]) == "Commercials" and self.DEBUG == False: continue""" - timeBStart = datetime.strptime(row[8], '%I:%M:%S %p') + try: + timeBStart = datetime.strptime(row[8], '%I:%M:%S %p') + except: + timeBStart = datetime.strptime(row[8], '%H:%M:%S') timeBStart = timeBStart.replace(year=1900, month=1, day=1) try: timeBEnd = datetime.strptime(row[9], '%Y-%m-%d %H:%M:%S.%f') @@ -707,13 +865,6 @@ class PseudoDailyScheduleController(): except: timeBEnd = datetime.strptime(row[9], '%Y-%m-%d %H:%M:%S') timeBEnd = timeBEnd.replace(day=1) - - #print ((currentTime - timeBStart).total_seconds() >= 0 and \ - # (timeBEnd - currentTime).total_seconds() >= 0) - - #print currentTime.minute - #print timeBStart.minute - if ((currentTime - timeBStart).total_seconds() >= 0 and \ (timeBEnd - currentTime).total_seconds() >= 0) or \ ((timeBStart - timeBEnd).total_seconds() >= 0 and \ @@ -722,7 +873,7 @@ class PseudoDailyScheduleController(): ((currentTime-timeBStart).total_seconds() >= 0 and \ (midnight-currentTime).total_seconds() >= 0))): - print("+++++ Made the conditional & found item: {}".format(row[6])) + print("NOTICE: Made the conditional & found item: {}".format(row[6])) return row[6] + " - " + row[3] if row[11] == "TV Shows" else row[3] @@ -733,13 +884,13 @@ class PseudoDailyScheduleController(): increase_var += 1 if len(datalist) >= increase_var: - print("+++++ In 'manually_get_now_playing_title()'. " + print("NOTICE: In 'manually_get_now_playing_title()'. " "Reached the end of the schedule. No bgImages found.") return '' def make_xml_schedule(self, datalist): - print("##### ", "Writing XML / HTML to file.") + print("NOTICE: ", "Writing XML / HTML to file.") now = datetime.now() now = now.replace(year=1900, month=1, day=1) @@ -747,7 +898,7 @@ class PseudoDailyScheduleController(): itemTitle = self.manually_get_now_playing_title(now, datalist) - print("+++++ The path to the bgImage: {}".format(bgImage)) + print("NOTICE: The path to the bgImage: {}".format(bgImage)) self.write_refresh_bool_to_file() self.write_schedule_to_file(self.get_html_from_daily_schedule(now, bgImage, datalist, itemTitle)) diff --git a/channel-dir/report_MediaFolders.py b/channel-dir/report_MediaFolders.py index 9393f83..162fcd4 100644 --- a/channel-dir/report_MediaFolders.py +++ b/channel-dir/report_MediaFolders.py @@ -11,19 +11,19 @@ from pseudo_config import plexLibraries as local_commercials try: commercials = local_commercials["Commercials"] except KeyError: - print("##### Commercials not defined on this channel, setting to blank") + print("ERROR: Commercials not defined on this channel, setting to blank") commercials = "" try: movies = local_commercials["Movies"] except KeyError: - print("##### Movies not defined on this channel, setting to blank") + print("ERROR: Movies not defined on this channel, setting to blank") movies = "" try: tvs = local_commercials["TV Shows"] except KeyError: - print("##### TV Shows not defined on this channel, setting to blank") + print("ERROR: TV Shows not defined on this channel, setting to blank") tvs = "" commercials_file = open('Commercial_Libraries.txt','w') movies_file = open('Movie_Libraries.txt','w') diff --git a/main-dir/Global_DatabaseUpdate.py b/main-dir/Global_DatabaseUpdate.py index 7845a97..56e7c3b 100644 --- a/main-dir/Global_DatabaseUpdate.py +++ b/main-dir/Global_DatabaseUpdate.py @@ -36,16 +36,22 @@ else: update_flags+=' -uc' -update_call = "sudo python PseudoChannel.py %s" % update_flags +update_call = "python PseudoChannel.py %s" % update_flags # Step ONE: Global database update -print("+++++ Doing global update from PLEX: %s" % update_flags) +print("NOTICE: Doing global update from PLEX: %s" % update_flags) try: - os.rename("pseudo-channel.db", "pseudo-channel.bak") + os.rename("pseudo-channel.db", "pseudo-channel.bak") except OSError: - pass -os.system(update_call) + pass +try: + os.system(update_call) +except: + print("ERROR: Global Update Failed!") + os.remove("pseudo-channel.db") + os.rename("pseudo-channel.bak", "pseudo-channel.db") + sys.exit() base_dirA = os.path.dirname(os.path.abspath(__file__)) @@ -57,12 +63,13 @@ for channel_dir in channel_dirs: # Step TWO: Go to each folder, export the following information # - Show title, lastEpisodeTitle # - Movie title, lastPlayedDate + # - Current channel schedule that the daily schedule is sourced from # - Daily schedule currently being executed os.chdir(channel_dir) channel_dirA = os.path.dirname(os.path.abspath(__file__)) db_path = os.path.join(channel_dirA, "pseudo-channel.db") - print("+++++ Importing from " + db_path) + print("NOTICE: Importing from " + db_path) try: conn = sqlite3.connect(db_path) @@ -73,7 +80,7 @@ for channel_dir in channel_dirs: lastEpisode_export = list(lastEpisode_export) lastMovie_export = table.execute('SELECT lastPlayedDate,title FROM movies').fetchall() lastMovie_export = list(lastMovie_export) - + schedule = table.execute('SELECT * FROM schedule').fetchall() daily_schedule = table.execute('SELECT * FROM daily_schedule').fetchall() @@ -81,19 +88,20 @@ for channel_dir in channel_dirs: conn.commit() conn.close() except: - print("+++++ Database experiencing errors or hasn't been formed yet; creating fresh one") + print("NOTICE: Database experiencing errors or hasn't been formed yet; creating fresh one") lastEpisode_export = [] lastMovie_export = [] - daily_schedule = [] + schedule = [] + daily_schedule = [] # Step THREE: Delete the previous database, replace with the recently created global one - print("+++++ Copying global update to " + db_path) + print("NOTICE: Copying global update to " + db_path) copy2('../pseudo-channel.db','.') # Step FOUR: Import the previous information we exported previously - print("+++++ Exporting to " + db_path) + print("NOTICE: Exporting to " + db_path) conn = sqlite3.connect(db_path) table = conn.cursor() @@ -104,7 +112,10 @@ for channel_dir in channel_dirs: for i in range(0,len(lastMovie_export)): sql = "UPDATE movies SET lastPlayedDate=? WHERE title=?" table.execute(sql,lastMovie_export[i]) - + for i in range(0,len(schedule)): + sql = "INSERT INTO schedule(id,unix,mediaID,title,duration,startTime,endTime,dayOfWeek,startTimeUnix,section,strictTime,timeShift,overlapMax,xtra) \ + VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)" + table.execute(sql,schedule[i]) for i in range(0,len(daily_schedule)): sql = "INSERT INTO daily_schedule(id,unix,mediaID,title,episodeNumber,seasonNumber,showTitle,duration,startTime,endTime,dayOfWeek,sectionType,plexMediaID,customSectionName) \ VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)" @@ -112,8 +123,8 @@ for channel_dir in channel_dirs: # Step FIVE: Remove any media not in the directories set of commerical archives - print("+++++ Trimming database at " + db_path) - os.system('sudo python report_MediaFolders.py') + print("NOTICE: Trimming database at " + db_path) + os.system('python report_MediaFolders.py') local_commercials = open('Commercial_Libraries.txt').read().splitlines() local_movies = open('Movie_Libraries.txt').read().splitlines() local_tvs = open('TV_Libraries.txt').read().splitlines() @@ -144,6 +155,6 @@ for channel_dir in channel_dirs: os.chdir('..') - print("+++++ " + db_path + " complete! Going to next file") + print("NOTICE: " + db_path + " complete! Going to next file") -print("+++++ Global update COMPLETE") +print("NOTICE: Global update COMPLETE") diff --git a/main-dir/controls.py b/main-dir/controls.py new file mode 100644 index 0000000..57c278f --- /dev/null +++ b/main-dir/controls.py @@ -0,0 +1,224 @@ +#!/usr/bin/env python +import os +import sys +import glob +import time +import argparse +import subprocess +import pseudo_config as config +import signal + +OUTPUT_PID_FILE='running.pid' +OUTPUT_PID_PATH='.' +OUTPUT_LAST_FILE='last.info' + +def execfile(filename, globals=None, locals=None): + if globals is None: + globals = sys._getframe(1).f_globals + if locals is None: + locals = sys._getframe(1).f_locals + with open(filename, "r") as fh: + exec(fh.read()+"\n", globals, locals) + +def get_channels(channelsDir='.'): + #get list of available channels and arrange in numerical order + dirList = sorted(next(os.walk('.'))[1]) + chanList = [] + channelsList = [] + for dir in dirList: + if "pseudo-channel_" in dir: + chanList.append(dir) + for chan in chanList: + channelNumber = chan.split('_') + channelNumber = channelNumber[1] + channelsList.append(channelNumber) + return channelsList + +def get_playing(): + #check for pid file, if present, identify which channel is running + pids = "**/"+OUTPUT_PID_FILE + for runningPID in glob.glob(pids): + with open(runningPID) as f: + pid = f.readline() + playing = { runningPID : pid } + return playing + +def get_last(): + #check for last file, if present identify which channel is 'last' + lastFile = '**/'+OUTPUT_LAST_FILE + for lasts in glob.glob(lastFile): + pathtofile = lasts.split('/') + lastDir = pathtofile[-2] + last = lastDir.split('_') + return last[1] + +def start_channel(channel): + #execute PseudoChannel.py -r in specified channel\ + os.chdir('./pseudo-channel_'+channel) + process = subprocess.Popen(["python", "-u", "PseudoChannel.py", "-r"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) + #create pid file and write pid into file + print("NOTICE: Channel Process Running at "+str(process.pid)) + p = open(OUTPUT_PID_FILE, 'w+') + p.write(str(process.pid)) + p.close() + while True: + output = process.stdout.readline() + if process.poll() is not None: + break + if output: + print(output.strip()) + rc = process.poll() + +def stop_channel(channel, pid): + #kill pid process + os.kill(int(pid), signal.SIGTERM) + print(pid+" PID TERMINATED") + #delete pid file + os.remove(channel) + print(OUTPUT_PID_FILE+" DELETED") + #write last.info file + lastFile = channel.replace(OUTPUT_PID_FILE, OUTPUT_LAST_FILE) + i = open('./'+lastFile, 'w') + i.write(str(time.time())) + i.close() + print(OUTPUT_LAST_FILE+" CREATED") + +def stop_all_boxes(): + #get list of boxes + #get list of channels in box + #stop all channels in box + print("stop_all_boxes FUNCTION NOT YET IMPLEMENTED") + +def channel_up(channelsList): + #play next channel in numerical order + try: + getPlaying = get_playing() + for channelPlaying, pid in getPlaying.items(): + channelNumber = channelPlaying.replace('pseudo-channel_','') + channelNumber = channelNumber.replace('/'+OUTPUT_PID_FILE,'') + print("NOTICE: Stopping Channel "+str(channelNumber)+" at PID "+str(pid)) + stop_channel(channelPlaying, pid) + except: + print("NOTICE: Channel not playing or error") + channelPlaying = get_last() + isnext = 0 + next_channel = channelsList[0] + for channel in channelsList: + if isnext == 1: + next_channel = channel + if channel == channelNumber: + isnext = 1 + print("NOTICE: Starting Channel "+str(next_channel)) + start_channel(next_channel) + +def channel_down(channelsList): + #play previous channel in numerical order + try: + getPlaying = get_playing() + for channelPlaying, pid in getPlaying.items(): + channelNumber = channelPlaying.replace('pseudo-channel_','') + channelNumber = channelNumber.replace('/'+OUTPUT_PID_FILE,'') + print("NOTICE: Stopping Channel "+str(channelNumber)+" at PID "+str(pid)) + stop_channel(channelPlaying, pid) + except: + print("NOTICE: Channel not playing or error") + channelPlaying = get_last() + isnext = 0 + channelsList.reverse() + next_channel = channelsList[0] + for channel in channelsList: + if isnext == 1: + next_channel = channel + if channel == channelNumber: + isnext = 1 + print("NOTICE: Starting Channel "+str(next_channel)) + start_channel(next_channel) + +def generate_daily_schedules(channelsList): + #execute PseudoChannel.py -g in specified channel\ + for channel in channelsList: + os.chdir('./pseudo-channel_'+channel) + print("GENERATING SCHEDULE FOR CHANNEL "+channel) + process = subprocess.Popen(["python", "-u", "PseudoChannel.py", "-g"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) + while True: + output = process.stdout.readline() + if process.poll() is not None: + break + if output: + print(output.strip()) + rc = process.poll() + os.chdir('../') + +parser = argparse.ArgumentParser(description='Pseudo Channel Controls') +channelsList = get_channels() +#channel, pid = playing.popitem() +parser.add_argument('-c', '--channel', + choices = channelsList, + help='Start Specified Channel') +parser.add_argument('-s', '--stop', + action='store_true', + help='Stop Active Channel') +parser.add_argument('-sb', '--stopallboxes', + action='store_true', + help='Stop All Clients') +parser.add_argument('-up', '--channelup', + action='store_true', + help='Channel Up') +parser.add_argument('-dn', '--channeldown', + action='store_true', + help='Channel Down') +parser.add_argument('-l', '--last', + action='store_true', + help='Last Channel') +parser.add_argument('-r', '--restart', + action='store_true', + help='Restart Playing Channel') +parser.add_argument('-g', '--generateschedules', + action='store_true', + help='Generate Daily Schedules for All Channels') + +args = parser.parse_args() + +if args.channel: + print("STARTING CHANNEL "+args.channel) + start_channel(args.channel) +if args.stop: + playing = get_playing() + for channel, pid in playing.items(): + stop_channel(channel, pid) + print("STOPPING ACTIVE CHANNEL AT PID# "+pid) +if args.stopallboxes: + print("STOPPING ALL BOXES") + stop_all_boxes() +if args.channelup: + print("CHANNEL UP") + channel_up(channelsList) +if args.channeldown: + print("CHANNEL DOWN") + channel_down(channelsList) +if args.last: + print("LAST CHANNEL") + last = get_last() + start_channel(last) +if args.restart: + playing = get_playing() + for channel, pid in playing.items(): + stop_channel(channel, pid) + print("STOPPING ACTIVE CHANNEL AT PID "+pid) + last = get_last() + print("RESTARTING CHANNEL "+last) + start_channel(last) +if args.generateschedules: + try: + playing = get_playing() + for channel, pid in playing.items(): + stop_channel(channel, pid) + print("STOPPING ACTIVE CHANNEL AT PID "+pid) + last = get_last() + print("GENERATING DAILY SCHEDULES") + generate_daily_schedules(channelsList) + print("RESTARTING CHANNEL "+last) + start_channel(last) + except: + print("GENERATING DAILY SCHEDULES") + generate_daily_schedules(channelsList) \ No newline at end of file diff --git a/main-dir/setup.py b/main-dir/setup.py new file mode 100644 index 0000000..64a9685 --- /dev/null +++ b/main-dir/setup.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python +import os +import sys +import glob +import time +import argparse +import subprocess +import pseudo_config as config +import signal + +def execfile(filename, globals=None, locals=None): + if globals is None: + globals = sys._getframe(1).f_globals + if locals is None: + locals = sys._getframe(1).f_locals + with open(filename, "r") as fh: + exec(fh.read()+"\n", globals, locals) + +def get_channels(channelsDir='.'): + #get list of available channels and arrange in numerical order + dirList = sorted(next(os.walk('.'))[1]) + chanList = ['all',] + channelsList = [] + for dir in dirList: + if "pseudo-channel_" in dir: + chanList.append(dir) + for chan in chanList: + channelNumber = chan.split('_') + channelNumber = channelNumber[1] + channelsList.append(channelNumber) + return channelsList + +def ps_install(): + #download and install pseudo channel from git + +def copyconfig(channel=None): + #copy config file to one or more channels + +def copy_tv(client): + #make symlinked copy of pseudo channel files to run on another client + +def ps_update(branch='main'): + #download and copy updates from git to all branches and boxes + +def web_setup(branch='main'): + #set up the web interface and api + +parser = argparse.ArgumentParser(description='Pseudo Channel Controls') +channelsList = get_channels() +parser.add_argument('-i', '--install', + action='store_true', + help='Install Pseudo Channel from git') +parser.add_argument('-cc', '--copyconfig', + choices = channelsList, + help='Copy root config file to one or all channels') +parser.add_argument('-tv', '--tv', + action = 'store', + help='Add another TV with linked database') +parser.add_argument('-u', '--update', + choices = ['main','dev'], + help='Update Pseudo Channel to the Latest Version') +parser.add_argument('-w', '--web', + choices = ['main','dev'], + help='Install and Set Up Web Interface and API') + +args = parser.parse_args() + +if args.install: + print("DOWNLOADING AND INSTALLING PSEUDO CHANNEL FROM GIT") + ps_install() +if args.copyconfig: + if args.copyconfig != 'all': + print("COPYING CONFIG TO CHANNEL "+str(args.copyconfig)) + copyconfig(args.copyconfig) + else: + print("COPYING CONFIG TO ALL CHANNELS") + copyconfig() +if args.tv: + print("SETTING UP PSUEDO CHANNEL FOR CLIENT "+str(args.tv)) + copy_tv(args.tv) +if args.update: + print("UPDATING PSEUDO CHANNEL FROM GIT BRANCH "+str(args.update)) + ps_update(args.update) +if args.web: + print("SETTING UP PSEUDO CHANNEL WEB INTERFACE AND API FROM GIT BRANCH "+str(args.web)) + web_setup(args.web) \ No newline at end of file