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