diff --git a/both-dir/PseudoChannel.py b/both-dir/PseudoChannel.py index 660bf53..1498340 100644 --- a/both-dir/PseudoChannel.py +++ b/both-dir/PseudoChannel.py @@ -144,8 +144,8 @@ class PseudoChannel(): ) #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: duration = episode.duration if duration: @@ -240,8 +240,8 @@ class PseudoChannel(): ) #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: duration = episode.duration if duration: @@ -312,7 +312,7 @@ class PseudoChannel(): "everyday" ] section_dict = { - "TV Shows" : ["series", "shows", "tv", "episodes", "tv shows", "show"], + "TV Shows" : ["series", "shows", "tv", "episodes", "tv shows", "show","random"], "Movies" : ["movie", "movies", "films", "film"], "Videos" : ["video", "videos", "vid"], "Music" : ["music", "songs", "song", "tune", "tunes"] @@ -328,6 +328,10 @@ 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": + mediaID_place=9999 + else: + mediaID_place=0 day_of_week = child.tag 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' @@ -348,7 +352,7 @@ class PseudoChannel(): print "Adding: ", time.tag, section, time.text, time.attrib['title'] self.db.add_schedule_to_db( - 0, # mediaID + mediaID_place, # mediaID title, # title 0, # duration natural_start_time, # startTime @@ -540,6 +544,8 @@ class PseudoChannel(): if section == "TV Shows": if str(entry[3]).lower() == "random": next_episode = self.db.get_random_episode() + elif entry[2] == 9999: + next_episode = self.db.get_random_episode_alternate(entry[3]) else: next_episode = self.db.get_next_episode(entry[3]) if next_episode != None: @@ -713,7 +719,8 @@ class PseudoChannel(): if self.USING_COMMERCIAL_INJECTION: list_of_commercials = self.commercials.get_commercials_to_place_between_media( previous_episode, - entry + entry, + entry.is_strict_time.lower() ) for commercial in list_of_commercials: self.db.add_media_to_daily_schedule(commercial) @@ -740,7 +747,8 @@ class PseudoChannel(): if self.USING_COMMERCIAL_INJECTION: list_of_commercials = self.commercials.get_commercials_to_place_between_media( previous_episode, - entry + entry, + entry.is_strict_time.lower() ) for commercial in list_of_commercials: self.db.add_media_to_daily_schedule(commercial) @@ -1088,16 +1096,16 @@ if __name__ == '__main__': 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 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." diff --git a/both-dir/src/PseudoChannelCommercial.py b/both-dir/src/PseudoChannelCommercial.py index ab2c623..77705d2 100644 --- a/both-dir/src/PseudoChannelCommercial.py +++ b/both-dir/src/PseudoChannelCommercial.py @@ -1,135 +1,159 @@ -"""Commercial Functionality -""" -from random import shuffle -import random -import copy -from datetime import datetime -from datetime import timedelta -from src import Commercial - -class PseudoChannelCommercial(): - - MIN_DURATION_FOR_COMMERCIAL = 10 #seconds - COMMERCIAL_PADDING_IN_SECONDS = 0 - daily_schedule = [] - - def __init__(self, commercials, commercialPadding, useDirtyGapFix): - - self.commercials = commercials - self.COMMERCIAL_PADDING_IN_SECONDS = commercialPadding - self.USE_DIRTY_GAP_FIX = useDirtyGapFix - - def get_random_commercial(self): - - random_commercial = random.choice(self.commercials) -# random_commercial_dur_seconds = (int(random_commercial[4])/1000)%60 - random_commercial_dur_seconds = (int(random_commercial[4])/1000) - while random_commercial_dur_seconds < self.MIN_DURATION_FOR_COMMERCIAL: - random_commercial = random.choice(self.commercials) - random_commercial_dur_seconds = (int(random_commercial[4])/1000) -# random_commercial_dur_seconds = (int(random_commercial[4])/1000)%60 - return random_commercial - - def timedelta_milliseconds(self, td): - - return td.days*86400000 + td.seconds*1000 + td.microseconds/1000 - - def pad_the_commercial_dur(self, commercial): - - commercial_as_list = list(commercial) - commercial_as_list[4] = int(commercial_as_list[4]) + (self.COMMERCIAL_PADDING_IN_SECONDS * 1000) - commercial = tuple(commercial_as_list) - return commercial - - def get_commercials_to_place_between_media(self, last_ep, now_ep): - - 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) - count = 0 - commercial_list = [] - commercial_dur_sum = 0 - 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 - while curr_item_start_time > new_commercial_start_time: - random_commercial_without_pad = self.get_random_commercial() - """ - Padding the duration of commercials as per user specified padding. - """ - 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_end_time = new_commercial_start_time + \ - timedelta(milliseconds=int(new_commercial_milli)) - else: - new_commercial_start_time = prev_item_end_time - 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') - new_commercial = Commercial( - "Commercials", - random_commercial[3], - formatted_time_for_new_commercial, # natural_start_time - new_commercial_end_time, - random_commercial[4], - "everyday", # day_of_week - "true", # is_strict_time - "1", # time_shift - "0", # overlap_max - "", # plex_media_id - random_commercial[6], # custom lib name - ) - last_commercial = new_commercial - if new_commercial_end_time > curr_item_start_time: - - # Fill up gap with commercials even if the last commercial gets cutoff - if self.USE_DIRTY_GAP_FIX: - - commercial_list.append(new_commercial) - # Find the best fitting final commercial and break - 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') - if int(self.commercials[0][4]) > self.timedelta_milliseconds(gapToFill): - - break - else: - - print "===== Finding correct FINAL commercial to add to List." - - last_comm = None - for comm in self.commercials: - - if int(comm[4]) >= self.timedelta_milliseconds(gapToFill) and last_comm != None: - - 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') - - final_commercial_end_time = datetime.strptime(new_commercial.natural_start_time, '%I:%M:%S %p') + \ - timedelta(milliseconds=int(random_final_comm[4])) - - final_commercial = Commercial( - "Commercials", - random_final_comm[3], - formatted_time_for_final_commercial, # natural_start_time - final_commercial_end_time, - random_final_comm[4], - "everyday", # day_of_week - "true", # is_strict_time - "1", # time_shift - "0", # overlap_max - "", # plex_media_id - random_final_comm[6], # custom lib name - ) - commercial_list.append(final_commercial) - break - last_comm = comm - break - commercial_list.append(new_commercial) +"""Commercial Functionality +""" +from random import shuffle +import random +import copy +from datetime import datetime +from datetime import timedelta +from src import Commercial + +class PseudoChannelCommercial(): + + MIN_DURATION_FOR_COMMERCIAL = 10 #seconds + COMMERCIAL_PADDING_IN_SECONDS = 0 + daily_schedule = [] + + def __init__(self, commercials, commercialPadding, useDirtyGapFix): + + self.commercials = commercials + self.COMMERCIAL_PADDING_IN_SECONDS = commercialPadding + self.USE_DIRTY_GAP_FIX = useDirtyGapFix + + def get_random_commercial(self): + + random_commercial = random.choice(self.commercials) +# random_commercial_dur_seconds = (int(random_commercial[4])/1000)%60 + random_commercial_dur_seconds = (int(random_commercial[4])/1000) + while random_commercial_dur_seconds < self.MIN_DURATION_FOR_COMMERCIAL: + random_commercial = random.choice(self.commercials) + random_commercial_dur_seconds = (int(random_commercial[4])/1000) +# random_commercial_dur_seconds = (int(random_commercial[4])/1000)%60 + return random_commercial + + def timedelta_milliseconds(self, td): + + return td.days*86400000 + td.seconds*1000 + td.microseconds/1000 + + def pad_the_commercial_dur(self, commercial): + + commercial_as_list = list(commercial) + commercial_as_list[4] = int(commercial_as_list[4]) + (self.COMMERCIAL_PADDING_IN_SECONDS * 1000) + commercial = tuple(commercial_as_list) + return commercial + + def get_commercials_to_place_between_media(self, last_ep, now_ep, strict_time): + + 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) + # 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) + + 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": + # 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" + 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 "curr_item_start_time: %s" % curr_item_start_time + print "time_diff: %s" % time_diff + print "##############################################" + + count = 0 + commercial_list = [] + commercial_dur_sum = 0 + 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 + while curr_item_start_time > new_commercial_start_time: + random_commercial_without_pad = self.get_random_commercial() + """ + Padding the duration of commercials as per user specified padding. + """ + 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_end_time = new_commercial_start_time + \ + timedelta(milliseconds=int(new_commercial_milli)) + else: + new_commercial_start_time = prev_item_end_time + 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') + new_commercial = Commercial( + "Commercials", + random_commercial[3], + formatted_time_for_new_commercial, # natural_start_time + new_commercial_end_time, + random_commercial[4], + "everyday", # day_of_week + "true", # is_strict_time + "1", # time_shift + "0", # overlap_max + "", # plex_media_id + random_commercial[6], # custom lib name + ) + last_commercial = new_commercial + if new_commercial_end_time > curr_item_start_time: + + # Fill up gap with commercials even if the last commercial gets cutoff + if self.USE_DIRTY_GAP_FIX: + + commercial_list.append(new_commercial) + # Find the best fitting final commercial and break + 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') + if int(self.commercials[0][4]) > self.timedelta_milliseconds(gapToFill): + + break + else: + + print "===== Finding correct FINAL commercial to add to List." + + last_comm = None + for comm in self.commercials: + + if int(comm[4]) >= self.timedelta_milliseconds(gapToFill) and last_comm != None: + + 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') + + final_commercial_end_time = datetime.strptime(new_commercial.natural_start_time, '%I:%M:%S %p') + \ + timedelta(milliseconds=int(random_final_comm[4])) + + final_commercial = Commercial( + "Commercials", + random_final_comm[3], + formatted_time_for_final_commercial, # natural_start_time + final_commercial_end_time, + random_final_comm[4], + "everyday", # day_of_week + "true", # is_strict_time + "1", # time_shift + "0", # overlap_max + "", # plex_media_id + random_final_comm[6], # custom lib name + ) + commercial_list.append(final_commercial) + break + last_comm = comm + break + commercial_list.append(new_commercial) return commercial_list \ No newline at end of file diff --git a/both-dir/src/PseudoChannelDatabase.py b/both-dir/src/PseudoChannelDatabase.py index 88c990a..4371306 100644 --- a/both-dir/src/PseudoChannelDatabase.py +++ b/both-dir/src/PseudoChannelDatabase.py @@ -513,6 +513,14 @@ 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() + + ####mutto233 made this one#### + def get_random_episode_alternate(self,series): + + sql = "SELECT * FROM episodes WHERE (showTitle LIKE ? AND id IN (SELECT id FROM episodes ORDER BY RANDOM() LIMIT 1))" + self.cursor.execute(sql, (series, )) + return self.cursor.fetchone() + ####mutto233 made this one#### def get_random_movie(self): diff --git a/both-dir/src/PseudoDailyScheduleController.py b/both-dir/src/PseudoDailyScheduleController.py index 26ffab2..b10c5bf 100644 --- a/both-dir/src/PseudoDailyScheduleController.py +++ b/both-dir/src/PseudoDailyScheduleController.py @@ -1,647 +1,734 @@ -#!/usr/bin/env python - -import os, sys -import socket -import logging -import logging.handlers -from datetime import datetime -import sqlite3 -import thread,SocketServer,SimpleHTTPServer -from plexapi.server import PlexServer -from yattag import Doc -from yattag import indent - -class PseudoDailyScheduleController(): - - def __init__(self, - server, - token, - clients, - controllerServerPath = '', - controllerServerPort = '8000', - debugMode = False, - htmlPseudoTitle = "Daily PseudoChannel" - ): - - self.PLEX = PlexServer(server, token) - self.BASE_URL = server - self.TOKEN = token - self.PLEX_CLIENTS = clients - self.CONTROLLER_SERVER_PATH = controllerServerPath - self.CONTROLLER_SERVER_PORT = controllerServerPort if controllerServerPort != '' else '80' - self.DEBUG = debugMode - self.webserverStarted = False - self.HTML_PSEUDO_TITLE = htmlPseudoTitle - try: - self.my_logger = logging.getLogger('MyLogger') - self.my_logger.setLevel(logging.DEBUG) - self.handler = logging.handlers.SysLogHandler(address = '/dev/log') - self.my_logger.addHandler(self.handler) - except: - pass - - ''' - * - * Get the full image url (including plex token) from the local db. - * @param seriesTitle: case-unsensitive string of the series title - * @return string: full path of to the show image - * - ''' - def get_show_photo(self, section, title): - - backgroundImagePath = None - backgroundImgURL = '' - try: - backgroundImagePath = self.PLEX.library.section(section).get(title) - except: - return backgroundImgURL - if backgroundImagePath != None and isinstance(backgroundImagePath.art, str): - backgroundImgURL = self.BASE_URL+backgroundImagePath.art+"?X-Plex-Token="+self.TOKEN - return backgroundImgURL - - def start_server(self): - - if self.webserverStarted == False and self.CONTROLLER_SERVER_PATH != '': - """Changing dir to the schedules dir.""" - 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(SimpleHTTPServer.SimpleHTTPRequestHandler): - - def log_message(self, format, *args): - return - - global httpd - try: - #print "Starting webserver at port: ", PORT - # 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 - httpd = ReusableTCPServer(("0.0.0.0", PORT),MyHandler) - # thread this mofo - thread.start_new_thread(httpd.serve_forever,()) - # handle keyboard interrupts - except KeyboardInterrupt: - core.print_info("Exiting the SET web server...") - httpd.socket.close() - except socket.error, exc: - print "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() - time = now.strftime("%B %d, %Y") - doc, tag, text, line = Doc( - - ).ttl() - doc.asis('') - with tag('schedule', currently_playing_bg_image=bgImageURL if bgImageURL != None else ''): - 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', - ('data-key', str(row[12])), - ('data-current', 'false'), - ('data-type', str(row[11])), - ('data-title', str(row[3])), - ('data-start-time', str(row[8])), - ): - text(row[8]) - elif currentTime.hour == timeB.hour and currentTime.minute == timeB.minute: - with tag('time', - ('data-key', str(row[12])), - ('data-current', 'true'), - ('data-type', str(row[11])), - ('data-title', str(row[3])), - ('data-start-time', str(row[8])), - ): - text(row[8]) - else: - with tag('time', - ('data-key', str(row[12])), - ('data-current', 'false'), - ('data-type', str(row[11])), - ('data-title', str(row[3])), - ('data-start-time', str(row[8])), - ): - text(row[8]) - return indent(doc.getvalue()) - - ''' - * - * Get the generated html for the .html file that is the schedule. - * ...This is used whenever a show starts or stops in order to add and remove various styles. - * @param currentTime: datetime object - * @param bgImageURL: str of the image used for the background - * @return string: the generated html content - * - ''' - def get_html_from_daily_schedule(self, currentTime, bgImageURL, datalist, nowPlayingTitle): - - now = datetime.now() - time = now.strftime("%B %d, %Y") - doc, tag, text, line = Doc( - - ).ttl() - doc.asis('') - with tag('html'): - with tag('head'): - with tag('title'): - text(time + " - Daily Pseudo Schedule") - doc.asis('') - doc.asis('') - doc.asis(""" - - """) - if bgImageURL != None: - doc.asis('') - with tag('body'): - with tag('div', klass='container mt-3'): - with tag('div', klass='row make-white'): - with tag('div'): - with tag('div'): - line('h1', self.HTML_PSEUDO_TITLE, klass='col-12 pl-0') - with tag('div'): - line('h3', time, klass='col-12 pl-1') - line('h3', - "Now Playing: "+nowPlayingTitle, - klass='col-12 pl-1', - style="color:red;") - with tag('table', klass='col-12 table table-bordered table-hover'): - with tag('thead', klass='table-info'): - with tag('tr'): - with tag('th'): - text('#') - with tag('th'): - text('Type') - with tag('th'): - text('Series') - with tag('th'): - text('Title') - with tag('th'): - text('Start Time') - numberIncrease = 0 - for row in datalist: - if str(row[11]) == "Commercials" and self.DEBUG == False: - continue - numberIncrease += 1 - with tag('tbody'): - if currentTime != None: - currentTime = currentTime.replace(year=1900, month=1, day=1) - timeBStart = datetime.strptime(row[8], '%I:%M:%S %p') - timeBStart = timeBStart.replace(year=1900, month=1, day=1) - try: - timeBEnd = datetime.strptime(row[9], '%Y-%m-%d %H:%M:%S.%f') - except: - timeBEnd = datetime.strptime(row[9], '%Y-%m-%d %H:%M:%S') - #print timeBStart - if currentTime == None: - with tag('tr'): - with tag('th', scope='row'): - text(numberIncrease) - with tag('td'): - text(row[11]) - with tag('td'): - text(row[6]) - with tag('td'): - text(row[3]) - with tag('td'): - text(row[8]) - elif (currentTime - timeBStart).total_seconds() >= 0 and \ - (timeBEnd - currentTime).total_seconds() >= 0: - - #if self.DEBUG: - print "+++++ Currently Playing:", row[3] - - with tag('tr', klass='bg-info'): - with tag('th', scope='row'): - text(numberIncrease) - with tag('td'): - text(row[11]) - with tag('td'): - text(row[6]) - with tag('td'): - text(row[3]) - with tag('td'): - text(row[8]) - else: - with tag('tr'): - with tag('th', scope='row'): - text(numberIncrease) - with tag('td'): - text(row[11]) - with tag('td'): - text(row[6]) - with tag('td'): - text(row[3]) - with tag('td'): - text(row[8]) - return indent(doc.getvalue()) - - ''' - * - * Create 'schedules' dir & write the generated html to .html file. - * @param data: html string - * @return null - * - ''' - def write_schedule_to_file(self, data): - - now = datetime.now() - fileName = "index.html" - writepath = './' if os.path.basename(os.getcwd()) == "schedules" else "./schedules/" - if not os.path.exists(writepath): - os.makedirs(writepath) - if os.path.exists(writepath+fileName): - os.remove(writepath+fileName) - mode = 'a' if os.path.exists(writepath) else 'w' - with open(writepath+fileName, mode) as f: - f.write(data) - self.start_server() - - ''' - * - * Create 'schedules' dir & write the generated xml to .xml file. - * @param data: xml string - * @return null - * - ''' - def write_xml_to_file(self, data): - - now = datetime.now() - fileName = "pseudo_schedule.xml" - writepath = './' if os.path.basename(os.getcwd()) == "schedules" else "./schedules/" - if not os.path.exists(writepath): - os.makedirs(writepath) - if os.path.exists(writepath+fileName): - os.remove(writepath+fileName) - mode = 'a' if os.path.exists(writepath) else 'w' - with open(writepath+fileName, mode) as f: - f.write(data) - - ''' - * - * Write 0 or 1 to file for the ajax in the schedule.html to know when to refresh - * @param data: xml string - * @return null - * - ''' - def write_refresh_bool_to_file(self): - - fileName = "pseudo_refresh.txt" - writepath = './' if os.path.basename(os.getcwd()) == "schedules" else "./schedules/" - first_line = '' - if not os.path.exists(writepath): - os.makedirs(writepath) - if not os.path.exists(writepath+fileName): - file(writepath+fileName, 'w').close() - mode = 'r+' - with open(writepath+fileName, mode) as f: - f.seek(0) - first_line = f.read() - if self.DEBUG: - print "+++++ Html refresh flag: {}".format(first_line) - if first_line == '' or first_line == "0": - f.seek(0) - f.truncate() - f.write("1") - else: - f.seek(0) - f.truncate() - f.write("0") - - ''' - * - * Trigger "playMedia()" on the Python Plex API for specified media. - * @param mediaType: str: "TV Shows" - * @param mediaParentTitle: str: "Seinfeld" - * @param mediaTitle: str: "The Soup Nazi" - * @return null - * - ''' - def play_media(self, mediaType, mediaParentTitle, mediaTitle, offset, customSectionName): - - try: - if mediaType == "TV Shows": - print "Here, Trying to play custom type: ", customSectionName - mediaItems = self.PLEX.library.section(customSectionName).get(mediaParentTitle).episodes() - for item in mediaItems: - if item.title == mediaTitle: - for client in self.PLEX_CLIENTS: - clientItem = self.PLEX.client(client) - clientItem.playMedia(item, offset=offset) - break - elif mediaType == "Movies": - movie = self.PLEX.library.section(customSectionName).get(mediaTitle) - for client in self.PLEX_CLIENTS: - clientItem = self.PLEX.client(client) - clientItem.playMedia(movie, offset=offset) - elif mediaType == "Commercials": - movie = self.PLEX.library.section(customSectionName).get(mediaTitle) - 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." - except Exception as e: - print e.__doc__ - print e.message - print "##### There was an error trying to play the media." - pass - - def stop_media(self): - - try: - self.my_logger.debug('Trying to stop media.') - for client in self.PLEX_CLIENTS: - clientItem = self.PLEX.client(client) - clientItem.stop(mtype='video') - self.my_logger.debug('Done.') - except Exception as e: - self.my_logger.debug('stop_media - except.', e) - pass - ''' - * - * If tv_controller() does not find a "startTime" for scheduled media, search for an "endTime" match for now time. - * ...This is useful for clearing the generated html schedule when media ends and there is a gap before the next media. - * @param null - * @return null - * - ''' - def check_for_end_time(self, datalist): - - currentTime = datetime.now() - """c.execute("SELECT * FROM daily_schedule") - datalist = list(c.fetchall()) - """ - for row in datalist: - try: - endTime = datetime.strptime(row[9], '%Y-%m-%d %H:%M:%S.%f') - except ValueError: - endTime = datetime.strptime(row[9], '%Y-%m-%d %H:%M:%S') - if currentTime.hour == endTime.hour: - if currentTime.minute == endTime.minute: - if currentTime.second == endTime.second: - if self.DEBUG: - print("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() - break - - 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') - if self.DEBUG: - print str(row).encode('UTF-8') - timeB = datetime.strptime(row[8], '%I:%M:%S %p') - - print "Here, row[13]", row[13] - - self.play_media(row[11], row[6], row[3], offset, row[13]) - self.write_schedule_to_file( - self.get_html_from_daily_schedule( - timeB, - self.get_show_photo( - row[13], - row[6] if row[11] == "TV Shows" else row[3] - ), - datalist, - row[6] + " - " + row[3] if row[11] == "TV Shows" else row[3] - ) - ) - self.write_refresh_bool_to_file() - """Generate / write XML to file - """ - self.write_xml_to_file( - self.get_xml_from_daily_schedule( - timeB, - self.get_show_photo( - row[13], - row[6] if row[11] == "TV Shows" else row[3] - ), - datalist - ) - ) - try: - self.my_logger.debug('Trying to play: ' + row[3]) - except: - pass - - ''' - * - * Check DB / current time. If that matches a scheduled shows startTime then trigger play via Plex API - * @param null - * @return null - * - ''' - def tv_controller(self, datalist): - - datalistLengthMonitor = 0; - currentTime = datetime.now() - """c.execute("SELECT * FROM daily_schedule ORDER BY datetime(startTimeUnix) ASC") - datalist = list(c.fetchall())""" - try: - self.my_logger.debug('TV Controller') - except: - pass - for row in datalist: - timeB = datetime.strptime(row[8], '%I:%M:%S %p') - if currentTime.hour == timeB.hour: - if currentTime.minute == timeB.minute: - if currentTime.second == timeB.second: - print("Starting Media: " + row[3]) - print(row) - self.play_media(row[11], row[6], row[3], row[13]) - self.write_schedule_to_file( - self.get_html_from_daily_schedule( - timeB, - self.get_show_photo( - row[13], - row[6] if row[11] == "TV Shows" else row[3] - ), - datalist, - row[6] + " - " + row[3] if row[11] == "TV Shows" else row[3] - ) - ) - self.write_refresh_bool_to_file() - """Generate / write XML to file - """ - self.write_xml_to_file( - self.get_xml_from_daily_schedule( - timeB, - self.get_show_photo( - row[13], - row[6] if row[11] == "TV Shows" else row[3] - ), - datalist - ) - ) - try: - self.my_logger.debug('Trying to play: ' + row[3]) - except: - pass - break - datalistLengthMonitor += 1 - if datalistLengthMonitor >= len(datalist): - self.check_for_end_time(datalist) - - def manually_get_now_playing_bg_image(self, currentTime, datalist): - - 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') - timeBStart = timeBStart.replace(year=1900, month=1, day=1) - try: - timeBEnd = datetime.strptime(row[9], '%Y-%m-%d %H:%M:%S.%f') - except: - timeBEnd = datetime.strptime(row[9], '%Y-%m-%d %H:%M:%S') - - #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: - - print "+++++ Made the conditional & found item: {}".format(row[6]) - - return self.get_show_photo( - row[13], - row[6] if row[11] == "TV Shows" else row[3] - ) - - else: - - pass - - increase_var += 1 - - if len(datalist) >= increase_var: - print("+++++ In 'manually_get_now_playing_bg_image()'. " - "Reached the end of the schedule. No bgImages found.") - return None - - def manually_get_now_playing_title(self, currentTime, datalist): - - 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') - timeBStart = timeBStart.replace(year=1900, month=1, day=1) - try: - timeBEnd = datetime.strptime(row[9], '%Y-%m-%d %H:%M:%S.%f') - except: - timeBEnd = datetime.strptime(row[9], '%Y-%m-%d %H:%M:%S') - - #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 : - - print "+++++ Made the conditional & found item: {}".format(row[6]) - - return row[6] + " - " + row[3] if row[11] == "TV Shows" else row[3] - - else: - - pass - - increase_var += 1 - - if len(datalist) >= increase_var: - print("+++++ 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." - now = datetime.now() - now = now.replace(year=1900, month=1, day=1) - - bgImage = self.manually_get_now_playing_bg_image(now, datalist) - - itemTitle = self.manually_get_now_playing_title(now, datalist) - - print "+++++ 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)) +#!/usr/bin/env python + +import os, sys +import socket +import logging +import logging.handlers +from datetime import datetime +import sqlite3 +import thread,SocketServer,SimpleHTTPServer +from plexapi.server import PlexServer +from yattag import Doc +from yattag import indent +import pseudo_config as config + +class PseudoDailyScheduleController(): + + def __init__(self, + server, + token, + clients, + controllerServerPath = '', + controllerServerPort = '8000', + debugMode = False, + htmlPseudoTitle = "Daily PseudoChannel" + ): + + self.PLEX = PlexServer(server, token) + self.BASE_URL = server + self.TOKEN = token + self.PLEX_CLIENTS = clients + self.CONTROLLER_SERVER_PATH = controllerServerPath + self.CONTROLLER_SERVER_PORT = controllerServerPort if controllerServerPort != '' else '80' + self.DEBUG = debugMode + self.webserverStarted = False + self.HTML_PSEUDO_TITLE = htmlPseudoTitle + try: + self.my_logger = logging.getLogger('MyLogger') + self.my_logger.setLevel(logging.DEBUG) + self.handler = logging.handlers.SysLogHandler(address = '/dev/log') + self.my_logger.addHandler(self.handler) + except: + pass + + ''' + * + * Get the full image url (including plex token) from the local db. + * @param seriesTitle: case-unsensitive string of the series title + * @return string: full path of to the show image + * + ''' + def get_show_photo(self, section, showtitle, durationAmount): + + backgroundImagePath = None + backgroundImgURL = '' + # 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: + return backgroundImgURL + + if backgroundImagePath == None: + # We will try the old way, for the sake of TV Shows + try: + backgroundImagePath = self.PLEX.library.section(section).get(showtitle) + except: + return backgroundImgURL + + if backgroundImagePath != None and isinstance(backgroundImagePath.art, str): + backgroundImgURL = self.BASE_URL+backgroundImagePath.art+"?X-Plex-Token="+self.TOKEN + return backgroundImgURL + + def start_server(self): + + if self.webserverStarted == False and self.CONTROLLER_SERVER_PATH != '': + """Changing dir to the schedules dir.""" + 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(SimpleHTTPServer.SimpleHTTPRequestHandler): + + def log_message(self, format, *args): + return + + global httpd + try: + #print "Starting webserver at port: ", PORT + # 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 + httpd = ReusableTCPServer(("0.0.0.0", PORT),MyHandler) + # thread this mofo + thread.start_new_thread(httpd.serve_forever,()) + # handle keyboard interrupts + except KeyboardInterrupt: + core.print_info("Exiting the SET web server...") + httpd.socket.close() + except socket.error, exc: + print "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() + time = now.strftime("%B %d, %Y") + doc, tag, text, line = Doc( + + ).ttl() + doc.asis('') + with tag('schedule', currently_playing_bg_image=bgImageURL if bgImageURL != None else ''): + 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', + ('data-key', str(row[12])), + ('data-current', 'false'), + ('data-type', str(row[11])), + ('data-title', str(row[3])), + ('data-start-time', str(row[8])), + ): + text(row[8]) + elif currentTime.hour == timeB.hour and currentTime.minute == timeB.minute: + with tag('time', + ('data-key', str(row[12])), + ('data-current', 'true'), + ('data-type', str(row[11])), + ('data-title', str(row[3])), + ('data-start-time', str(row[8])), + ): + text(row[8]) + else: + with tag('time', + ('data-key', str(row[12])), + ('data-current', 'false'), + ('data-type', str(row[11])), + ('data-title', str(row[3])), + ('data-start-time', str(row[8])), + ): + text(row[8]) + return indent(doc.getvalue()) + + ''' + * + * Get the generated html for the .html file that is the schedule. + * ...This is used whenever a show starts or stops in order to add and remove various styles. + * @param currentTime: datetime object + * @param bgImageURL: str of the image used for the background + * @return string: the generated html content + * + ''' + def get_html_from_daily_schedule(self, currentTime, bgImageURL, datalist, nowPlayingTitle): + + now = datetime.now() + now = now.replace(year=1900, month=1, day=1) + midnight = now.replace(hour=23, minute=59, second=59) + #mutto233 put this here, because to be honest, isn't the current time always now? + if currentTime != None: + currentTime=now + + + time = datetime.now().strftime("%B %d, %Y") + doc, tag, text, line = Doc( + + ).ttl() + doc.asis('') + with tag('html'): + with tag('head'): + with tag('title'): + text(time + " - Daily Pseudo Schedule") + doc.asis('') + doc.asis('') + doc.asis(""" + + """) + if bgImageURL != None: + doc.asis('') + with tag('body'): + with tag('div', klass='container mt-3'): + with tag('div', klass='row make-white'): + with tag('div'): + with tag('div'): + line('h1', self.HTML_PSEUDO_TITLE, klass='col-12 pl-0') + with tag('div'): + line('h3', time, klass='col-12 pl-1') + line('h3', + "Now Playing: "+nowPlayingTitle, + klass='col-12 pl-1', + style="color:red;") + with tag('table', klass='col-12 table table-bordered table-hover'): + with tag('thead', klass='table-info'): + with tag('tr'): + with tag('th'): + text('#') + with tag('th'): + text('Type') + with tag('th'): + text('Series') + with tag('th'): + text('Title') + with tag('th'): + text('Start Time') + numberIncrease = 0 + for row in datalist: + if str(row[11]) == "Commercials" and self.DEBUG == False: + continue + numberIncrease += 1 + with tag('tbody'): + if currentTime != None: + currentTime = currentTime.replace(year=1900, month=1, day=1) + timeBStart = datetime.strptime(row[8], '%I:%M:%S %p') + timeBStart = timeBStart.replace(year=1900, month=1, day=1) + try: + timeBEnd = datetime.strptime(row[9], '%Y-%m-%d %H:%M:%S.%f') + timeBEnd = timeBEnd.replace(day=1) + 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'): + text(numberIncrease) + with tag('td'): + text(row[11]) + with tag('td'): + text(row[6]) + with tag('td'): + text(row[3]) + with tag('td'): + text(row[8]) + elif ((currentTime - timeBStart).total_seconds() >= 0 and \ + (timeBEnd - currentTime).total_seconds() >= 0) or \ + ((timeBStart - timeBEnd).total_seconds() >= 0 and \ + (((currentTime-midnight.replace(hour=0,minute=0,second=0)).total_seconds() >= 0 and \ + (timeBEnd-currentTime).total_seconds() >= 0) or + ((currentTime-timeBStart).total_seconds() >= 0 and \ + (midnight-currentTime).total_seconds() >= 0))): + + print "+++++ Currently Playing:", row[3] + + with tag('tr', klass='bg-info'): + with tag('th', scope='row'): + text(numberIncrease) + with tag('td'): + text(row[11]) + with tag('td'): + text(row[6]) + with tag('td'): + text(row[3]) + with tag('td'): + text(row[8]) + else: + with tag('tr'): + with tag('th', scope='row'): + text(numberIncrease) + with tag('td'): + text(row[11]) + with tag('td'): + text(row[6]) + with tag('td'): + text(row[3]) + with tag('td'): + text(row[8]) + return indent(doc.getvalue()) + + ''' + * + * Create 'schedules' dir & write the generated html to .html file. + * @param data: html string + * @return null + * + ''' + def write_schedule_to_file(self, data): + + now = datetime.now() + fileName = "index.html" + writepath = './' if os.path.basename(os.getcwd()) == "schedules" else "./schedules/" + if not os.path.exists(writepath): + os.makedirs(writepath) + if os.path.exists(writepath+fileName): + os.remove(writepath+fileName) + mode = 'a' if os.path.exists(writepath) else 'w' + with open(writepath+fileName, mode) as f: + f.write(data) + self.start_server() + + ''' + * + * Create 'schedules' dir & write the generated xml to .xml file. + * @param data: xml string + * @return null + * + ''' + def write_xml_to_file(self, data): + + now = datetime.now() + fileName = "pseudo_schedule.xml" + writepath = './' if os.path.basename(os.getcwd()) == "schedules" else "./schedules/" + if not os.path.exists(writepath): + os.makedirs(writepath) + if os.path.exists(writepath+fileName): + os.remove(writepath+fileName) + mode = 'a' if os.path.exists(writepath) else 'w' + with open(writepath+fileName, mode) as f: + f.write(data) + + ''' + * + * Write 0 or 1 to file for the ajax in the schedule.html to know when to refresh + * @param data: xml string + * @return null + * + ''' + def write_refresh_bool_to_file(self): + + fileName = "pseudo_refresh.txt" + writepath = './' if os.path.basename(os.getcwd()) == "schedules" else "./schedules/" + first_line = '' + if not os.path.exists(writepath): + os.makedirs(writepath) + if not os.path.exists(writepath+fileName): + file(writepath+fileName, 'w').close() + mode = 'r+' + with open(writepath+fileName, mode) as f: + f.seek(0) + first_line = f.read() + if self.DEBUG: + print "+++++ Html refresh flag: {}".format(first_line) + if first_line == '' or first_line == "0": + f.seek(0) + f.truncate() + f.write("1") + else: + f.seek(0) + f.truncate() + f.write("0") + + ''' + * + * Trigger "playMedia()" on the Python Plex API for specified media. + * @param mediaType: str: "TV Shows" + * @param mediaParentTitle: str: "Seinfeld" + * @param mediaTitle: str: "The Soup Nazi" + * @return null + * + ''' + def play_media(self, mediaType, mediaParentTitle, mediaTitle, offset, customSectionName, durationAmount): + # 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 "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 + 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 + for client in self.PLEX_CLIENTS: + clientItem = self.PLEX.client(client) + 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: + movie + except: + print "+++++ Commercial is NOT FOUND, my guess is this is the dirty gap. Picking first one" + 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." + except Exception as e: + print e.__doc__ + print e.message + print "##### There was an error trying to play the media." + pass + + def stop_media(self): + + try: + self.my_logger.debug('Trying to stop media.') + for client in self.PLEX_CLIENTS: + clientItem = self.PLEX.client(client) + clientItem.stop(mtype='video') + self.my_logger.debug('Done.') + except Exception as e: + self.my_logger.debug('stop_media - except.', e) + pass + ''' + * + * If tv_controller() does not find a "startTime" for scheduled media, search for an "endTime" match for now time. + * ...This is useful for clearing the generated html schedule when media ends and there is a gap before the next media. + * @param null + * @return null + * + ''' + def check_for_end_time(self, datalist): + + currentTime = datetime.now() + """c.execute("SELECT * FROM daily_schedule") + datalist = list(c.fetchall()) + """ + for row in datalist: + try: + endTime = datetime.strptime(row[9], '%Y-%m-%d %H:%M:%S.%f') + except ValueError: + endTime = datetime.strptime(row[9], '%Y-%m-%d %H:%M:%S') + if currentTime.hour == endTime.hour: + if currentTime.minute == endTime.minute: + if currentTime.second == endTime.second: + if self.DEBUG: + print("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() + break + + 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') + if self.DEBUG: + print str(row).encode('UTF-8') + timeB = datetime.strptime(row[8], '%I:%M:%S %p') + + print "Here, row[13]", row[13] + + self.play_media(row[11], row[6], row[3], offset, row[13], row[7]) + self.write_schedule_to_file( + self.get_html_from_daily_schedule( + timeB, + self.get_show_photo( + row[13], + row[6] if row[11] == "TV Shows" else row[3], row[7] + ), + datalist, + row[6] + " - " + row[3] if row[11] == "TV Shows" else row[3] + ) + ) + self.write_refresh_bool_to_file() + """Generate / write XML to file + """ + self.write_xml_to_file( + self.get_xml_from_daily_schedule( + timeB, + self.get_show_photo( + row[13], + row[6] if row[11] == "TV Shows" else row[3], row[7] + ), + datalist + ) + ) + try: + self.my_logger.debug('Trying to play: ' + row[3]) + except: + pass + + ''' + * + * Check DB / current time. If that matches a scheduled shows startTime then trigger play via Plex API + * @param null + * @return null + * + ''' + def tv_controller(self, datalist): + + datalistLengthMonitor = 0; + currentTime = datetime.now() + """c.execute("SELECT * FROM daily_schedule ORDER BY datetime(startTimeUnix) ASC") + datalist = list(c.fetchall())""" + try: + self.my_logger.debug('TV Controller') + except: + pass + for row in datalist: + timeB = datetime.strptime(row[8], '%I:%M:%S %p') + if currentTime.hour == timeB.hour: + if currentTime.minute == timeB.minute: + if currentTime.second == timeB.second: + print("Starting Media: " + row[3]) + print(row) + self.play_media(row[11], row[6], row[3], row[13], row[7]) + self.write_schedule_to_file( + self.get_html_from_daily_schedule( + timeB, + self.get_show_photo( + row[13], + row[6] if row[11] == "TV Shows" else row[3], row[7] + ), + datalist, + row[6] + " - " + row[3] if row[11] == "TV Shows" else row[3] + ) + ) + self.write_refresh_bool_to_file() + """Generate / write XML to file + """ + self.write_xml_to_file( + self.get_xml_from_daily_schedule( + timeB, + self.get_show_photo( + row[13], + row[6] if row[11] == "TV Shows" else row[3], row[7] + ), + datalist + ) + ) + try: + self.my_logger.debug('Trying to play: ' + row[3]) + except: + pass + break + datalistLengthMonitor += 1 + if datalistLengthMonitor >= len(datalist): + self.check_for_end_time(datalist) + + def manually_get_now_playing_bg_image(self, currentTime, datalist): + now = datetime.now() + now = now.replace(year=1900, month=1, day=1) + midnight = now.replace(hour=23, minute=59, second=59) + 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') + timeBStart = timeBStart.replace(year=1900, month=1, day=1) + try: + timeBEnd = datetime.strptime(row[9], '%Y-%m-%d %H:%M:%S.%f') + timeBEnd = timeBEnd.replace(day=1) + 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 \ + (((currentTime-midnight.replace(hour=0,minute=0,second=0)).total_seconds() >= 0 and \ + (timeBEnd-currentTime).total_seconds() >= 0) or + ((currentTime-timeBStart).total_seconds() >= 0 and \ + (midnight-currentTime).total_seconds() >= 0))): + + print "+++++ Made the conditional & found item: {}".format(row[6]) + + return self.get_show_photo( + row[13], + row[6] if row[11] == "TV Shows" else row[3], row[7] + ) + + else: + + pass + + increase_var += 1 + + if len(datalist) >= increase_var: + print("+++++ In 'manually_get_now_playing_bg_image()'. " + "Reached the end of the schedule. No bgImages found.") + return None + + def manually_get_now_playing_title(self, currentTime, datalist): + now = datetime.now() + now = now.replace(year=1900, month=1, day=1) + midnight = now.replace(hour=23, minute=59, second=59) + 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') + timeBStart = timeBStart.replace(year=1900, month=1, day=1) + try: + timeBEnd = datetime.strptime(row[9], '%Y-%m-%d %H:%M:%S.%f') + timeBEnd = timeBEnd.replace(day=1) + 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 \ + (((currentTime-midnight.replace(hour=0,minute=0,second=0)).total_seconds() >= 0 and \ + (timeBEnd-currentTime).total_seconds() >= 0) or + ((currentTime-timeBStart).total_seconds() >= 0 and \ + (midnight-currentTime).total_seconds() >= 0))): + + print "+++++ Made the conditional & found item: {}".format(row[6]) + + return row[6] + " - " + row[3] if row[11] == "TV Shows" else row[3] + + else: + + pass + + increase_var += 1 + + if len(datalist) >= increase_var: + print("+++++ 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." + now = datetime.now() + now = now.replace(year=1900, month=1, day=1) + + bgImage = self.manually_get_now_playing_bg_image(now, datalist) + + itemTitle = self.manually_get_now_playing_title(now, datalist) + + print "+++++ 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)) self.write_xml_to_file(self.get_xml_from_daily_schedule(None, None, datalist)) \ No newline at end of file diff --git a/main-dir/config.cache b/main-dir/config.cache new file mode 100644 index 0000000..502ece7 --- /dev/null +++ b/main-dir/config.cache @@ -0,0 +1,6 @@ +# PLEX SERVER IP ADDRESS +server_ip= +# PLEX SERVER PORT (DEFAULT: 32400) +server_port=32400 +# PLEX SERVER AUTH TOKEN +server_token= diff --git a/main-dir/config_editor.sh b/main-dir/config_editor.sh new file mode 100644 index 0000000..a88de71 --- /dev/null +++ b/main-dir/config_editor.sh @@ -0,0 +1,524 @@ +#!/bin/bash +#### Script to make changes to config files + +#Allow command argument $1 to indicate channel to edit config +#If $1 == '' Choose main config file or specific channel +#cd into channel directory if necessary +source config.cache +re='^[0-9]+$' +number_of_channels=$(ls | grep pseudo-channel_ | wc -l) +channel_number=$1 +loop_or_exit=loop + +clear +echo "++++++++++++++++++++PSEUDO CHANNEL CONFIG EDITOR++++++++++++++++++++" +echo "Welcome to the CONFIG EDITOR script." +if [[ $channel_number == '' ]] # IF NO ARGUMENT PROVIDED, ASK IF USER WANTS TO EDIT THE MAIN CONFIG OR SELECT A CHANNEL + then + echo "No channel number specified. Edit the main config file?" + read -p 'Y/N: ' edit_main_config + while [[ "$edit_main_config" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "No CHANNEL NUMBER specified. Edit the MAIN CONFIG file?" + read -p 'Y/N: ' edit_main_config + done + if [[ "$edit_main_config" == @(Y|y|Yes|yes|YES) ]] + then + echo "Now editing MAIN CONFIG file." # IF THE USER WANTS TO EDIT THE MAIN CONFIG + sleep 1 + else + echo "Enter CHANNEL NUMBER between 1 and $number_of_channels" # IF THE USER WANTS TO EDIT A CHANNEL CONFIG, ASKING FOR CHANNEL NUMBER + read -p 'Channel Number: ' channel_number + while ! [[ $channel_number =~ $re ]] # VALIDATES THAT CHANNEL NUMBER IS ACTUALLY A NUMBER + do + echo "Enter CHANNEL NUMBER" + read -p 'Channel Number: ' channel_number + done + while ! [[ $channel_number -ge 1 && $channel_number -le $number_of_channels ]] # VALIDATES CHANNEL NUMBER AGAINST ACTUAL CHANNELS + do + echo "ERROR: Channel NOT FOUND." + echo "Channels must be between 1 and $number_of_channels" + echo "Enter CHANNEL NUMBER" + read -p 'Channel Number: ' channel_number + done + echo "Now editing CHANNEL $channel_number file" + sleep 1 + fi +elif ! [[ $channel_number =~ $re ]] # VALIDATES ARGUMENT IS A NUMBER, IF NOT, PROMPT FOR RE-ENTRY + then + echo "ERROR! INVALID CHANNEL SPECIFIED" + echo "Enter CHANNEL NUMBER" + read -p 'Channel Number: ' channel_number + while ! [[ $channel_number =~ $re ]] + do + echo "Enter CHANNEL NUMBER" + read -p 'Channel Number: ' channel_number + done +elif ! [[ $channel_number -ge 1 && $channel_number -le $number_of_channels ]] # VALIDATES ARGUMENT IS A VALID CHANNEL NUMBER, PROMPT FOR RE-ENTRY IF NOT + then + echo "ERROR! SPECIFIED CHANNEL DOES NOT EXIST" + echo "Channels must be between 1 and $number_of_channels" + echo "Enter CHANNEL NUMBER" + read -p 'Channel Number: ' channel_number + while ! [[ $channel_number -ge 1 && $channel_number -le $number_of_channels ]] + do + echo "ERROR! SPECIFIED CHANNEL DOES NOT EXIST" + echo "Channels must be between 1 and $number_of_channels" + echo "Enter CHANNEL NUMBER" + read -p 'Channel Number: ' channel_number + done +fi +if [[ $channel_number -ge 1 && $channel_number -le 9 ]] # SET DIRECTORY TO SELECTED CHANNEL + then + cd pseudo-channel_0"$channel_number" + elif [[ $channel_number -ge 10 ]] + then + cd pseudo-channel_"$channel_number" +fi +while [[ $loop_or_exit == "loop" ]] +do +sleep 1 +clear +echo "++++++++++++++++++++PSEUDO CHANNEL CONFIG EDITOR++++++++++++++++++++" +select category in "BASIC OPTIONS" "ADVANCED OPTIONS" "QUIT" # MAIN MENU + do + if [[ "$category" == "BASIC OPTIONS" && $channel_number == '' ]] # BASIC OPTIONS FOR MAIN CONFIG + then + clear + echo "++++++++++++++++++++PSEUDO CHANNEL CONFIG EDITOR++++++++++++++++++++" + echo "CHOOSE an OPTION to SET VALUE in CONFIG" + select config_option in "Plex Server URL" "Plex Client" "Plex Libraries" "Plex Token" "Daily Reset Time" "Back" + do + break + done + elif [[ "$category" == "BASIC OPTIONS" && $channel_number != '' ]] # BASIC OPTIONS FOR CHANNEL CONFIG + then + clear + echo "++++++++++++++++++++PSEUDO CHANNEL CONFIG EDITOR++++++++++++++++++++" + echo "CHOOSE an OPTION to SET VALUE in CONFIG" + select config_option in "Plex Client" "Plex Libraries" "Use Commercials?" "Back" + do + break + done + elif [[ "$category" == "ADVANCED OPTIONS" && $channel_number == '' ]] # ADVANCED OPTIONS FOR MAIN CONFIG + then + clear + echo "++++++++++++++++++++PSEUDO CHANNEL CONFIG EDITOR++++++++++++++++++++" + echo "CHOOSE an OPTION to SET VALUE in CONFIG" + select config_option in "Use Daily Overlap Cache" "Dirty Gap Fix" "Debug Mode" "Commercial Padding" "Back" + do + break + done + elif [[ "$category" == "ADVANCED OPTIONS" && $channel_number != '' ]] # ADVANCED OPTIONS FOR CHANNEL CONFIG + then + clear + echo "++++++++++++++++++++PSEUDO CHANNEL CONFIG EDITOR++++++++++++++++++++" + echo "CHOOSE an OPTION to SET VALUE in CONFIG" + select config_option in "Debug Mode" "TV Guide Page" "Use Daily Overlap Cache" "Dirty Gap Fix" "Commercial Padding" "Back" + do + break + done + elif [[ "$category" == "QUIT" ]] # QUIT THE SCRIPT + then + echo "PREPARING TO EXIT CONFIG EDITOR..." + sleep 1 + if [[ $channel_number == '' ]] + then + clear + echo "++++++++++++++++++++PSEUDO CHANNEL CONFIG EDITOR++++++++++++++++++++" + echo "Changes to MAIN CONFIG file have been saved." + echo "COPY changes to ALL CONFIG FILES?" + echo "(WARNING: Copying changes will overwrite all" + echo "channel-specific settings)" + read -p 'Y/N: ' write_to_all + while [[ "$write_to_all" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "COPY changes to ALL CONFIG FILES?" + read -p 'Y/N: ' write_to_all + done + if [[ "$write_to_all" == @(Y|y|Yes|yes|YES) ]] + then + echo "There are $number_of_channels channels detected." + channel=1 + while [[ $channel -le $number_of_channels ]] + do + if [[ $channel -ge 1 && $channel -le 9 ]] # SET DIRECTORY TO SELECTED CHANNEL + then + cd pseudo-channel_0"$channel" + elif [[ $channel -ge 10 ]] + then + cd pseudo-channel_"$channel" + fi + cp ../pseudo_config.py ./ + echo "CONFIG FILE copied to CHANNEL $channel of $number_of_channels" + cd .. + ((channel++)) + done + fi + else + echo "CHANGES to the CHANNEL $channel_number CONFIG FILE have been SAVED." + sleep 1 + fi + + echo "EXITING CONFIG EDITOR..." + sleep 1 + clear + exit 0 + fi + break + done +if [[ "$config_option" == "Plex Server URL" ]] # CHANGE THE PLEX SERVER URL AND PORT STORED IN THE PLEX_TOKEN.PY FILE + then + clear + echo "++++++++++++++++++++PSEUDO CHANNEL CONFIG EDITOR++++++++++++++++++++" + #GET PLEX SERVER IP AND PORT + if [[ $server_ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] + then + echo "PLEX SERVER IP detected as $server_ip" + echo "Press ENTER to save $server_ip as your PLEX SERVER IP address" + echo "or enter the new PLEX SERVER IP address below." + read -p "Plex Server IP ($server_ip): " server_ip_entry + if [[ $server_ip_entry == '' ]] + then + echo "PLEX SERVER IP is $server_ip" + else + server_ip="$server_ip_entry" + fi + else + echo "ENTER the IP ADDRESS of your PLEX SERVER" + read -p 'Plex Server IP: ' server_ip + fi + echo "ENTER the PORT number for your PLEX SERVER" + read -p "Public Port (default: $server_port): " server_port_entry + if [ "$server_port_entry" != '' ] + then + server_port="$server_port_entry" + fi + echo "PLEX SERVER is $server_ip:$server_port" + sudo sed -i "s/baseurl =.*/baseurl = \'http:\/\/$server_ip:$server_port\'/" plex_token.py + sudo sed -i "s/server_ip=.*/server_ip=$server_ip/" config.cache + sudo sed -i "s/server_port=.*/server_port=$server_port/" config.cache + sleep 1 +elif [[ "$config_option" == "Plex Token" ]] # CHANGE THE PLEX AUTH TOKEN VALUE IN THE PLEX_TOKEN.PY FILE + then + clear + echo "++++++++++++++++++++PSEUDO CHANNEL CONFIG EDITOR++++++++++++++++++++" + if [ "$server_token" != '' ] + then + echo "AUTH TOKEN is currently set to $server_token" + echo "PRESS ENTER to KEEP THIS as your AUTH TOKEN" + echo "or ENTER your new PLEX AUTH TOKEN." + echo "(for help finding token, check here: https://bit.ly/2p7RtOu)" + else + echo "ENTER your PLEX AUTHENTICATION TOKEN" # GET PLEX SERVER AUTH TOKEN + echo "(for help finding token, check here: https://bit.ly/2p7RtOu)" + fi + read -p 'Plex Auth Token: ' server_token_entry + if [ "$server_token_entry" == '' ] + then + echo "PLEX AUTH TOKEN saved as $server_token" + server_token="\'$server_token\'" + else + server_token=$server_token_entry + echo "PLEX AUTH TOKEN saved as $server_token" + server_token="\'$server_token\'" + fi + sudo sed -i "s/token =.*/token = $server_token/" plex_token.py + sudo sed -i "s/server_token=.*/server_token=$server_token/" config.cache + sleep 1 +elif [[ "$config_option" == "Plex Client" ]] # CHANGE PLEX CLIENT + then + clear + echo "++++++++++++++++++++PSEUDO CHANNEL CONFIG EDITOR++++++++++++++++++++" + clientlist=$(xmllint --xpath "//Server/@name" "http://$serverip_ip:$server_port/clients" | sed "s|name=||g" | sed "s|^ ||g" && echo -e " Other") # GET LIST OF CLIENTS + eval set $clientlist + select ps_client_entry in "$@" + do + if [[ "$ps_client_entry" == "Other" ]] + then + read -p 'Client Name: ' ps_client_entry + ps_client_entry=$(eval echo $ps_client_entry) + fi + ps_client="[\"$ps_client_entry\"]" + sudo sed -i "s/plexClients = .*/plexClients = $ps_client/" pseudo_config.py + echo "Plex Client set to $ps_client_entry in the config" + sleep 1 + break + done +elif [[ "$config_option" == "Plex Libraries" ]] #CHANGE PLEX LIBRARIES + then + clear + echo "++++++++++++++++++++PSEUDO CHANNEL CONFIG EDITOR++++++++++++++++++++" + if [[ $channel_number =~ $re ]] + then + echo "++++++CHANNEL $channel_number PLEX LIBRARIES++++++" + echo "Add LIBRARIES to use with CHANNEL $channel_number" + else + echo "Add ALL LIBRARIES that may be used for ANY CHANNEL here." + fi + echo "ENTER the name of EACH desired Plex library defined as TV SHOWS" + enter_tv_shows=yes + echo -n "[" > tv-libraries.temp + while [[ "$enter_tv_shows" == @(Y|y|Yes|yes|YES) ]] + do + read -p 'TV Show Library Name: ' tv_library_entry + echo -n "\"$tv_library_entry\"" >> tv-libraries.temp + echo "ENTER another TV SHOW LIBRARY?" + read -p 'Y/N: ' enter_tv_shows + while [[ "$enter_tv_shows" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ENTER another TV SHOW LIBRARY?" + read -p 'Y/N: ' enter_tv_shows + done + if [[ "$enter_tv_shows" == @(Y|y|Yes|yes|YES) ]] + then + echo -n ", " >> tv-libraries.temp + fi + done + echo -n "]," >> tv-libraries.temp + echo "ENTER the name of EACH Plex library defined as MOVIES" + enter_movies=yes + echo -n "[" > movie-libraries.temp + while [[ "$enter_movies" == @(Y|y|Yes|yes|YES) ]] + do + read -p 'Movie Library Name: ' movie_library_entry + echo -n "\"$movie_library_entry\"" >> movie-libraries.temp + echo "ENTER another MOVIE LIBRARY?" + read -p 'Y/N: ' enter_movies + while [[ "$enter_movies" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ENTER another MOVIE LIBRARY?" + read -p 'Y/N: ' enter_movies + done + if [[ "$enter_movies" == @(Y|y|Yes|yes|YES) ]] + then + echo -n ", " >> movie-libraries.temp + fi + done + echo -n "]," >> movie-libraries.temp + echo "Use COMMERCIALS in between scheduled content?" + read -p 'Y/N: ' enter_commercials + while [[ "$enter_commercials" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "Use COMMERCIALS in between scheduled content?" + read -p 'Y/N: ' enter_commercials + done + if [[ "$enter_commercials" == @("Y"|"y"|"yes"|"Yes"|"YES") ]] + then + commercials_true=true + echo "ENTER the name of EACH Plex library defined as COMMERCIALS" + echo -n "[" > commercial-libraries.temp + fi + while [[ "$enter_commercials" == @(Y|y|Yes|yes|YES) ]] + do + read -p 'Commercial Library Name: ' commercial_library_entry + echo -n "\"$commercial_library_entry\", " >> commercial-libraries.temp + echo "ENTER another COMMERCIAL LIBRARY?" + read -p 'Y/N: ' enter_commercials + while [[ "$enter_commercials" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ENTER another COMMERCIAL LIBRARY?" + read -p 'Y/N: ' enter_commercials + done + done + if [[ "$commercials_true" == "true" ]] + then + truncate -s-2 commercial-libraries.temp + echo -n "]," >> commercial-libraries.temp + commercial_libraries=$(cat commercial-libraries.temp) + sudo sed -i "/.\"Commercials\" :*./c\ \"Commercials\" : $commercial_libraries" pseudo_config.py + fi + tv_libraries=$(cat tv-libraries.temp) + sudo sed -i "/.\"TV Shows\" :*./c\ \"TV Shows\" : $tv_libraries" pseudo_config.py # WRITE TV LIBRARIES TO CONFIG + movie_libraries=$(cat movie-libraries.temp) + sudo sed -i "/.\"Movies\" :*./c\ \"Movies\" : $movie_libraries" pseudo_config.py # WRITE MOVIE LIBRARIES TO CONFIG +elif [[ "$config_option" == "Daily Reset Time" ]] + then + clear + echo "++++++++++++++++++++PSEUDO CHANNEL CONFIG EDITOR++++++++++++++++++++" + echo "Set the TIME for PSEUDO CHANNEL to GENERATE the DAILY SCHEDULE" + echo "USE 24H FORMAT (ex: 23:00)" + read -p 'Daily Reset Time: ' reset_time_entry +# if [[ $reset_time_entry =~ ^[01][0-9]:[0-5][0-9]|2[0-3]:[0-5][0-9]$ ]] +# then + echo "Saving DAILY RESET TIME as $reset_time_entry..." + sleep 1 +# else +# echo "Set the TIME for PSEUDO CHANNEL to GENERATE the DAILY SCHEDULE" +# echo "USE 24H FORMAT (ex: 23:00)" +# read -p 'Daily Reset Time: ' reset_time_entry +# fi + reset_time_formatted=$(echo $reset_time_entry | sed -e "s|^[0-9]:.*|0$reset_time_entry|g") + reset_time_hour="${reset_time_formatted:0:2}" + reset_time_hour="$(echo $reset_time_hour | sed -e s/^[0]//)" + reset_time_minute="${reset_time_formatted: -2}" + reset_time_minutes="$(echo $reset_time_minutes | sed -e s/^[0]//)" + # SET UP CRON JOB TO RUN DAILY RESET + sudo crontab -l | grep -v 'daily-cron.sh' | crontab - + sudo echo \#\!/bin/bash > ./daily-cron.sh && echo "cd $PWD" >> ./daily-cron.sh && echo "sudo ./generate-channels-daily-schedules.sh" >> ./daily-cron.sh + ( sudo crontab -l ; echo "$reset_time_minute $reset_time_hour * * * $PWD/daily-cron.sh" ) | sudo crontab - + sudo sed -i "s/dailyUpdateTime.*/dailyUpdateTime = \"$reset_time_entry\"/" pseudo_config.py + elif [[ "$config_option" == "Use Commercials?" ]] + then + clear + echo "++++++++++++++++++++PSEUDO CHANNEL CONFIG EDITOR++++++++++++++++++++" + echo "Use COMMERCIALS in between scheduled content?" + read -p 'Y/N: ' use_commercials + while [[ "$use_commercials" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "Use COMMERCIALS in between scheduled content?" + read -p 'Y/N: ' use_commercials + done + if [[ "$use_commercials" == "true" ]] + then + commercials_true=true + sudo sed -i "s/useCommercialInjection =.*/useCommercialInjection = \"true\"/" pseudo_config.py + echo "COMMERCIAL INJECTION has been turned ON" + else + sudo sed -i "s/useCommercialInjection =.*/useCommercialInjection = \"false\"/" pseudo_config.py + echo "COMMERCIAL INJECTION has been turned OFF" + fi + elif [[ "$config_option" == "Use Daily Overlap Cache" ]] + then + clear + echo "++++++++++++++++++++PSEUDO CHANNEL CONFIG EDITOR++++++++++++++++++++" + echo "When the schedule updates every 24 hours," + echo "it's possible that it will interrupt any" + echo "shows / movies that were playing from the" + echo "previous day. To fix this, this option saves" + echo "a cached schedule from the previous day to" + echo "override any media that is trying to play" + echo "while the previous day is finishing." + echo "This option is off by default." + echo "Turn on DAILY OVERLAP CACHE?" + read -p 'Y/N: ' use_daily_overlap + if [[ "$use_daily_overlap" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + then + echo "Turn on DAILY OVERLAP CACHE?" + read -p 'Y/N: ' use_daily_overlap + fi + if [[ "$use_daily_overlap" = @(Y|y|Yes|yes|YES) ]] + then + sudo sed -i "s/useDailyOverlapCache =.*/useDailyOverlapCache = True/" pseudo_config.py + echo "DAILY OVERLAP CACHE has been set to TRUE" + else + sudo sed -i "s/useDailyOverlapCache =.*/useDailyOverlapCache = False/" pseudo_config.py + echo "DAILY OVERLAP CACHE has been set to FALSE" + fi + elif [[ "$config_option" == "Dirty Gap Fix" ]] + then + clear + echo "++++++++++++++++++++PSEUDO CHANNEL CONFIG EDITOR++++++++++++++++++++" + echo "When this option is turned off, commercials" + echo "are selected to fit in the gap between the last" + echo "commercial and the next scheduled item. If this" + echo "option is turned on, the script will not take" + echo "length into account when choosing the last commercial." + echo "This may result in partial playback until the next show" + echo "or movie starts. However, it may be preferred if your" + echo "commercial library is small or doesn't contain any" + echo "shorter (5-15 second) videos in the commercials library." + echo "Turn on DIRTY GAP FIX?" + read -p 'Y/N: ' use_dirty_gap + if [[ "$use_dirty_gap" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + then + echo "Turn on DIRTY GAP FIX?" + read -p 'Y/N: ' use_dirty_gap + fi + if [[ "$use_dirty_gap" = @(Y|y|Yes|yes|YES) ]] + then + sudo sed -i "s/useDirtyGapFix =.*/useDirtyGapFix = True/" pseudo_config.py + echo "DIRTY GAP FIX has been set to TRUE" + else + sudo sed -i "s/useDirtyGapFix =.*/useDirtyGapFix = False/" pseudo_config.py + echo "DIRTY GAP FIX has been set to FALSE" + fi + + elif [[ "$config_option" == "Debug Mode" ]] + then + clear + echo "++++++++++++++++++++PSEUDO CHANNEL CONFIG EDITOR++++++++++++++++++++" + echo "Debug mode provides more terminal output and writes" + echo "the entire daily schedule (including commercials) to" + echo "the web and xml file outputs." + echo "Turn on DEBUG MODE?" + read -p 'Y/N: ' use_debug_mode + if [[ "$use_debug_mode" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + then + echo "Turn on DEBUG MODE?" + read -p 'Y/N: ' use_debug_mode + fi + if [[ "$use_debug_mode" = @(Y|y|Yes|yes|YES) ]] + then + sudo sed -i "s/debug_mode.*/debug_mode = True/" pseudo_config.py + echo "DEBUG MODE has been set to TRUE" + else + sudo sed -i "s/debug_mode =.*/debug_mode = False/" pseudo_config.py + echo "DEBUG MODE has been set to FALSE" + fi + elif [[ "$config_option" == "TV Guide Page" ]] + then + clear + echo "++++++++++++++++++++PSEUDO CHANNEL CONFIG EDITOR++++++++++++++++++++" + echo "Setting these options will run a simple http webserver" + echo "to display the daily schedule in any web browser with" + echo "network access to the device. If you decline to set the" + echo "IP address and port number, you will still have the option" + echo "to set the page title for if you decide to run your own" + echo "webserver and symlink the html files into the appropriate" + echo "directory." + echo "NOTE: This option must be set individually per channel and" + echo "each channel must have a unique port number." + echo "Use Simple http Webserver?" + read -p 'Y/N: ' use_webserver + if [[ "$use_webserver" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + then + echo "Use Simple http Webserver?" + read -p 'Y/N: ' use_webserver + fi + if [[ "$use_webserver" = @(Y|y|Yes|yes|YES) ]] + then + local_ip=$(ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p') + echo "Your IP address is $local_ip" + sudo sed -i "s/controllerServerPath =.*/controllerServerPath = \"$local_ip\"/" pseudo_config.py + echo "Enter the PORT NUMBER to use with THIS CHANNEL" + read -p 'Port Number: ' port_number + sudo sed -i "s/controllerServerPort =.*/controllerServerPort = \"$port_number\"/" pseudo_config.py + echo "Set the CHANNEL TITLE for the SCHEDULE PAGE" + read -p 'Channel Title: ' channel_name + sudo sed -i "s/htmlPseudoTitle =.*/htmlPseudoTitle = \"$channel_name\"/" pseudo_config.py + echo "$channel_name's daily schedule will be accessible at http://$local_ip:$port_number" + echo "To access this page from OUTSIDE your LOCAL NETWORK, add a port forward rule in" + echo "your router for $port_number to $local_ip." + else + sudo sed -i "s/controllerServerPath =.*/controllerServerPath = \"\"/" pseudo_config.py + sudo sed -i "s/controllerServerPort =.*/controllerServerPort = \"\"/" pseudo_config.py + echo "Set the CHANNEL TITLE for the SCHEDULE PAGE" + read -p 'Channel Title: ' channel_name + sudo sed -i "s/htmlPseudoTitle =.*/htmlPseudoTitle = \"$channel_name\"/" pseudo_config.py + echo "CHANNEL TITLE set to $channel_name" + fi + elif [[ "$config_option" == "Commercial Padding" ]] + then + clear + echo "++++++++++++++++++++PSEUDO CHANNEL CONFIG EDITOR++++++++++++++++++++" + echo "The COMMERCIAL PADDING value is the number of seconds in" + echo "between the end of a commercial, movie or show and the" + echo "start of the next. This accounts for lag in starting" + echo "the previous item by allowing time for it to end before" + echo "the next one starts." + echo "Set the COMMERCIAL PADDING value (in SECONDS)" + read -p 'Commercial Padding: ' commercial_padding + if ! [[ $commercial_padding =~ $re ]] + then + echo "Set the COMMERCIAL PADDING value (in SECONDS)" + read -p 'Commercial Padding: ' commercial_padding + fi + sudo sed -i "s/commercialPadding =.*/commercialPadding = $commercial_padding/" pseudo_config.py + + elif [[ "$config_option" == "Back" ]] + then + echo "Going BACK to MAIN MENU" + sleep 1 +fi +done diff --git a/main-dir/create_box.sh b/main-dir/create_box.sh new file mode 100644 index 0000000..239e8bf --- /dev/null +++ b/main-dir/create_box.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +# Purpose of the script is to copy the current "master" channel database and create a new set for a named box +# As the input, simply give the name of a client, this will be appended in the form "channels_" + +# Flow of the script +# - Go out of directory, and make a new directory +# - Copy from the master folder to this folder +# - Find all channels, go in and remove .db, symlink to the original (running with -sf) + +CHANNEL_DIR_INCREMENT_SYMBOL="_" + +MASTERDIRECTORY="channels" + +NEWDIRECTORY="${MASTERDIRECTORY}_${1}" + +# CREATE THE NEW DIRECTORY +cd .. + +if [ -d "$NEWDIRECTORY" ]; then + sudo rm -R ${NEWDIRECTORY} +fi +mkdir $NEWDIRECTORY + + +# COPY THE ELEMENTS INTO HERE, THEN SET CORRECT PROPERTIES +sudo cp -r ./${MASTERDIRECTORY}/* ./${NEWDIRECTORY}/ +sudo chmod -R 777 ./${NEWDIRECTORY} + + +# GO INTO EACH CHANNEL, DELETE THE .db FILE, AND SYMLINK TO THE ORIGINAL +cd ${NEWDIRECTORY} +CHANNEL_DIR_ARR=( $(find . -maxdepth 1 -type d -name '*'"$CHANNEL_DIR_INCREMENT_SYMBOL"'[[:digit:]]*' -printf "%P\n" | sort -t"$CHANNEL_DIR_INCREMENT_SYMBOL" -n) ) + + +if [ "${#CHANNEL_DIR_ARR[@]}" -gt 1 ]; then + + echo "+++++ There are ${#CHANNEL_DIR_ARR[@]} channels detected." + + for i in "${!CHANNEL_DIR_ARR[@]}" + do + echo "+++++ Linking Directories in ${CHANNEL_DIR_ARR[i]}" + cd ${CHANNEL_DIR_ARR[i]} + MASTER_CHANNEL="../../${MASTERDIRECTORY}/${CHANNEL_DIR_ARR[i]}" + + ln -sf "${MASTER_CHANNEL}/pseudo-channel.db" + + cd .. + done +fi + + + diff --git a/main-dir/pseudo-channel-control.sh b/main-dir/pseudo-channel-control.sh new file mode 100644 index 0000000..93dc386 --- /dev/null +++ b/main-dir/pseudo-channel-control.sh @@ -0,0 +1,180 @@ +#!/bin/bash +source config.cache +re='^[0-9]+$' +number_of_channels=$(ls | grep pseudo-channel_ | wc -l) +clear +echo "+++++++++++++++++++++++++++PSEUDO CHANNEL+++++++++++++++++++++++++++" +echo "Choose a CATEGORY" +select category in "CONTROL" "EDIT" "UPDATE" "EXIT" + do + sleep 1 + clear + echo "+++++++++++++++++++++++++++PSEUDO CHANNEL+++++++++++++++++++++++++++" + if [[ "$category" == "CONTROL" ]] + then + echo "PSEUDO CHANNEL CONTROL OPTIONS" + select pseudo_channel_do in "START CHANNEL" "NEXT CHANNEL" "PREVIOUS CHANNEL" "STOP CHANNEL" "BACK" + do + sleep 1 + clear + echo "+++++++++++++++++++++++++++PSEUDO CHANNEL+++++++++++++++++++++++++++" + if [[ "$pseudo_channel_do" == "START CHANNEL" ]] + then + echo "PSEUDO CHANNEL - START CHANNEL" + echo "Enter CHANNEL NUMBER between 1 and $number_of_channels" + read -p "Channel: " channel_number + while ! [[ $channel_number =~ $re ]] # VALIDATES THAT CHANNEL NUMBER IS ACTUALLY A NUMBER + do + echo "Enter CHANNEL NUMBER between 1 and $number_of_channels" + read -p "Channel: " channel_number + done + while ! [[ $channel_number -ge 1 && $channel_number -le $number_of_channels ]] + do + echo "ERROR: Channel NOT FOUND." + echo "Channels must be between 1 and $number_of_channels" + echo "Enter CHANNEL NUMBER" + read -p 'Channel: ' channel_number + done + if [[ $channel_number -ge 1 && $channel_number -le 9 ]] + then + (sudo ./manual.sh 0"$channel_number") + else + (sudo ./manual.sh "$channel_number") + fi + break + fi + if [[ "$pseudo_channel_do" == "NEXT CHANNEL" ]] + then + (sudo ./channelup.sh) + fi + if [[ "$pseudo_channel_do" == "PREVIOUS CHANNEL" ]] + then + (sudo ./channeldown.sh) + fi + if [[ "$pseudo_channel_do" == "STOP CHANNEL" ]] + then + (sudo ./stop-all-channels.sh) + fi + if [[ "$pseudo_channel_do" == "BACK" ]] + then + break + fi + sleep 1 + clear + echo "+++++++++++++++++++++++++++PSEUDO CHANNEL+++++++++++++++++++++++++++" + echo "PSEUDO CHANNEL CONTROL OPTIONS" + echo "1) START CHANNEL 3) PREVIOUS CHANNEL 5) BACK" + echo "2) NEXT CHANNEL 4) STOP CHANNEL" + done + fi + if [[ "$category" == "EDIT" ]] + then + sleep 1 + clear + echo "+++++++++++++++++++++++++++PSEUDO CHANNEL+++++++++++++++++++++++++++" + echo "PSEUDO CHANNEL EDIT OPTIONS" + select pseudo_channel_do in "EDIT SCHEDULE" "EDIT CONFIG" "ADD CLIENT" "BACK" + do + sleep 1 + clear + echo "+++++++++++++++++++++++++++PSEUDO CHANNEL+++++++++++++++++++++++++++" + if [[ "$pseudo_channel_do" == "EDIT SCHEDULE" ]] + then + (sudo ./schedule-editor.sh) + fi + if [[ "$pseudo_channel_do" == "EDIT CONFIG" ]] + then + (sudo ./config_editor.sh) + fi + if [[ "$pseudo_channel_do" == "ADD CLIENT" ]] + then + echo "SELECT the PLEX CLIENT for the NEW CLIENT SETUP or ENTER one manually" + clientlist=$(xmllint --xpath "//Server/@name" "http://$server_ip:$server_port/clients" | sed "s|name=||g" | sed "s|^ ||g" && echo -e " Other") + eval set $clientlist + select create_box_client in "$@" + do + if [[ "$create_box_client" == "Other" ]] + then + read -p 'Client Name: ' create_box_client + create_box_client=$(eval echo $create_box_client) + fi + break + done + (sudo ./create_box.sh "$create_box_client") + fi + if [[ "$pseudo_channel_do" == "BACK" ]] + then + break + fi + sleep 1 + clear + echo "+++++++++++++++++++++++++++PSEUDO CHANNEL+++++++++++++++++++++++++++" + echo "PSEUDO CHANNEL EDIT OPTIONS" + echo "1) EDIT SCHEDULE" + echo "2) EDIT CONFIG" + echo "3) ADD CLIENT" + echo "4) BACK" + done + fi + if [[ "$category" == "UPDATE" ]] + then + echo "PSEUDO CHANNEL UPDATE OPTIONS" + select pseudo_channel_do in "DATABASE UPDATE" "SOFTWARE UPDATE" "BACK" + do + sleep 1 + clear + echo "+++++++++++++++++++++++++++PSEUDO CHANNEL+++++++++++++++++++++++++++" + if [[ "$pseudo_channel_do" == "DATABASE UPDATE" ]] + then + echo "Select DATABASE to UPDATE" + select update_database in "TV Shows" "Movies" "Commercials" "All" + do + if [[ "$update_database" == "TV Shows" ]] + then + (sudo python Global_DatabaseUpdate.py -ut) + elif [[ "$update_database" == "Movies" ]] + then + (sudo python Global_DatabaseUpdate.py -um) + elif [[ "$update_database" == "Commercials" ]] + then + (sudo python Global_DatabaseUpdate.py -uc) + elif [[ "$update_database" == "All" ]] + then + (sudo python Global_DatabaseUpdate.py -u) + fi + break + done + fi + if [[ "$pseudo_channel_do" == "SOFTWARE UPDATE" ]] + then + (sudo ./update-channels-from-git.sh) + fi + if [[ "$pseudo_channel_do" == "BACK" ]] + then + break + fi + sleep 1 + clear + echo "+++++++++++++++++++++++++++PSEUDO CHANNEL+++++++++++++++++++++++++++" + echo "PSEUDO CHANNEL UPDATE OPTIONS" + echo "1) DATABASE UPDATE" + echo "2) SOFTWARE UPDATE" + echo "3) BACK" + done + fi + if [[ "$category" == "EXIT" ]] + then + echo "EXITING PSEUDO CHANNEL CONTROL SCRIPT..." + sleep 1 + clear + exit + fi +sleep 1 +clear +echo "+++++++++++++++++++++++++++PSEUDO CHANNEL+++++++++++++++++++++++++++" +echo "Choose a CATEGORY" +echo "1) CONTROL" +echo "2) EDIT" +echo "3) UPDATE" +echo "4) EXIT" +done diff --git a/main-dir/schedule-editor.sh b/main-dir/schedule-editor.sh new file mode 100644 index 0000000..095790b --- /dev/null +++ b/main-dir/schedule-editor.sh @@ -0,0 +1,582 @@ +#!/bin/bash +source config.cache +re='^[0-9]+$' +number_of_channels=$(ls | grep pseudo-channel_ | wc -l) +channel_number=$1 +loop_or_exit=loop + +time_entry() { +sleep 1 +clear +echo "++++++++++++++++++++PSEUDO CHANNEL SCHEDULE EDITOR++++++++++++++++++++" +echo "ENTER the START TIME for THIS ENTRY in 24h format" +read -p 'Time (24h): ' start_time +echo "START TIME set to $start_time" +sleep 1 +clear +echo "++++++++++++++++++++PSEUDO CHANNEL SCHEDULE EDITOR++++++++++++++++++++" +echo "Choose MEDIA TYPE to start at $start_time" +select media_type in "Movie" "TV Series" "Random TV Episode" + do + sleep 1 + clear + echo "++++++++++++++++++++PSEUDO CHANNEL SCHEDULE EDITOR++++++++++++++++++++" + if [[ "$media_type" == "Movie" ]] + then + type="\"movie\"" + entry="MOVIE" + #echo "ENTER the MOVIE TITLE" + #read -p 'Title: ' title + title="\"random\"" + elif [[ "$media_type" == "TV Series" ]] + then + type="\"series\"" + echo "ENTER the TV SERIES title" + read -p 'Title: ' title + entry="SHOW" + title=$(echo $title | recode ..html) + title="\"$title\"" + elif [[ "$media_type" == "Random TV Episode" ]] + then + type="\"random\"" + echo "ENTER the NAME of the TV SHOW to schedule RANDOM EPISODES from" + read -p 'Title: ' title + entry="SHOW" + title=$(echo $title | recode ..html) + title="\"$title\"" + fi + break +done +sleep 1 +clear +echo "++++++++++++++++++++PSEUDO CHANNEL SCHEDULE EDITOR++++++++++++++++++++" +echo "Start this $entry to start at the EXACT TIME specified or AFTER" +echo "the PREVIOUS show or movie ENDS?" +select strict_time_entry in "Exact Time" "After Previous" + do + if [[ $strict_time_entry == "Exact Time" ]] + then + strict_time="\"true\"" + time_shift="\"1\"" + echo "The $entry $title will play at exactly $start_time" + elif [[ $strict_time_entry == "After Previous" ]] + then + sleep 1 + clear + echo "++++++++++++++++++++PSEUDO CHANNEL SCHEDULE EDITOR++++++++++++++++++++" + strict_time="\"false\"" + echo "TIME SHIFT VALUE" + echo "This value will determine how much commercial time will be placed" + echo "in between the end of the previous show or movie and the start of this $entry" + echo "The value entered will restrict the start time to a time that ends in that number" + echo "FOR EXAMPLE: A value of 5 will allow the $entry to start at" + echo "5, 10, 15, 20, etc. after the hour. A value of 30 will only allow the $entry to" + echo "start on the half-hour. A value of 2 will restrict start times to even-numbered minutes only." + echo "ENTER the TIME SHIFT value" + read -p 'Time Shift: ' time_shift + while ! [[ $time_shift =~ $re ]] + do + echo "ENTER the TIME SHIFT value" + read -p 'Time Shift: ' time_shift + time_shift="\"$time_shift\"" + done + fi +break +done +if [[ $media_type == "Movie" ]] + then + sleep 1 + clear + echo "++++++++++++++++++++PSEUDO CHANNEL SCHEDULE EDITOR++++++++++++++++++++" + echo "Restrict RANDOM MOVIE selection based on available PLEX METADATA?" + read -p 'Y/N: ' add_xtra + while [[ "$add_xtra" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "Restrict RANDOM MOVIE selection based on available PLEX METADATA?" + read -p 'Y/N: ' add_xtra + done + if [[ "$add_xtra" == @(Y|y|Yes|yes|YES) ]] + then + sleep 1 + clear + echo "++++++++++++++++++++PSEUDO CHANNEL SCHEDULE EDITOR++++++++++++++++++++" + select xtra_tag in "Studio" "MPAA Rating" "Year" "Decade" "Genre" "Director" "Writer" "Actor" "Collection" + do + sleep 1 + clear + echo "++++++++++++++++++++PSEUDO CHANNEL SCHEDULE EDITOR++++++++++++++++++++" + if [[ "$xtra_tag" == "Studio" ]] + then + echo "Enter the NAME of the MOVIE STUDIO(S) to FILTER by (Example: Amblin Entertainment)." + enter_studio=yes + echo -n "studio:" > xtra.temp + while [[ "$enter_studio" == @(Y|y|Yes|yes|YES) ]] + do + read -p 'Studio(s) :' xtra_studio + echo -n "$xtra_studio" >> xtra.temp + echo "ENTER another STUDIO?" + echo "Multiples are treated as an AND, not OR. Results will be filtered by ALL VALUES." + read -p 'Y/N: ' enter_studio + while [[ "$enter_studio" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ENTER another STUDIO?" + read -p 'Y/N: ' enter_studio + done + if [[ "$enter_studio" == @(Y|y|Yes|yes|YES) ]] + then + echo -n "," >> xtra.temp + fi + done + fi + if [[ "$xtra_tag" == "MPAA Rating" ]] + then + echo "ADD the MPAA RATING(s) to FILTER by (Example: PG-13)" + enter_rating=yes + echo -n "contentRating:" > xtra.temp + while [[ "$enter_rating" == @(Y|y|Yes|yes|YES) ]] + do + read -p 'Rating(s): ' xtra_rating + echo -n "$xtra_rating" >> xtra.temp + echo "ENTER another RATING?" + echo "Multiples are treated as an AND, not OR. Results will be filtered by ALL VALUES." + read -p 'Y/N: ' enter_rating + while [[ "$enter_rating" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ENTER another RATING?" + read -p 'Y/N: ' enter_rating + done + if [[ "$enter_rating" == @(Y|y|Yes|yes|YES) ]] + then + echo -n "," >> xtra.temp + fi + done + fi + if [[ "$xtra_tag" == "Year" ]] + then + echo "ADD RELEASE YEAR(S) to FILTER by (Example: 1982)" + echo -n "year:" > xtra.temp + read -p 'Year(s): ' xtra_year + echo -n "$xtra_year" >> xtra.temp + fi + if [[ "$xtra_tag" == "Decade" ]] + then + echo "ADD the DECADE of release to FILTER by (Example: 1980)" + echo -n "decade:" > xtra.temp + read -p 'Decade: ' xtra_decade + echo -n "$xtra_decade" >> xtra.temp + fi + if [[ "$xtra_tag" == "Genre" ]] + then + echo "ENTER GENRES to the RANDOM MOVIE FILTER (Example: Action)" + enter_genre=yes + echo -n "genre:" > xtra.temp + while [[ "$enter_genre" == @(Y|y|Yes|yes|YES) ]] + do + read -p 'Genre: ' xtra_genre + echo -n "$xtra_genre" >> xtra.temp + echo "ENTER another GENRE?" + echo "Multiples are treated as an AND, not OR. Results will be filtered by ALL VALUES." + read -p 'Y/N: ' enter_genre + while [[ "$enter_genre" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ENTER another GENRE?" + read -p 'Y/N: ' enter_genre + done + if [[ "$enter_genre" == @(Y|y|Yes|yes|YES) ]] + then + echo -n "," >> xtra.temp + fi + done + fi + if [[ "$xtra_tag" == "Director" ]] + then + echo "FILTER by the following DIRECTOR(S) (Example: Taika Waititi)" + enter_director=yes + echo -n "director:" > xtra.temp + while [[ "$enter_director" == @(Y|y|Yes|yes|YES) ]] + do + read -p 'Director: ' xtra_director + echo -n "$xtra_genre" >> xtra.temp + echo "ENTER another GENRE?" + echo "Multiples are treated as an AND, not OR. Results will be filtered by ALL VALUES." + read -p 'Y/N: ' enter_director + while [[ "$enter_director" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ENTER another DIRECTOR?" + read -p 'Y/N: ' enter_director + done + if [[ "$enter_director" == @(Y|y|Yes|yes|YES) ]] + then + echo -n "," >> xtra.temp + fi + done + fi + if [[ "$xtra_tag" == "Writer" ]] + then + echo "ADD WRITER(S) to FILTER by (Example: Sandra Bullock)" + enter_writer=yes + echo -n "Writer:" > xtra.temp + while [[ "$enter_writer" == @(Y|y|Yes|yes|YES) ]] + do + read -p 'Writer: ' xtra_writer + echo -n "$xtra_writer" >> xtra.temp + echo "ENTER another WRITER?" + echo "Multiples are treated as an AND, not OR. Results will be filtered by ALL VALUES." + read -p 'Y/N: ' enter_writer + while [[ "$enter_writer" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ENTER another writer?" + read -p 'Y/N: ' enter_writer + done + if [[ "$enter_writer" == @(Y|y|Yes|yes|YES) ]] + then + echo -n "," >> xtra.temp + fi + done + fi + if [[ "$xtra_tag" == "Actor" ]] + then + echo "ADD ACTOR(S) to FILTER by (Example: Sandra Bullock)" + enter_actor=yes + echo -n "Actor:" > xtra.temp + while [[ "$enter_actor" == @(Y|y|Yes|yes|YES) ]] + do + read -p 'Actor: ' xtra_writer + echo -n "$xtra_actor" >> xtra.temp + echo "ENTER another ACTOR?" + echo "Multiples are treated as an AND, not OR. Results will be filtered by ALL VALUES." + read -p 'Y/N: ' enter_actor + while [[ "$enter_actor" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ENTER another actor?" + read -p 'Y/N: ' enter_actor + done + if [[ "$enter_actor" == @(Y|y|Yes|yes|YES) ]] + then + echo -n "," >> xtra.temp + fi + done + fi + if [[ "$xtra_tag" == "Collection" ]] + then + echo "A COLLECTION is a user-defined TAG. Any selection of MOVIES can be added to a COLLECTION" + echo "and DEFINED here to be FILTERED by. (Example: Marvel Movies or Halloween Movies)" + echo -n "collection:" > xtra.temp + read -p 'Collection(s): ' xtra_collection + echo -n "$xtra_collection" >> xtra.temp + fi + xtra=$(cat xtra.temp) + xtra="\"$xtra\"" + break + done + else + > xtra.temp + fi +fi +overlap_max="\"30\"" +} +clear +echo "++++++++++++++++++++PSEUDO CHANNEL SCHEDULE EDITOR++++++++++++++++++++" +if [[ $channel_number == '' ]] # IF NO ARGUMENT PROVIDED, ASK IF USER WANTS TO EDIT THE MAIN CONFIG OR SELECT A CHANNEL + then + echo "CHOOSE which CHANNEL SCHEDULE to create." + echo "Enter CHANNEL NUMBER between 1 and $number_of_channels" + read -p 'Channel Number: ' channel_number + while ! [[ $channel_number =~ $re ]] # VALIDATES THAT CHANNEL NUMBER IS ACTUALLY A NUMBER + do + echo "Enter CHANNEL NUMBER" + read -p 'Channel Number: ' channel_number + done + while ! [[ $channel_number -ge 1 && $channel_number -le $number_of_channels ]] # VALIDATES CHANNEL NUMBER AGAINST ACTUAL CHANNELS + do + echo "ERROR: Channel NOT FOUND." + echo "Channels must be between 1 and $number_of_channels" + echo "Enter CHANNEL NUMBER" + read -p 'Channel Number: ' channel_number + done +fi + echo "Now editing the schedule for CHANNEL $channel_number" + if [[ $channel_number -ge 1 && $channel_number -le 9 ]] # SET DIRECTORY TO SELECTED CHANNEL + then + cd pseudo-channel_0"$channel_number" + elif [[ $channel_number -ge 10 ]] + then + cd pseudo-channel_"$channel_number" + fi +sleep 1 +clear +echo "++++++++++++++++++++PSEUDO CHANNEL SCHEDULE EDITOR++++++++++++++++++++" +echo "Backing up CURRENT SCHEDULE FILE..." +sleep 1 +sudo cp pseudo_schedule.xml pseudo_schedule.backup +echo "Creating NEW SCHEDULE FILE..." +echo "" > pseudo_schedule.xml +echo "" >> pseudo_schedule.xml +sleep 1 +clear +echo "++++++++++++++++++++PSEUDO CHANNEL SCHEDULE EDITOR++++++++++++++++++++" +echo "CHOOSE which DAY to SCHEDULE" +select day_of_week in "Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday" "Weekends" "Weekdays" "Every Day" "Exit" + do + sleep 1 + clear + echo "++++++++++++++++++++PSEUDO CHANNEL SCHEDULE EDITOR++++++++++++++++++++" + if [[ "$day_of_week" == "Sunday" ]] + then + echo "" >> pseudo_schedule.xml + enter_time=yes + while [[ $enter_time == @(Y|y|Yes|yes|YES) ]] + do + time_entry + if [[ "$entry" == "MOVIE" && "$add_xtra" == @(Y|y|Yes|yes|YES) ]] + then + echo "" >> pseudo_schedule.xml + else + echo "" >> pseudo_schedule.xml + fi + echo "ADD another SHOW or MOVIE?" + read -p 'Y/N: ' enter_time + while [[ "$enter_time" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ADD another SHOW or MOVIE?" + read -p 'Y/N: ' enter_time + done + done + echo "" >> pseudo_schedule.xml + fi + if [[ "$day_of_week" == "Monday" ]] + then + echo "" >> pseudo_schedule.xml + enter_time=yes + while [[ $enter_time == @(Y|y|Yes|yes|YES) ]] + do + time_entry + if [[ "$entry" == "MOVIE" && "$add_xtra" == @(Y|y|Yes|yes|YES) ]] + then + echo "" >> pseudo_schedule.xml + else + echo "" >> pseudo_schedule.xml + fi + echo "ADD another SHOW or MOVIE?" + read -p 'Y/N: ' enter_time + while [[ "$enter_time" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ADD another SHOW or MOVIE?" + read -p 'Y/N: ' enter_time + done + done + echo "" >> pseudo_schedule.xml + fi + if [[ "$day_of_week" == "Tuesday" ]] + then + echo "" >> pseudo_schedule.xml + enter_time=yes + while [[ $enter_time == @(Y|y|Yes|yes|YES) ]] + do + time_entry + if [[ "$entry" == "MOVIE" && "$add_xtra" == @(Y|y|Yes|yes|YES) ]] + then + echo "" >> pseudo_schedule.xml + else + echo "" >> pseudo_schedule.xml + fi + echo "ADD another SHOW or MOVIE?" + read -p 'Y/N: ' enter_time + while [[ "$enter_time" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ADD another SHOW or MOVIE?" + read -p 'Y/N: ' enter_time + done + done + echo "" >> pseudo_schedule.xml + fi + if [[ "$day_of_week" == "Wednesday" ]] + then + echo "" >> pseudo_schedule.xml + enter_time=yes + while [[ $enter_time == @(Y|y|Yes|yes|YES) ]] + do + time_entry + if [[ "$entry" == "MOVIE" && "$add_xtra" == @(Y|y|Yes|yes|YES) ]] + then + echo "" >> pseudo_schedule.xml + else + echo "" >> pseudo_schedule.xml + fi + echo "ADD another SHOW or MOVIE?" + read -p 'Y/N: ' enter_time + while [[ "$enter_time" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ADD another SHOW or MOVIE?" + read -p 'Y/N: ' enter_time + done + done + echo "" >> pseudo_schedule.xml + fi + if [[ "$day_of_week" == "Thursday" ]] + then + echo "" >> pseudo_schedule.xml + enter_time=yes + while [[ $enter_time == @(Y|y|Yes|yes|YES) ]] + do + time_entry + if [[ "$entry" == "MOVIE" && "$add_xtra" == @(Y|y|Yes|yes|YES) ]] + then + echo "" >> pseudo_schedule.xml + else + echo "" >> pseudo_schedule.xml + fi + echo "ADD another SHOW or MOVIE?" + read -p 'Y/N: ' enter_time + while [[ "$enter_time" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ADD another SHOW or MOVIE?" + read -p 'Y/N: ' enter_time + done + done + echo "" >> pseudo_schedule.xml + fi + if [[ "$day_of_week" == "Friday" ]] + then + echo "" >> pseudo_schedule.xml + enter_time=yes + while [[ $enter_time == @(Y|y|Yes|yes|YES) ]] + do + time_entry + if [[ "$entry" == "MOVIE" && "$add_xtra" == @(Y|y|Yes|yes|YES) ]] + then + echo "" >> pseudo_schedule.xml + else + echo "" >> pseudo_schedule.xml + fi + echo "ADD another SHOW or MOVIE?" + read -p 'Y/N: ' enter_time + while [[ "$enter_time" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ADD another SHOW or MOVIE?" + read -p 'Y/N: ' enter_time + done + done + echo "" >> pseudo_schedule.xml + fi + if [[ "$day_of_week" == "Saturday" ]] + then + echo "" >> pseudo_schedule.xml + enter_time=yes + while [[ $enter_time == @(Y|y|Yes|yes|YES) ]] + do + time_entry + if [[ "$entry" == "MOVIE" && "$add_xtra" == @(Y|y|Yes|yes|YES) ]] + then + echo "" >> pseudo_schedule.xml + else + echo "" >> pseudo_schedule.xml + fi + echo "ADD another SHOW or MOVIE?" + read -p 'Y/N: ' enter_time + while [[ "$enter_time" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ADD another SHOW or MOVIE?" + read -p 'Y/N: ' enter_time + done + done + echo "" >> pseudo_schedule.xml + fi + if [[ "$day_of_week" == "Weekends" ]] + then + echo "" >> pseudo_schedule.xml + enter_time=yes + while [[ $enter_time == @(Y|y|Yes|yes|YES) ]] + do + time_entry + if [[ "$entry" == "MOVIE" && "$add_xtra" == @(Y|y|Yes|yes|YES) ]] + then + echo "" >> pseudo_schedule.xml + else + echo "" >> pseudo_schedule.xml + fi + echo "ADD another SHOW or MOVIE?" + read -p 'Y/N: ' enter_time + while [[ "$enter_time" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ADD another SHOW or MOVIE?" + read -p 'Y/N: ' enter_time + done + done + echo "" >> pseudo_schedule.xml + fi + if [[ "$day_of_week" == "Weekdays" ]] + then + echo "" >> pseudo_schedule.xml + enter_time=yes + while [[ $enter_time == @(Y|y|Yes|yes|YES) ]] + do + time_entry + if [[ "$entry" == "MOVIE" && "$add_xtra" == @(Y|y|Yes|yes|YES) ]] + then + echo "" >> pseudo_schedule.xml + else + echo "" >> pseudo_schedule.xml + fi + echo "ADD another SHOW or MOVIE?" + read -p 'Y/N: ' enter_time + while [[ "$enter_time" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ADD another SHOW or MOVIE?" + read -p 'Y/N: ' enter_time + done + done + echo "" >> pseudo_schedule.xml + fi + if [[ "$day_of_week" == "Every Day" ]] + then + echo "" >> pseudo_schedule.xml + enter_time=yes + while [[ $enter_time == @(Y|y|Yes|yes|YES) ]] + do + time_entry + if [[ "$entry" == "MOVIE" && "$add_xtra" == @(Y|y|Yes|yes|YES) ]] + then + echo "" >> pseudo_schedule.xml + else + echo "" >> pseudo_schedule.xml + fi + echo "ADD another SHOW or MOVIE?" + read -p 'Y/N: ' enter_time + while [[ "$enter_time" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ADD another SHOW or MOVIE?" + read -p 'Y/N: ' enter_time + done + done + echo "" >> pseudo_schedule.xml + fi + if [[ "$day_of_week" == "Exit" ]] + then + echo "FINALIZING SCHEDULE FORMATTING..." + echo "" >> pseudo_schedule.xml + echo "CLEANING UP TEMPORARY FILES" + sudo rm xtra.temp + echo "REMOVE BACKUP of Channel $channel_number's previous schedule?" + read -p 'Y/N: ' remove_backup_schedule + while [[ "$remove_backup_schedule" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + clear + echo "++++++++++++++++++++PSEUDO CHANNEL SCHEDULE EDITOR++++++++++++++++++++" + echo "REMOVE BACKUP of Channel $channel_number's previous schedule?" + read -p 'Y/N: ' remove_backup_schedule + done + if [[ "$remove_backup_schedule" == @(Y|y|Yes|yes|YES) ]] + then + sudo rm pseudo_schedule.backup + fi + exit 0 + fi +sleep 1 +clear +echo "++++++++++++++++++++PSEUDO CHANNEL SCHEDULE EDITOR++++++++++++++++++++" +echo "CHOOSE which DAY to SCHEDULE" +echo "1) Sunday 4) Wednesday 7) Saturday 10) Every Day" +echo "2) Monday 5) Thursday 8) Weekends 11) Exit" +echo "3) Tuesday 6) Friday 9) Weekdays" +done diff --git a/main-dir/stop-all-boxes.sh b/main-dir/stop-all-boxes.sh new file mode 100644 index 0000000..48aea2f --- /dev/null +++ b/main-dir/stop-all-boxes.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Function will call stop-all-channels.sh on ALL current boxes. +# The purpose of this falls mainly to a kind of soft "reset", as well as for channel updating. + +CHANNEL_DIR_INCREMENT_SYMBOL="_" +MASTERDIRECTORY="channels" + + +cd .. +BOX_DIR_ARR=( $(find . -maxdepth 1 -type d -name 'channels'"$CHANNEL_DIR_INCREMENT_SYMBOL"'*' -printf "%P\n" | sort -t"$CHANNEL_DIR_INCREMENT_SYMBOL" -n) ) +BOX_DIR_ARR+=("${MASTERDIRECTORY}") +echo "+++++ FOUND THE FOLLOWING BOXES: ${BOX_DIR_ARR[@]}" + + +for BOX in "${BOX_DIR_ARR[@]}" +do + cd ${BOX} + echo "+++++ CURRENTLY STOPPING ${BOX}" + + sudo ./stop-all-channels.sh + + cd .. +done + diff --git a/main-dir/update-channels-from-git.sh b/main-dir/update-channels-from-git.sh index ab66e1c..780a5ad 100644 --- a/main-dir/update-channels-from-git.sh +++ b/main-dir/update-channels-from-git.sh @@ -15,7 +15,6 @@ #---- #----BEGIN EDITABLE VARS---- - if [ $# -gt 1 ]; then echo "ERROR: Please only supply one argument" exit 9999 @@ -32,7 +31,18 @@ OUTPUT_PREV_CHANNEL_PATH=. CHANNEL_DIR_INCREMENT_SYMBOL="_" -FIRST_INSTALL=false +# This does a check for the pseudo-channel_## directories that manage each channel. +# As this script generates those directories on first run, if those directories do +# not exist, then logically this is the first run. +FIND_CHANNEL_FOLDER='' +FIND_CHANNEL_FOLDERS=$(find ./ -name "pseudo-channel_*" -type d) +if [[ "$FIND_CHANNEL_FOLDERS" == '' ]] + then + FIRST_INSTALL=true + else + FIRST_INSTALL=false +fi + #----END EDITABLE VARS------- @@ -54,10 +64,33 @@ FIRST_INSTALL=false # If this is our first install, we will now make all necessary directories to prepare for install if [ "$FIRST_INSTALL" == "true" ]; then - - for (( num=1; num<=5; num++ )) +echo "This is a FIRST INSTALL, ENTER the NUMBER of PSEUDO CHANNELS to SET UP" +read -p 'Number of Channels: ' number_of_channels + if (( $number_of_channels >= 1 )) + then + entry_is_number=yes + else + entry_is_number=no + fi + while [[ $entry_is_number == "no" ]] do + echo "Enter the number of channels you would like this script to generate?" + read -p 'Number of Channels: ' number_of_channels + if (( $number_of_channels >= 1 )) + then + entry_is_number=yes + else + entry_is_number=no + fi + done + for (( num=1; num<="$number_of_channels"; num++ )) + do + if [ $num -ge 1 -a $num -le 9 ] + then + mkdir "pseudo-channel_0$num" + else mkdir "pseudo-channel_$num" + fi done fi @@ -68,14 +101,158 @@ cd github_download $SCRIPT_TO_EXECUTE_PLUS_ARGS #### If necessary, install the required elements as defined by requirements.txt -if [ "$FIRST_INSTALL" == "true" ]; then +#### Also, ask user for information to fill in the plex_token and pseudo_config files +if [ "$FIRST_INSTALL" == "true" ] + then echo "INSTALLING REQUIREMENTS because this is a FIRST RUN" sudo pip install -r requirements.txt + sudo apt-get -y install libxml2-utils recode # NEEDED FOR XML PARSING + cd .. + echo "ENTER the IP ADDRESS of your PLEX SERVER" #GET PLEX SERVER IP AND PORT + read -p 'Plex Server IP: ' server_ip + echo "ENTER the PUBLIC PORT number for your PLEX SERVER" + read -p 'Public Port (default: 32400): ' server_port + if [ "$server_port" == '' ] + then + server_port='32400' + fi + echo "ENTER your PLEX AUTHENTICATION TOKEN" # GET PLEX SERVER AUTH TOKEN + echo "(for help finding token, check here: https://bit.ly/2p7RtOu)" + read -p 'Plex Auth Token: ' server_token + echo "PLEX SERVER is $server_ip:$server_port" + echo "PLEX AUTH TOKEN is $server_token" + echo "SELECT the PLEX CLIENT for this install or ENTER one manually" + # DISPLAY A LIST OF CONNECTED CLIENTS AND ALLOW THE USER TO SELECT ONE OR ENTER ONE THAT ISN'T DISPLAYED + clientlist=$(xmllint --xpath "//Server/@name" "http://$server_ip:$server_port/clients" | sed "s|name=||g" | sed "s|^ ||g" && echo -e " Other") + eval set $clientlist + select ps_client_entry in "$@" + do + if [[ "$ps_client_entry" == "Other" ]] + then + read -p 'Client Name: ' ps_client_entry + ps_client_entry=$(eval echo $ps_client_entry) + fi + ps_client="[\"$ps_client_entry\"]" + break + done + # ALLOW THE USER TO ENTER ALL PLEX LIBRARIES + echo "++++++SETTING UP PLEX LIBRARIES WITH PSEUDO CHANNEL++++++" + echo "Add ALL LIBRARIES that may be used for ANY CHANNEL here." + echo "ENTER the name of EACH Plex library defined as TV SHOWS" + enter_tv_shows=yes + echo -n "[" > tv-libraries.temp + while [[ "$enter_tv_shows" == @(Y|y|Yes|yes|YES) ]] + do + read -p 'TV Show Library Name: ' tv_library_entry + echo -n "\"$tv_library_entry\"" >> tv-libraries.temp + echo "ENTER another TV SHOW LIBRARY?" + read -p 'Y/N: ' enter_tv_shows + while [[ "$enter_tv_shows" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ENTER another TV SHOW LIBRARY?" + read -p 'Y/N: ' enter_tv_shows + done + if [[ "$enter_tv_shows" == @(Y|y|Yes|yes|YES) ]] + then + echo -n ", " >> tv-libraries.temp + fi + done + echo -n "]," >> tv-libraries.temp + echo "ENTER the name of EACH Plex library defined as MOVIES" + enter_movies=yes + echo -n "[" > movie-libraries.temp + while [[ "$enter_movies" == @(Y|y|Yes|yes|YES) ]] + do + read -p 'Movie Library Name: ' movie_library_entry + echo -n "\"$movie_library_entry\"" >> movie-libraries.temp + echo "ENTER another MOVIE LIBRARY?" + read -p 'Y/N: ' enter_movies + while [[ "$enter_movies" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ENTER another MOVIE LIBRARY?" + read -p 'Y/N: ' enter_movies + done + if [[ "$enter_movies" == @(Y|y|Yes|yes|YES) ]] + then + echo -n ", " >> movie-libraries.temp + fi + done + echo -n "]," >> movie-libraries.temp + echo "Use COMMERCIALS in between scheduled content?" # ASK IF THE USER WANTS TO ADD COMMERCIAL LIBRARIES + read -p 'Y/N: ' enter_commercials + while [[ "$enter_commercials" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "Use COMMERCIALS in between scheduled content?" + read -p 'Y/N: ' enter_commercials + done + if [[ "$enter_commercials" == @("Y"|"y"|"yes"|"Yes"|"YES") ]] + then + commercials_true=true + echo "ENTER the name of EACH Plex library defined as COMMERCIALS" + echo -n "[" > commercial-libraries.temp + else + commercials_true=false + fi + while [[ "$enter_commercials" == @(Y|y|Yes|yes|YES) ]] + do + read -p 'Commercial Library Name: ' commercial_library_entry + echo -n "\"$commercial_library_entry\", " >> commercial-libraries.temp + echo "ENTER another COMMERCIAL LIBRARY?" + read -p 'Y/N: ' enter_commercials + while [[ "$enter_commercials" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ENTER another COMMERCIAL LIBRARY?" + read -p 'Y/N: ' enter_commercials + done + done + if [[ "$commercials_true" == "true" ]] + then + truncate -s-2 commercial-libraries.temp + echo -n "]," >> commercial-libraries.temp + fi + # DEFINE THE DAILY RESET TIME + echo "Set the TIME for PSEUDO CHANNEL to GENERATE the DAILY SCHEDULE" + echo "USE 24H FORMAT (ex: 23:00)" + read -p 'Schedule Reset Time: ' reset_time_entry + reset_time_formatted=$(echo $reset_time_entry | sed -e "s|^[0-9]:.*|0$reset_time_entry|g") + reset_time_hour="${reset_time_formatted:0:2}" + reset_time_hour=$(echo $reset_time_hour | sed -e "s|^[0]||") + reset_time_minute="${reset_time_formatted: -2}" + reset_time_minute=$(echo $reset_time_minute | sed "-e s|^[0]||") + # SET UP CRON JOB TO RUN DAILY RESET + sudo crontab -l | grep -v 'daily-cron.sh' | crontab - + sudo echo \#\!/bin/bash > ./daily-cron.sh && echo "cd $PWD" >> ./daily-cron.sh && echo "sudo ./generate-channels-daily-schedules.sh" >> ./daily-cron.sh + ( sudo crontab -l ; echo "$reset_time_minute $reset_time_hour * * * $PWD/daily-cron.sh" ) | sudo crontab - + + #### WRITE VARIABLES TO TOKEN AND CONFIG FILES #### + reset_time="\"$reset_time_entry\"" + echo "token = '$server_token'" > plex_token.py # WRITE PLEX SERVER TOKEN TO FILE + echo "baseurl = 'http://$server_ip:$server_port'" >> plex_token.py # WRITE PLEX URL TO FILE + tv_libraries=$(cat tv-libraries.temp) + sudo sed -i "s/plexClients = .*/plexClients = $ps_client/" github_download/both-dir/pseudo_config.py # WRITE CLIENT TO CONFIG + sudo sed -i "/.\"TV Shows\" :*./c\ \"TV Shows\" : $tv_libraries" github_download/both-dir/pseudo_config.py # WRITE TV LIBRARIES TO CONFIG + movie_libraries=$(cat movie-libraries.temp) + sudo sed -i "/.\"Movies\" :*./c\ \"Movies\" : $movie_libraries" github_download/both-dir/pseudo_config.py # WRITE MOVIE LIBRARIES TO CONFIG + if [[ "$commercials_true" == "true" ]] #WRITE COMMERCIAL LIBRARIES TO CONFIG + then + commercial_libraries=$(cat commercial-libraries.temp) + sudo sed -i "/.\"Commercials\" :*./c\ \"Commercials\" : $commercial_libraries" github_download/both-dir/pseudo_config.py + fi + # WRITE OTHER CONFIG OPTIONS TO THE CONFIG FILE + sudo sed -i "s/useCommercialInjection =.*/useCommercialInjection = $commercials_true/" github_download/both-dir/pseudo_config.py + sudo sed -i "s/dailyUpdateTime =.*/dailyUpdateTime = $reset_time/" github_download/both-dir/pseudo_config.py + sudo sed -i "s/controllerServerPath =.*/controllerServerPath = \"\"/" github_download/both-dir/pseudo_config.py + sudo sed -i "s/controllerServerPort =.*/controllerServerPort = \"\"/" github_download/both-dir/pseudo_config.py + sudo sed -i "s/debug_mode =.*/debug_mode = False/" github_download/both-dir/pseudo_config.py + # CLEAN UP TEMP FILES AND COPY CONFIG + sudo rm movie-libraries.temp + sudo rm tv-libraries.temp + sudo rm commercial-libraries.temp + sudo cp github_download/both-dir/pseudo_config.py ./ + else + cd .. fi -cd .. - - #### With information downloaded, we will first go to each channel folder and update important things #### This will take the following form #### - Enter folder @@ -92,31 +269,31 @@ if [ "${#CHANNEL_DIR_ARR[@]}" -gt 1 ]; then do echo "+++++ Trying to update channel:"./"$channel" cd "$channel" - + # Export critical files mkdir ../.pseudo-temp - + cp ./pseudo-channel.db ../.pseudo-temp 2>/dev/null cp ./pseudo_schedule.xml ../.pseudo-temp 2>/dev/null cp ./pseudo_config.py ../.pseudo-temp 2>/dev/null - + # Copy new elements - + cp -r ../github_download/channel-dir/* . cp -r ../github_download/both-dir/* . - + # Replace the files originally moved - + cp ../.pseudo-temp/pseudo-channel.db . 2>/dev/null cp ../.pseudo-temp/pseudo_schedule.xml . 2>/dev/null - + cp ../.pseudo-temp/pseudo_config.py . 2>/dev/null - + rm -rf ../.pseudo-temp - + cd .. done fi @@ -124,7 +301,7 @@ fi #### Now we will return to the original file, and ensure that everything is in the main folder #### This will include the following form #### - Return to folder -#### - Copy config, db, and tolken file +#### - Copy config, db, and token file #### - Copy relevant files from github #### - Replace files originally removed echo "Updating channels folder" @@ -159,3 +336,8 @@ rm -rf ./github_download sudo chmod -R 777 . echo "Update Complete" + +#### Write variables to config.cache +sudo sed -i "s/server_ip=.*/server_ip=$server_ip/" config.cache +sudo sed -i "s/server_port=.*/server_port=$server_port/" config.cache +sudo sed -i "s/server_token=.*/server_token=$server_token/" config.cache diff --git a/main-dir/update_box.sh b/main-dir/update_box.sh new file mode 100644 index 0000000..942cf26 --- /dev/null +++ b/main-dir/update_box.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +# Purpose of this script is to update ALL boxes with the most current version of the script. + +# Flow of the script +# Go to home directory, identify ALL boxes that need updating +# Run "update-channels-from-git.sh" in all of them. +# System link all databases when complete +CHANNEL_DIR_INCREMENT_SYMBOL="_" +MASTERDIRECTORY="channels" +BRANCH="develop" + + +cd .. +BOX_DIR_ARR=( $(find . -maxdepth 1 -type d -name 'channels'"$CHANNEL_DIR_INCREMENT_SYMBOL"'*' -printf "%P\n" | sort -t"$CHANNEL_DIR_INCREMENT_SYMBOL" -n) ) +BOX_DIR_ARR+=("${MASTERDIRECTORY}") +echo "+++++ FOUND THE FOLLOWING BOXES: ${BOX_DIR_ARR[@]}" + +for BOX in "${BOX_DIR_ARR[@]}" +do + cd ${BOX} + echo "+++++ CURRENTLY UPDATING ${BOX}" + # Sanity check, can we even update? + if [ ! -e "update-channels-from-git.sh" ]; then + echo "ERROR AT ${BOX}: No file to update with!" + exit 75 + fi + + # Update the given box with the gitHub repository branch selected. + sudo ./update-channels-from-git.sh ${BRANCH} + + # Now we need to go in and perform the symlink again + CHANNEL_DIR_ARR=( $(find . -maxdepth 1 -type d -name '*'"$CHANNEL_DIR_INCREMENT_SYMBOL"'[[:digit:]]*' -printf "%P\n" | sort -t"$CHANNEL_DIR_INCREMENT_SYMBOL" -n) ) + if [ "${#CHANNEL_DIR_ARR[@]}" -gt 1 ]; then + + echo "+++++ There are ${#CHANNEL_DIR_ARR[@]} channels detected." + if [ ! "${BOX}" == "${MASTERDIRECTORY}" ]; then + echo "+++++ symlinking channels in ${BOX}" + for i in "${!CHANNEL_DIR_ARR[@]}" + do + echo "+++++ Linking Directories in ${CHANNEL_DIR_ARR[i]}" + cd ${CHANNEL_DIR_ARR[i]} + MASTER_CHANNEL="../../${MASTERDIRECTORY}/${CHANNEL_DIR_ARR[i]}" + + ln -sf "${MASTER_CHANNEL}/pseudo-channel.db" + + cd .. + done + else + echo "+++++ NOT symlinking these channels; these are master!!!" + + fi + fi + + cd .. +done