From bf994a91da1d1fa812a3de9b10c822567d1401a8 Mon Sep 17 00:00:00 2001 From: mutto233 <39921339+mutto233@users.noreply.github.com> Date: Sat, 7 Jul 2018 22:09:40 -0400 Subject: [PATCH 01/28] Update of Schedule Controller Bug reports were coming in where like-named shows were not all being played. This fix attempts to solve the problem, by checking show title AND duration. This ensures that you find exactly the right thing to play. The fix has also been translated to the website creation as well, so the correct artwork will be portrayed for each movie/show. --- both-dir/src/PseudoDailyScheduleController.py | 79 +++++++++++++++---- 1 file changed, 65 insertions(+), 14 deletions(-) diff --git a/both-dir/src/PseudoDailyScheduleController.py b/both-dir/src/PseudoDailyScheduleController.py index 26ffab2..76aad7e 100644 --- a/both-dir/src/PseudoDailyScheduleController.py +++ b/both-dir/src/PseudoDailyScheduleController.py @@ -10,6 +10,7 @@ import thread,SocketServer,SimpleHTTPServer from plexapi.server import PlexServer from yattag import Doc from yattag import indent +import pseudo_config as config class PseudoDailyScheduleController(): @@ -47,14 +48,30 @@ class PseudoDailyScheduleController(): * @return string: full path of to the show image * ''' - def get_show_photo(self, section, title): + def get_show_photo(self, section, showtitle, durationAmount): backgroundImagePath = None backgroundImgURL = '' + # First, we are going to search for movies/commercials try: - backgroundImagePath = self.PLEX.library.section(section).get(title) + 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 @@ -147,6 +164,10 @@ class PseudoDailyScheduleController(): def get_html_from_daily_schedule(self, currentTime, bgImageURL, datalist, nowPlayingTitle): now = datetime.now() + #mutto233 put this here, because to be honest, isn't the current time always now? + if currentTime != None: + currentTime=now + time = now.strftime("%B %d, %Y") doc, tag, text, line = Doc( @@ -270,6 +291,8 @@ class PseudoDailyScheduleController(): (timeBEnd - currentTime).total_seconds() >= 0: #if self.DEBUG: + #print "%s, %s, %s" % (currentTime, timeBStart, timeBEnd) + #print "%s, %s" % ((currentTime - timeBStart).total_seconds(), (timeBEnd - currentTime).total_seconds()) print "+++++ Currently Playing:", row[3] with tag('tr', klass='bg-info'): @@ -378,25 +401,53 @@ class PseudoDailyScheduleController(): * @return null * ''' - def play_media(self, mediaType, mediaParentTitle, mediaTitle, offset, customSectionName): + def play_media(self, mediaType, mediaParentTitle, mediaTitle, offset, customSectionName, durationAmount): try: if mediaType == "TV Shows": - print "Here, Trying to play custom type: ", customSectionName +# 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: - if item.title == mediaTitle: +# 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": - movie = self.PLEX.library.section(customSectionName).get(mediaTitle) + 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": - movie = self.PLEX.library.section(customSectionName).get(mediaTitle) + # 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) @@ -459,13 +510,13 @@ class PseudoDailyScheduleController(): print "Here, row[13]", row[13] - self.play_media(row[11], row[6], row[3], offset, 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[6] if row[11] == "TV Shows" else row[3], row[7] ), datalist, row[6] + " - " + row[3] if row[11] == "TV Shows" else row[3] @@ -479,7 +530,7 @@ class PseudoDailyScheduleController(): timeB, self.get_show_photo( row[13], - row[6] if row[11] == "TV Shows" else row[3] + row[6] if row[11] == "TV Shows" else row[3], row[7] ), datalist ) @@ -513,13 +564,13 @@ class PseudoDailyScheduleController(): if currentTime.second == timeB.second: print("Starting Media: " + row[3]) print(row) - self.play_media(row[11], row[6], row[3], row[13]) + 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[6] if row[11] == "TV Shows" else row[3], row[7] ), datalist, row[6] + " - " + row[3] if row[11] == "TV Shows" else row[3] @@ -533,7 +584,7 @@ class PseudoDailyScheduleController(): timeB, self.get_show_photo( row[13], - row[6] if row[11] == "TV Shows" else row[3] + row[6] if row[11] == "TV Shows" else row[3], row[7] ), datalist ) @@ -576,7 +627,7 @@ class PseudoDailyScheduleController(): return self.get_show_photo( row[13], - row[6] if row[11] == "TV Shows" else row[3] + row[6] if row[11] == "TV Shows" else row[3], row[7] ) else: From c94eb7dd6848dc5da4b42101dba32fbcff4d68cf Mon Sep 17 00:00:00 2001 From: mutto233 <39921339+mutto233@users.noreply.github.com> Date: Sat, 7 Jul 2018 23:09:27 -0400 Subject: [PATCH 02/28] Random TV Series episode capabilities added Now, there is the ability to run random episodes in a TV series, without ruining your place in the series designation. To do so, simply edit your xml file so the lines title=<>, and the line's type=random. --- both-dir/PseudoChannel.py | 38 ++++++++++++++++----------- both-dir/src/PseudoChannelDatabase.py | 8 ++++++ 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/both-dir/PseudoChannel.py b/both-dir/PseudoChannel.py index 660bf53..f1d3dbc 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: @@ -1088,16 +1094,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/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): From fce926936e56b9b5a8bebf9c0fd0a04b838e664e Mon Sep 17 00:00:00 2001 From: mutto233 <39921339+mutto233@users.noreply.github.com> Date: Mon, 9 Jul 2018 01:14:09 -0400 Subject: [PATCH 05/28] Commercial logic improvement; website creation changes Modifications were made to allow for commercials to be generated for the last show before midnight. This had been an issue in the past, and should be fixed with this update. Further modifications were also made to the -m flag script, hopefully removing the issues surrounding multiple items being declared running. --- both-dir/src/PseudoChannelCommercial.py | 28 +++++++++- both-dir/src/PseudoDailyScheduleController.py | 53 ++++++++++++++----- 2 files changed, 67 insertions(+), 14 deletions(-) diff --git a/both-dir/src/PseudoChannelCommercial.py b/both-dir/src/PseudoChannelCommercial.py index ab2c623..8d1b54a 100644 --- a/both-dir/src/PseudoChannelCommercial.py +++ b/both-dir/src/PseudoChannelCommercial.py @@ -44,8 +44,32 @@ class PseudoChannelCommercial(): 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) + 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 > curr_item_start_time: + # 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 + 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 diff --git a/both-dir/src/PseudoDailyScheduleController.py b/both-dir/src/PseudoDailyScheduleController.py index 76aad7e..e4bd0ed 100644 --- a/both-dir/src/PseudoDailyScheduleController.py +++ b/both-dir/src/PseudoDailyScheduleController.py @@ -164,10 +164,13 @@ class PseudoDailyScheduleController(): 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 = now.strftime("%B %d, %Y") doc, tag, text, line = Doc( @@ -272,9 +275,15 @@ class PseudoDailyScheduleController(): 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'): @@ -287,12 +296,14 @@ class PseudoDailyScheduleController(): 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 "%s, %s, %s" % (currentTime, timeBStart, timeBEnd) - #print "%s, %s" % ((currentTime - timeBStart).total_seconds(), (timeBEnd - currentTime).total_seconds()) + 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'): @@ -599,7 +610,9 @@ class PseudoDailyScheduleController(): 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: @@ -611,8 +624,10 @@ class PseudoDailyScheduleController(): 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) @@ -620,8 +635,13 @@ class PseudoDailyScheduleController(): #print currentTime.minute #print timeBStart.minute - if (currentTime - timeBStart).total_seconds() >= 0 and \ - (timeBEnd - currentTime).total_seconds() >= 0: + 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]) @@ -642,7 +662,9 @@ class PseudoDailyScheduleController(): 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: @@ -654,8 +676,10 @@ class PseudoDailyScheduleController(): 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) @@ -663,8 +687,13 @@ class PseudoDailyScheduleController(): #print currentTime.minute #print timeBStart.minute - if (currentTime - timeBStart).total_seconds() >= 0 and \ - (timeBEnd - currentTime).total_seconds() >= 0 : + 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]) From d0b9f4bfcf4fbbc26eafba310945a414691a52bb Mon Sep 17 00:00:00 2001 From: mutto233 <39921339+mutto233@users.noreply.github.com> Date: Mon, 9 Jul 2018 10:58:35 -0400 Subject: [PATCH 06/28] Installer update The installer has been made a bit more user friendly. - To install, simply PLACE the installer in the folder you would like to use. You can make it yourself with mkdir, then drop it in there. first_run is still a valid variable, and will make some "pseudo-channel_#" files for you to start - Input is now accepted as either "develop" or "master" to choose the branch you would like to download from "master" will download the master branch and install/update "develop" will download the develop branch and install/update. --- main-dir/update-channels-from-git.sh | 30 +++++++++++++--------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/main-dir/update-channels-from-git.sh b/main-dir/update-channels-from-git.sh index f91f8f3..ab66e1c 100644 --- a/main-dir/update-channels-from-git.sh +++ b/main-dir/update-channels-from-git.sh @@ -4,6 +4,8 @@ #---- # Simple script to update every channel with updates from the github repo. # BACKUP EACH XML/DB IN EACH CHANNEL. +# Code will take in one argument: To take from the master or development branch +# For ALL installs, simply place this file in the location you would like your channels to be installed/updated #---- #---- @@ -14,14 +16,22 @@ #----BEGIN EDITABLE VARS---- -SCRIPT_TO_EXECUTE_PLUS_ARGS='git clone https://github.com/mutto233/pseudo-channel . --branch master' +if [ $# -gt 1 ]; then + echo "ERROR: Please only supply one argument" + exit 9999 +elif [ "$1" == "develop" ]; then + echo "Downloading the develop branch" + SCRIPT_TO_EXECUTE_PLUS_ARGS='git clone https://github.com/mutto233/pseudo-channel . --branch develop' + +else + echo "Downloading the master branch" + SCRIPT_TO_EXECUTE_PLUS_ARGS='git clone https://github.com/mutto233/pseudo-channel . --branch master' +fi OUTPUT_PREV_CHANNEL_PATH=. CHANNEL_DIR_INCREMENT_SYMBOL="_" -INSTALL_FOLDER="channels" - FIRST_INSTALL=false #----END EDITABLE VARS------- @@ -44,8 +54,6 @@ 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 - mkdir $INSTALL_FOLDER - cd $INSTALL_FOLDER for (( num=1; num<=5; num++ )) do @@ -54,15 +62,6 @@ if [ "$FIRST_INSTALL" == "true" ]; then fi -# Sanity check, are we in the install folder? This is just to make sure we don't run into errors. -if [ ! -d "../$INSTALL_FOLDER" ]; then - echo "ERROR: NOT IN '$INSTALL_FOLDER' FOLDER, PLEASE MAKE SURE WE ARE IN HERE!" - echo "Did you mean to set FIRST_RUN=true?" - exit 9999 -fi - - - #### Next, let's download the latest master version of information from GitHub and store it in a temporary folder mkdir github_download cd github_download @@ -157,7 +156,6 @@ rm -rf ./.pseudo-temp rm -rf ./github_download #### Change permissions to 777 for all files, so that things will run -cd .. -sudo chmod -R 777 "./$INSTALL_FOLDER" +sudo chmod -R 777 . echo "Update Complete" From 8a56aec40e139e749e860ed0f76f9f87c0212e6b Mon Sep 17 00:00:00 2001 From: mutto233 <39921339+mutto233@users.noreply.github.com> Date: Mon, 9 Jul 2018 22:39:24 -0400 Subject: [PATCH 07/28] Bug fix Had issue with PseudoChannelCommercial scheduling over 24 hours of commercials; this has been fixed. --- both-dir/src/PseudoChannelCommercial.py | 316 ++++++++++++------------ 1 file changed, 158 insertions(+), 158 deletions(-) diff --git a/both-dir/src/PseudoChannelCommercial.py b/both-dir/src/PseudoChannelCommercial.py index 8d1b54a..01c646a 100644 --- a/both-dir/src/PseudoChannelCommercial.py +++ b/both-dir/src/PseudoChannelCommercial.py @@ -1,159 +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) - # 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 > curr_item_start_time: - # 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 - 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) +"""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) + # 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: + # 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 From b4564345ea9fb4ca8b538180bf881aa2b53339e5 Mon Sep 17 00:00:00 2001 From: mutto233 <39921339+mutto233@users.noreply.github.com> Date: Tue, 10 Jul 2018 01:23:02 -0400 Subject: [PATCH 08/28] PlexClient Override feature added New feature! Now, if your directory is named "channels_" your script will override and always play to the client . This is going to be helpful for when we add mutli-box support. --- both-dir/src/PseudoDailyScheduleController.py | 1459 +++++++++-------- 1 file changed, 733 insertions(+), 726 deletions(-) diff --git a/both-dir/src/PseudoDailyScheduleController.py b/both-dir/src/PseudoDailyScheduleController.py index e4bd0ed..78b9f6d 100644 --- a/both-dir/src/PseudoDailyScheduleController.py +++ b/both-dir/src/PseudoDailyScheduleController.py @@ -1,727 +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 -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 = 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): - - 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)) +#!/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 = 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 From 465b24b1c35cd71f357255e103b1167b82277bd0 Mon Sep 17 00:00:00 2001 From: mutto233 <39921339+mutto233@users.noreply.github.com> Date: Tue, 10 Jul 2018 01:40:08 -0400 Subject: [PATCH 09/28] Multi-Box Editing Added Two new functions added, "update_box " will create a new folder that is identical to your master folder, and name it "channels_" so it will play to the correct client. "update_box.sh" will go through ALL made boxes and update from gitHub (either master or develop branch, depending on what you want). --- main-dir/create_box.sh | 53 +++++++++++++++++++++++++++++++++++++++ main-dir/update_box.sh | 56 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 main-dir/create_box.sh create mode 100644 main-dir/update_box.sh 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/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 From 8a97233523928cd1ed906567c305d74a1a5e6021 Mon Sep 17 00:00:00 2001 From: mutto233 <39921339+mutto233@users.noreply.github.com> Date: Wed, 11 Jul 2018 11:08:44 -0400 Subject: [PATCH 10/28] Added stop-all-boxes Shell script "stop-all-boxes.sh" has been added, so if there are multiple sets of boxes and you want to turn them all off you can. --- main-dir/stop-all-boxes.sh | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 main-dir/stop-all-boxes.sh 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 + From 27f4cbef9b584eb9363085ddad93ac8b215ede40 Mon Sep 17 00:00:00 2001 From: mutto233 <39921339+mutto233@users.noreply.github.com> Date: Fri, 13 Jul 2018 00:09:23 -0400 Subject: [PATCH 11/28] Minor website fix Oopsie! I left in a thing that kept the date on your websites as 1/1/1990. This has been fixed by this update. --- both-dir/src/PseudoDailyScheduleController.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/both-dir/src/PseudoDailyScheduleController.py b/both-dir/src/PseudoDailyScheduleController.py index 78b9f6d..b10c5bf 100644 --- a/both-dir/src/PseudoDailyScheduleController.py +++ b/both-dir/src/PseudoDailyScheduleController.py @@ -171,7 +171,7 @@ class PseudoDailyScheduleController(): currentTime=now - time = now.strftime("%B %d, %Y") + time = datetime.now().strftime("%B %d, %Y") doc, tag, text, line = Doc( ).ttl() From 77ddb7f998d488e871b8976e0a569c9010ec20b6 Mon Sep 17 00:00:00 2001 From: mutto233 <39921339+mutto233@users.noreply.github.com> Date: Sun, 15 Jul 2018 23:31:22 -0400 Subject: [PATCH 12/28] Strict_Time Commercial Fix Users pointed out that there was an issue where the strict_time entries were still creating 24 hr sets of commercials. This issue has been fixed; if there is an issue of overlap with strict time, no commercials will be played as expected. --- both-dir/PseudoChannel.py | 6 ++++-- both-dir/src/PseudoChannelCommercial.py | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/both-dir/PseudoChannel.py b/both-dir/PseudoChannel.py index f1d3dbc..1498340 100644 --- a/both-dir/PseudoChannel.py +++ b/both-dir/PseudoChannel.py @@ -719,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) @@ -746,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) diff --git a/both-dir/src/PseudoChannelCommercial.py b/both-dir/src/PseudoChannelCommercial.py index 01c646a..77705d2 100644 --- a/both-dir/src/PseudoChannelCommercial.py +++ b/both-dir/src/PseudoChannelCommercial.py @@ -41,7 +41,7 @@ class PseudoChannelCommercial(): commercial = tuple(commercial_as_list) return commercial - def get_commercials_to_place_between_media(self, last_ep, now_ep): + 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') @@ -55,7 +55,7 @@ class PseudoChannelCommercial(): 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: + 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" From 73e5209eb5396d9fe3e5874842de2a12dae83a18 Mon Sep 17 00:00:00 2001 From: Moe Fwacky Date: Sat, 15 Sep 2018 17:08:45 -0700 Subject: [PATCH 15/28] Add files via upload --- main-dir/update-channels-from-git2.sh | 161 ++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 main-dir/update-channels-from-git2.sh diff --git a/main-dir/update-channels-from-git2.sh b/main-dir/update-channels-from-git2.sh new file mode 100644 index 0000000..ab66e1c --- /dev/null +++ b/main-dir/update-channels-from-git2.sh @@ -0,0 +1,161 @@ +#!/bin/bash +# file: update-channels-from-git.sh + +#---- +# Simple script to update every channel with updates from the github repo. +# BACKUP EACH XML/DB IN EACH CHANNEL. +# Code will take in one argument: To take from the master or development branch +# For ALL installs, simply place this file in the location you would like your channels to be installed/updated +#---- + +#---- +# To Use: +# chmod +x update-channels-from-git.sh +# ./update-channels-from-git.sh +#---- + +#----BEGIN EDITABLE VARS---- + +if [ $# -gt 1 ]; then + echo "ERROR: Please only supply one argument" + exit 9999 +elif [ "$1" == "develop" ]; then + echo "Downloading the develop branch" + SCRIPT_TO_EXECUTE_PLUS_ARGS='git clone https://github.com/mutto233/pseudo-channel . --branch develop' + +else + echo "Downloading the master branch" + SCRIPT_TO_EXECUTE_PLUS_ARGS='git clone https://github.com/mutto233/pseudo-channel . --branch master' +fi + +OUTPUT_PREV_CHANNEL_PATH=. + +CHANNEL_DIR_INCREMENT_SYMBOL="_" + +FIRST_INSTALL=false + +#----END EDITABLE VARS------- + + + +# First, we need to figure out if we have actually installed this already +# To do this, we are going to check if we go up one level we have the folder "channels" +# We will also check if the current directory has "channels" +# FIRST_INSTALL=true + +# if [ -d "$INSTALL_FOLDER" ] || [ -d "../$INSTALL_FOLDER" ]; then + # echo "This is NOT the first install" + # FIRST_INSTALL=false +# else + # echo "This IS the first install, installing 'channels' directory in current directory with five starting channels." + # FIRST_INSTALL=true +# fi + + +# 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++ )) + do + mkdir "pseudo-channel_$num" + done +fi + + +#### Next, let's download the latest master version of information from GitHub and store it in a temporary folder +mkdir github_download +cd github_download +$SCRIPT_TO_EXECUTE_PLUS_ARGS + +#### If necessary, install the required elements as defined by requirements.txt +if [ "$FIRST_INSTALL" == "true" ]; then + echo "INSTALLING REQUIREMENTS because this is a FIRST RUN" + sudo pip install -r requirements.txt +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 +#### - Copy database, xml, and config file to temporary folder +#### - copy all files from the download/channel-dir and download/both-dir to the channel folder. +#### - Replace files that were originally removed + +# Scan the dir to see how many channels there are, store them in an arr. +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 channel in "${CHANNEL_DIR_ARR[@]}" + 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 + +#### 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 relevant files from github +#### - Replace files originally removed +echo "Updating channels folder" + +# Export critical files +mkdir .pseudo-temp + +cp ./pseudo-channel.db .pseudo-temp 2>/dev/null + +cp ./pseudo_config.py .pseudo-temp 2>/dev/null + +cp ./plex_token.py .pseudo-temp 2>/dev/null + +# Copy new elements + +cp -r ./github_download/main-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_config.py . 2>/dev/null + +cp ./.pseudo-temp/plex_token.py . 2>/dev/null + +rm -rf ./.pseudo-temp + +rm -rf ./github_download + +#### Change permissions to 777 for all files, so that things will run +sudo chmod -R 777 . + +echo "Update Complete" From cb0329317b516782f3d66aafb914d198212c1566 Mon Sep 17 00:00:00 2001 From: Moe Fwacky Date: Sat, 15 Sep 2018 17:08:59 -0700 Subject: [PATCH 16/28] Delete update-channels-from-git.sh --- main-dir/update-channels-from-git.sh | 161 --------------------------- 1 file changed, 161 deletions(-) delete mode 100644 main-dir/update-channels-from-git.sh diff --git a/main-dir/update-channels-from-git.sh b/main-dir/update-channels-from-git.sh deleted file mode 100644 index ab66e1c..0000000 --- a/main-dir/update-channels-from-git.sh +++ /dev/null @@ -1,161 +0,0 @@ -#!/bin/bash -# file: update-channels-from-git.sh - -#---- -# Simple script to update every channel with updates from the github repo. -# BACKUP EACH XML/DB IN EACH CHANNEL. -# Code will take in one argument: To take from the master or development branch -# For ALL installs, simply place this file in the location you would like your channels to be installed/updated -#---- - -#---- -# To Use: -# chmod +x update-channels-from-git.sh -# ./update-channels-from-git.sh -#---- - -#----BEGIN EDITABLE VARS---- - -if [ $# -gt 1 ]; then - echo "ERROR: Please only supply one argument" - exit 9999 -elif [ "$1" == "develop" ]; then - echo "Downloading the develop branch" - SCRIPT_TO_EXECUTE_PLUS_ARGS='git clone https://github.com/mutto233/pseudo-channel . --branch develop' - -else - echo "Downloading the master branch" - SCRIPT_TO_EXECUTE_PLUS_ARGS='git clone https://github.com/mutto233/pseudo-channel . --branch master' -fi - -OUTPUT_PREV_CHANNEL_PATH=. - -CHANNEL_DIR_INCREMENT_SYMBOL="_" - -FIRST_INSTALL=false - -#----END EDITABLE VARS------- - - - -# First, we need to figure out if we have actually installed this already -# To do this, we are going to check if we go up one level we have the folder "channels" -# We will also check if the current directory has "channels" -# FIRST_INSTALL=true - -# if [ -d "$INSTALL_FOLDER" ] || [ -d "../$INSTALL_FOLDER" ]; then - # echo "This is NOT the first install" - # FIRST_INSTALL=false -# else - # echo "This IS the first install, installing 'channels' directory in current directory with five starting channels." - # FIRST_INSTALL=true -# fi - - -# 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++ )) - do - mkdir "pseudo-channel_$num" - done -fi - - -#### Next, let's download the latest master version of information from GitHub and store it in a temporary folder -mkdir github_download -cd github_download -$SCRIPT_TO_EXECUTE_PLUS_ARGS - -#### If necessary, install the required elements as defined by requirements.txt -if [ "$FIRST_INSTALL" == "true" ]; then - echo "INSTALLING REQUIREMENTS because this is a FIRST RUN" - sudo pip install -r requirements.txt -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 -#### - Copy database, xml, and config file to temporary folder -#### - copy all files from the download/channel-dir and download/both-dir to the channel folder. -#### - Replace files that were originally removed - -# Scan the dir to see how many channels there are, store them in an arr. -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 channel in "${CHANNEL_DIR_ARR[@]}" - 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 - -#### 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 relevant files from github -#### - Replace files originally removed -echo "Updating channels folder" - -# Export critical files -mkdir .pseudo-temp - -cp ./pseudo-channel.db .pseudo-temp 2>/dev/null - -cp ./pseudo_config.py .pseudo-temp 2>/dev/null - -cp ./plex_token.py .pseudo-temp 2>/dev/null - -# Copy new elements - -cp -r ./github_download/main-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_config.py . 2>/dev/null - -cp ./.pseudo-temp/plex_token.py . 2>/dev/null - -rm -rf ./.pseudo-temp - -rm -rf ./github_download - -#### Change permissions to 777 for all files, so that things will run -sudo chmod -R 777 . - -echo "Update Complete" From 5fcb50ec21f9e1e5537f5d14c46440acdf9194c9 Mon Sep 17 00:00:00 2001 From: Moe Fwacky Date: Sat, 15 Sep 2018 17:09:17 -0700 Subject: [PATCH 17/28] Rename update-channels-from-git2.sh to update-channels-from-git.sh --- .../{update-channels-from-git2.sh => update-channels-from-git.sh} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename main-dir/{update-channels-from-git2.sh => update-channels-from-git.sh} (100%) diff --git a/main-dir/update-channels-from-git2.sh b/main-dir/update-channels-from-git.sh similarity index 100% rename from main-dir/update-channels-from-git2.sh rename to main-dir/update-channels-from-git.sh From fdbd7cfc3ec9b3188316b653bbfc4e61f519e98d Mon Sep 17 00:00:00 2001 From: Moe Fwacky Date: Mon, 17 Sep 2018 01:23:36 -0700 Subject: [PATCH 18/28] Installer update --- main-dir/update-channels-from-git.sh | 191 ++++++++++++++++++++++++--- 1 file changed, 175 insertions(+), 16 deletions(-) diff --git a/main-dir/update-channels-from-git.sh b/main-dir/update-channels-from-git.sh index ab66e1c..bf54a3f 100644 --- a/main-dir/update-channels-from-git.sh +++ b/main-dir/update-channels-from-git.sh @@ -32,7 +32,17 @@ 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,140 @@ 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 + cd .. + echo "ENTER the IP ADDRESS of your PLEX SERVER" + 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" + 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" + # Gets a list of Plex clients connected and registered with the server + clientlist=$(xmllint --xpath "//Server/@name" "http://192.168.1.140:32400/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 + # Get the names of Plex libraries for the config + 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 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 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 LIBRARY?" + read -p 'Y/N: ' enter_movies + while [[ "$enter_movies" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ENTER another 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 LIBRARY?" + read -p 'Y/N: ' enter_commercials + while [[ "$enter_commercials" != @(Y|y|Yes|yes|YES|N|n|No|no|NO) ]] + do + echo "ENTER another 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 + echo "Set the TIME for PSEUDO CHANNEL to GENERATE the DAILY SCHEDULE" + echo "USE either 24h FORMAT (ex: 23:00) or 12h FORMAT (11:00 PM)" + read -p 'Schedule Reset Time: ' reset_time + reset_time="\"$reset_time\"" + echo "token = '$server_token'" > plex_token.py + echo "baseurl = 'http://$server_ip:$server_port'" >> plex_token.py + tv_libraries=$(cat tv-libraries.temp) + sudo sed -i "s/plexClients = .*/plexClients = $ps_client/" github_download/both-dir/pseudo_config.py + sudo sed -i "/.\"TV Shows\" :*./c\ \"TV Shows\" : $tv_libraries" github_download/both-dir/pseudo_config.py + movie_libraries=$(cat movie-libraries.temp) + sudo sed -i "/.\"Movies\" :*./c\ \"Movies\" : $movie_libraries" github_download/both-dir/pseudo_config.py + if [[ "$commercials_true" == "true" ]] + then + commercial_libraries=$(cat commercial-libraries.temp) + sudo sed -i "/.\"Commercials\" :*./c\ \"Commercials\" : $commercial_libraries" github_download/both-dir/pseudo_config.py + fi + 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 + 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,29 +251,29 @@ 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 .. @@ -124,7 +283,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" From 3585a6bd6891b7a492d7fd29f56c2d3fd7770f5c Mon Sep 17 00:00:00 2001 From: Moe Fwacky Date: Thu, 20 Sep 2018 18:54:35 -0700 Subject: [PATCH 19/28] Add files via upload --- main-dir/update-channels-from-git.sh | 69 +++++++++++++++++----------- 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/main-dir/update-channels-from-git.sh b/main-dir/update-channels-from-git.sh index bf54a3f..fb6b098 100644 --- a/main-dir/update-channels-from-git.sh +++ b/main-dir/update-channels-from-git.sh @@ -16,14 +16,15 @@ #----BEGIN EDITABLE VARS---- -if [ $# -gt 1 ]; then +if [ $# -gt 1 ] + then echo "ERROR: Please only supply one argument" exit 9999 -elif [ "$1" == "develop" ]; then + elif [ "$1" == "develop" ] + then echo "Downloading the develop branch" SCRIPT_TO_EXECUTE_PLUS_ARGS='git clone https://github.com/mutto233/pseudo-channel . --branch develop' - -else + else echo "Downloading the master branch" SCRIPT_TO_EXECUTE_PLUS_ARGS='git clone https://github.com/mutto233/pseudo-channel . --branch master' fi @@ -106,9 +107,9 @@ 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 + sudo apt-get -y install libxml2-utils # NEEDED FOR XML PARSING cd .. - echo "ENTER the IP ADDRESS of your PLEX SERVER" + 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 @@ -116,13 +117,13 @@ if [ "$FIRST_INSTALL" == "true" ] then server_port='32400' fi - echo "ENTER your PLEX AUTHENTICATION TOKEN" + 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" - # Gets a list of Plex clients connected and registered with the server + # 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://192.168.1.140:32400/clients" | sed "s|name=||g" | sed "s|^ ||g" && echo -e " Other") eval set $clientlist select ps_client_entry in "$@" @@ -135,7 +136,9 @@ if [ "$FIRST_INSTALL" == "true" ] ps_client="[\"$ps_client_entry\"]" break done - # Get the names of Plex libraries for the config + # 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 @@ -143,11 +146,11 @@ if [ "$FIRST_INSTALL" == "true" ] do read -p 'TV Show Library Name: ' tv_library_entry echo -n "\"$tv_library_entry\"" >> tv-libraries.temp - echo "ENTER another LIBRARY?" + 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 LIBRARY?" + echo "ENTER another TV SHOW LIBRARY?" read -p 'Y/N: ' enter_tv_shows done if [[ "$enter_tv_shows" == @(Y|y|Yes|yes|YES) ]] @@ -163,11 +166,11 @@ if [ "$FIRST_INSTALL" == "true" ] do read -p 'Movie Library Name: ' movie_library_entry echo -n "\"$movie_library_entry\"" >> movie-libraries.temp - echo "ENTER another LIBRARY?" + 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 LIBRARY?" + echo "ENTER another MOVIE LIBRARY?" read -p 'Y/N: ' enter_movies done if [[ "$enter_movies" == @(Y|y|Yes|yes|YES) ]] @@ -176,7 +179,7 @@ if [ "$FIRST_INSTALL" == "true" ] fi done echo -n "]," >> movie-libraries.temp - echo "Use COMMERCIALS in between scheduled content?" + 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 @@ -193,11 +196,11 @@ if [ "$FIRST_INSTALL" == "true" ] do read -p 'Commercial Library Name: ' commercial_library_entry echo -n "\"$commercial_library_entry\", " >> commercial-libraries.temp - echo "ENTER another LIBRARY?" + 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 LIBRARY?" + echo "ENTER another COMMERCIAL LIBRARY?" read -p 'Y/N: ' enter_commercials done done @@ -206,27 +209,40 @@ if [ "$FIRST_INSTALL" == "true" ] 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 either 24h FORMAT (ex: 23:00) or 12h FORMAT (11:00 PM)" - read -p 'Schedule Reset Time: ' reset_time - reset_time="\"$reset_time\"" - echo "token = '$server_token'" > plex_token.py - echo "baseurl = 'http://$server_ip:$server_port'" >> plex_token.py + 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_hours | 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 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 - sudo sed -i "/.\"TV Shows\" :*./c\ \"TV Shows\" : $tv_libraries" github_download/both-dir/pseudo_config.py + 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 - if [[ "$commercials_true" == "true" ]] + 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 @@ -275,7 +291,7 @@ if [ "${#CHANNEL_DIR_ARR[@]}" -gt 1 ]; then cp ../.pseudo-temp/pseudo_config.py . 2>/dev/null rm -rf ../.pseudo-temp - + cd .. done fi @@ -318,3 +334,4 @@ rm -rf ./github_download sudo chmod -R 777 . echo "Update Complete" + From 9854b9f7b2a73222bd4f133e3f047471ec0ee155 Mon Sep 17 00:00:00 2001 From: Moe Fwacky Date: Sat, 22 Sep 2018 08:34:52 -0700 Subject: [PATCH 20/28] added script to edit config files --- main-dir/config_editor.sh | 489 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 489 insertions(+) create mode 100644 main-dir/config_editor.sh diff --git a/main-dir/config_editor.sh b/main-dir/config_editor.sh new file mode 100644 index 0000000..e0e581e --- /dev/null +++ b/main-dir/config_editor.sh @@ -0,0 +1,489 @@ +#!/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 +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++++++++++++++++++++" + 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 "PLEX SERVER is $server_ip:$server_port" + sudo sed -i "s/baseurl =.*/baseurl = \'http:\/\/$server_ip:$server_port\'/" plex_token.py + 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++++++++++++++++++++" + 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 AUTH TOKEN is $server_token" + server_token="\'$server_token\'" + sudo sed -i "s/token =.*/token = $server_token/" plex_token.py + sleep 1 +elif [[ "$config_option" == "Plex Client" ]] # CHANGE PLEX CLIENT + then + clear + echo "++++++++++++++++++++PSEUDO CHANNEL CONFIG EDITOR++++++++++++++++++++" + clientlist=$(xmllint --xpath "//Server/@name" "http://192.168.1.140:32400/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 From ee91de484b35be137da6459a7e15df646d3964ba Mon Sep 17 00:00:00 2001 From: Moe Fwacky Date: Sat, 22 Sep 2018 11:56:35 -0700 Subject: [PATCH 21/28] Updates to setup and config editor, added config.cache --- main-dir/config.cache | 6 +++ main-dir/config_editor.sh | 59 ++++++++++++++++++++++------ main-dir/update-channels-from-git.sh | 8 +++- 3 files changed, 60 insertions(+), 13 deletions(-) create mode 100644 main-dir/config.cache 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 index e0e581e..500805b 100644 --- a/main-dir/config_editor.sh +++ b/main-dir/config_editor.sh @@ -4,6 +4,7 @@ #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 @@ -158,6 +159,7 @@ select category in "BASIC OPTIONS" "ADVANCED OPTIONS" "QUIT" # MAIN MENU echo "CHANGES to the CHANNEL $channel_number CONFIG FILE have been SAVED." sleep 1 fi + echo "EXITING CONFIG EDITOR..." sleep 1 clear @@ -169,33 +171,66 @@ if [[ "$config_option" == "Plex Server URL" ]] # CHANGE THE PLEX SERVER URL AND then clear echo "++++++++++++++++++++PSEUDO CHANNEL CONFIG EDITOR++++++++++++++++++++" - 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" == '' ] + #GET PLEX SERVER IP AND PORT + if [[ $server_ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] then - server_port='32400' + 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++++++++++++++++++++" - 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 AUTH TOKEN is $server_token" - server_token="\'$server_token\'" + 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://192.168.1.140:32400/clients" | sed "s|name=||g" | sed "s|^ ||g" && echo -e " Other") # GET LIST OF CLIENTS + 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 diff --git a/main-dir/update-channels-from-git.sh b/main-dir/update-channels-from-git.sh index fb6b098..d6ac2a7 100644 --- a/main-dir/update-channels-from-git.sh +++ b/main-dir/update-channels-from-git.sh @@ -191,6 +191,8 @@ if [ "$FIRST_INSTALL" == "true" ] 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 @@ -222,7 +224,7 @@ if [ "$FIRST_INSTALL" == "true" ] 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 #### + #### 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 @@ -335,3 +337,7 @@ 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 From 231a7331aa423634de34793d5a2d05d8aafab0d0 Mon Sep 17 00:00:00 2001 From: Moe Fwacky Date: Sat, 22 Sep 2018 13:11:00 -0700 Subject: [PATCH 22/28] fixed a few bugs --- main-dir/update-channels-from-git.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/main-dir/update-channels-from-git.sh b/main-dir/update-channels-from-git.sh index d6ac2a7..2deb820 100644 --- a/main-dir/update-channels-from-git.sh +++ b/main-dir/update-channels-from-git.sh @@ -23,10 +23,10 @@ if [ $# -gt 1 ] elif [ "$1" == "develop" ] then echo "Downloading the develop branch" - SCRIPT_TO_EXECUTE_PLUS_ARGS='git clone https://github.com/mutto233/pseudo-channel . --branch develop' + SCRIPT_TO_EXECUTE_PLUS_ARGS='git clone https://github.com/MoeFwacky/pseudo-channel . --branch develop' else echo "Downloading the master branch" - SCRIPT_TO_EXECUTE_PLUS_ARGS='git clone https://github.com/mutto233/pseudo-channel . --branch master' + SCRIPT_TO_EXECUTE_PLUS_ARGS='git clone https://github.com/MoeFwacky/pseudo-channel . --branch master' fi OUTPUT_PREV_CHANNEL_PATH=. @@ -217,9 +217,9 @@ if [ "$FIRST_INSTALL" == "true" ] 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_hours | sed -e s|^[0]||)" + 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]||)" + reset_time_minute=$(echo $reset_time_minute | sed "-e s|^[0]||") # SET UP CRON JOB TO RUN DAILY RESET 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 - From 68be23c7d512ebbd021768e4212920cefda6a962 Mon Sep 17 00:00:00 2001 From: Moe Fwacky Date: Sat, 22 Sep 2018 13:36:29 -0700 Subject: [PATCH 23/28] Add files via upload --- main-dir/update-channels-from-git.sh | 228 +++------------------------ 1 file changed, 23 insertions(+), 205 deletions(-) diff --git a/main-dir/update-channels-from-git.sh b/main-dir/update-channels-from-git.sh index 2deb820..ab66e1c 100644 --- a/main-dir/update-channels-from-git.sh +++ b/main-dir/update-channels-from-git.sh @@ -16,34 +16,23 @@ #----BEGIN EDITABLE VARS---- -if [ $# -gt 1 ] - then +if [ $# -gt 1 ]; then echo "ERROR: Please only supply one argument" exit 9999 - elif [ "$1" == "develop" ] - then +elif [ "$1" == "develop" ]; then echo "Downloading the develop branch" - SCRIPT_TO_EXECUTE_PLUS_ARGS='git clone https://github.com/MoeFwacky/pseudo-channel . --branch develop' - else + SCRIPT_TO_EXECUTE_PLUS_ARGS='git clone https://github.com/mutto233/pseudo-channel . --branch develop' + +else echo "Downloading the master branch" - SCRIPT_TO_EXECUTE_PLUS_ARGS='git clone https://github.com/MoeFwacky/pseudo-channel . --branch master' + SCRIPT_TO_EXECUTE_PLUS_ARGS='git clone https://github.com/mutto233/pseudo-channel . --branch master' fi OUTPUT_PREV_CHANNEL_PATH=. CHANNEL_DIR_INCREMENT_SYMBOL="_" -# 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 +FIRST_INSTALL=false #----END EDITABLE VARS------- @@ -65,33 +54,10 @@ fi # If this is our first install, we will now make all necessary directories to prepare for install if [ "$FIRST_INSTALL" == "true" ]; then -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" ]] + + for (( num=1; num<=5; num++ )) 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 @@ -102,157 +68,14 @@ cd github_download $SCRIPT_TO_EXECUTE_PLUS_ARGS #### If necessary, install the required elements as defined by requirements.txt -#### Also, ask user for information to fill in the plex_token and pseudo_config files -if [ "$FIRST_INSTALL" == "true" ] - then +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 # 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://192.168.1.140:32400/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 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 @@ -269,31 +92,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 @@ -301,7 +124,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 token file +#### - Copy config, db, and tolken file #### - Copy relevant files from github #### - Replace files originally removed echo "Updating channels folder" @@ -336,8 +159,3 @@ 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 From 8a2d2306b131cdf1bcf7c86c3766aad7caecf157 Mon Sep 17 00:00:00 2001 From: Moe Fwacky Date: Sat, 22 Sep 2018 13:40:06 -0700 Subject: [PATCH 24/28] Add files via upload --- main-dir/update-channels-from-git.sh | 229 ++++++++++++++++++++++++--- 1 file changed, 206 insertions(+), 23 deletions(-) diff --git a/main-dir/update-channels-from-git.sh b/main-dir/update-channels-from-git.sh index ab66e1c..ddb3609 100644 --- a/main-dir/update-channels-from-git.sh +++ b/main-dir/update-channels-from-git.sh @@ -16,23 +16,34 @@ #----BEGIN EDITABLE VARS---- -if [ $# -gt 1 ]; then +if [ $# -gt 1 ] + then echo "ERROR: Please only supply one argument" exit 9999 -elif [ "$1" == "develop" ]; then + elif [ "$1" == "develop" ] + then echo "Downloading the develop branch" - SCRIPT_TO_EXECUTE_PLUS_ARGS='git clone https://github.com/mutto233/pseudo-channel . --branch develop' - -else + SCRIPT_TO_EXECUTE_PLUS_ARGS='git clone https://github.com/MoeFwacky/pseudo-channel . --branch develop' + else echo "Downloading the master branch" - SCRIPT_TO_EXECUTE_PLUS_ARGS='git clone https://github.com/mutto233/pseudo-channel . --branch master' + SCRIPT_TO_EXECUTE_PLUS_ARGS='git clone https://github.com/MoeFwacky/pseudo-channel . --branch master' fi 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 +65,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 +102,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 # 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://192.168.1.140:32400/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 +270,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 +302,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 +337,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 From 46cb2b0ac63b972acacb79ca690a619632b4cd07 Mon Sep 17 00:00:00 2001 From: Moe Fwacky Date: Sat, 22 Sep 2018 15:56:31 -0700 Subject: [PATCH 25/28] Update update-channels-from-git.sh --- main-dir/update-channels-from-git.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main-dir/update-channels-from-git.sh b/main-dir/update-channels-from-git.sh index ddb3609..ceae241 100644 --- a/main-dir/update-channels-from-git.sh +++ b/main-dir/update-channels-from-git.sh @@ -107,7 +107,7 @@ 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 # NEEDED FOR XML PARSING + 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 From a7f8cd8aee6e043aac01b540463e4d5653609f7a Mon Sep 17 00:00:00 2001 From: Moe Fwacky Date: Mon, 24 Sep 2018 01:13:20 -0700 Subject: [PATCH 26/28] added interactive schedule editor script --- main-dir/schedule-editor.sh | 582 ++++++++++++++++++++++++++++++++++++ 1 file changed, 582 insertions(+) create mode 100644 main-dir/schedule-editor.sh 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 From 58aa4da775c3a51b5f1e7643bbc4666c3eca6847 Mon Sep 17 00:00:00 2001 From: Moe Fwacky Date: Tue, 25 Sep 2018 00:53:35 -0700 Subject: [PATCH 27/28] Update update-channels-from-git.sh --- main-dir/update-channels-from-git.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main-dir/update-channels-from-git.sh b/main-dir/update-channels-from-git.sh index ceae241..0d19a9e 100644 --- a/main-dir/update-channels-from-git.sh +++ b/main-dir/update-channels-from-git.sh @@ -124,7 +124,7 @@ if [ "$FIRST_INSTALL" == "true" ] 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://192.168.1.140:32400/clients" | sed "s|name=||g" | sed "s|^ ||g" && echo -e " Other") + 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 From 43b66339c803daace08eed42d33af3fe8ec2bc39 Mon Sep 17 00:00:00 2001 From: Moe Fwacky Date: Tue, 25 Sep 2018 01:04:36 -0700 Subject: [PATCH 28/28] Add files via upload --- main-dir/config_editor.sh | 4 +- main-dir/pseudo-channel-control.sh | 180 +++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+), 2 deletions(-) create mode 100644 main-dir/pseudo-channel-control.sh diff --git a/main-dir/config_editor.sh b/main-dir/config_editor.sh index 500805b..a88de71 100644 --- a/main-dir/config_editor.sh +++ b/main-dir/config_editor.sh @@ -372,10 +372,10 @@ elif [[ "$config_option" == "Daily Reset Time" ]] if [[ "$use_commercials" == "true" ]] then commercials_true=true - sudo sed -i "s/useCommercialInjection =.*/useCommercialInjection = true/" pseudo_config.py + 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 + 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" ]] 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