diff --git a/PseudoChannel.py b/PseudoChannel.py index 64fcd37..352eae2 100644 --- a/PseudoChannel.py +++ b/PseudoChannel.py @@ -9,6 +9,7 @@ from src import Music from src import Video from src import PseudoDailyScheduleController from src import GoogleCalendar +from src import PseudoChannelCommercial from plexapi.server import PlexServer @@ -36,6 +37,8 @@ class PseudoChannel(): GKEY = config.gkey USING_GOOGLE_CALENDAR = config.useGoogleCalendar + USING_COMMERCIAL_INJECTION = config.useCommercialInjection + def __init__(self): self.db = PseudoChannelDatabase("pseudo-channel.db") @@ -243,7 +246,7 @@ class PseudoChannel(): title = titlelist[1] # s.strftime('%I:%M'), event["summary"] - natural_start_time = self.translate_time(s.strftime('%I:%M %p')) + natural_start_time = self.translate_time(s.strftime('%I:%M:%S %p')) natural_end_time = 0 @@ -259,6 +262,8 @@ class PseudoChannel(): strict_time = titlelist[2] if len(titlelist) > 2 else "true" + #strict_time = "true" + time_shift = "5" overlap_max = "" @@ -267,7 +272,7 @@ class PseudoChannel(): start_time_unix = datetime.datetime.strptime( self.translate_time(natural_start_time), - '%I:%M %p').strftime('%Y-%m-%d %H:%M:%S') + '%I:%M:%S %p').strftime('%Y-%m-%d %H:%M:%S') #print "Adding: ", time.tag, section, time.text, time.attrib['title'] @@ -343,7 +348,7 @@ class PseudoChannel(): start_time_unix = datetime.datetime.strptime( self.translate_time(time.text), - '%I:%M %p').strftime('%Y-%m-%d %H:%M:%S') + '%I:%M:%S %p').strftime('%Y-%m-%d %H:%M:%S') print "Adding: ", time.tag, section, time.text, time.attrib['title'] @@ -398,7 +403,7 @@ class PseudoChannel(): try: - return datetime.datetime.strptime(timestr, "%I:%M %p").strftime("%-I:%M %p") + return datetime.datetime.strptime(timestr, '%I:%M:%S %p').strftime('%I:%M:%S %p') except ValueError as e: @@ -406,7 +411,7 @@ class PseudoChannel(): try: - return datetime.datetime.strptime(timestr, "%H:%M").strftime("%-I:%M %p") + return datetime.datetime.strptime(timestr, '%I:%M:%S %p').strftime('%I:%M:%S %p') except ValueError as e: @@ -418,8 +423,8 @@ class PseudoChannel(): * Getting the offest by comparing both times from the unix epoch time and getting the difference. * ''' - timeA = datetime.datetime.strptime(time1, "%I:%M %p") - timeB = datetime.datetime.strptime(time2, "%I:%M %p") + timeA = datetime.datetime.strptime(time1, '%I:%M:%S %p') + timeB = datetime.datetime.strptime(time2, '%I:%M:%S %p') timeAEpoch = calendar.timegm(timeA.timetuple()) timeBEpoch = calendar.timegm(timeB.timetuple()) @@ -444,9 +449,9 @@ class PseudoChannel(): self.OVERLAP_MAX = overlapMax - time1 = prevEndTime.strftime('%-I:%M %p') + time1 = prevEndTime.strftime('%I:%M:%S %p') - timeB = datetime.datetime.strptime(intendedStartTime, '%I:%M %p').strftime('%-I:%M %p') + timeB = datetime.datetime.strptime(intendedStartTime, '%I:%M:%S %p').strftime('%I:%M:%S %p') print "++++ Previous End Time: ", time1, "Intended start time: ", timeB @@ -511,7 +516,7 @@ class PseudoChannel(): theTimeSetInterval = datetime.datetime.strptime(time, '%H:%M') - tempTimeTwoStr = datetime.datetime.strptime(time1, '%I:%M %p').strftime('%H:%M') + tempTimeTwoStr = datetime.datetime.strptime(time1, '%I:%M:%S %p').strftime('%H:%M') formatted_time_two = datetime.datetime.strptime(tempTimeTwoStr, '%H:%M') @@ -527,11 +532,11 @@ class PseudoChannel(): print("Not sure what to do here") - return newStartTime.strftime('%-I:%M %p') + return newStartTime.strftime('%I:%M:%S %p') def get_end_time_from_duration(self, startTime, duration): - time = datetime.datetime.strptime(startTime, '%I:%M %p') + time = datetime.datetime.strptime(startTime, '%I:%M:%S %p') show_time_plus_duration = time + datetime.timedelta(milliseconds=duration) @@ -543,6 +548,11 @@ class PseudoChannel(): print("#### Generating Daily Schedule") + if self.USING_COMMERCIAL_INJECTION: + self.commercials = PseudoChannelCommercial( + self.db.get_commercials() + ) + schedule = self.db.get_schedule() weekday_dict = { @@ -713,7 +723,7 @@ class PseudoChannel(): if previous_episode != None: - natural_start_time = datetime.datetime.strptime(entry.natural_start_time, '%I:%M %p') + natural_start_time = datetime.datetime.strptime(entry.natural_start_time, '%I:%M:%S %p') natural_end_time = entry.natural_end_time @@ -726,6 +736,19 @@ class PseudoChannel(): entry.duration ) + """Get List of Commercials to inject""" + + if self.USING_COMMERCIAL_INJECTION: + + list_of_commercials = self.commercials.get_commercials_to_place_between_media( + previous_episode, + entry + ) + + for commercial in list_of_commercials: + + self.db.add_media_to_daily_schedule(commercial) + self.db.add_media_to_daily_schedule(entry) previous_episode = entry @@ -743,10 +766,21 @@ class PseudoChannel(): print "++++ New start time:", new_starttime - entry.start_time = datetime.datetime.strptime(new_starttime, '%I:%M %p').strftime('%-I:%M %p') + entry.start_time = datetime.datetime.strptime(new_starttime, '%I:%M:%S %p').strftime('%I:%M:%S %p') entry.end_time = self.get_end_time_from_duration(entry.start_time, entry.duration) + """Get List of Commercials to inject""" + if self.USING_COMMERCIAL_INJECTION: + list_of_commercials = self.commercials.get_commercials_to_place_between_media( + previous_episode, + entry + ) + + for commercial in list_of_commercials: + + self.db.add_media_to_daily_schedule(commercial) + self.db.add_media_to_daily_schedule(entry) previous_episode = entry @@ -757,6 +791,19 @@ class PseudoChannel(): previous_episode = entry + def run_commercial_injection(self): + + print "#### Running commercial injection." + + self.commercials = PseudoChannelCommercial( + self.db.get_commercials(), + self.db.get_daily_schedule() + ) + + commercials_to_inject = self.commercials.get_commercials_to_inject() + + print commercials_to_inject + def make_xml_schedule(self): self.controller.make_xml_schedule(self.db.get_daily_schedule()) @@ -906,6 +953,15 @@ if __name__ == '__main__': action='store_true', help='Makes the XML / HTML schedule based on the daily_schedule table.') + ''' + * + * Make XML / HTML Schedule: "python PseudoChannel.py -i" + * + ''' + parser.add_argument('-i', '--inject_commercials', + action='store_true', + help='Squeeze commercials in any media gaps if possible.') + globals().update(vars(parser.parse_args())) args = parser.parse_args() @@ -940,6 +996,10 @@ if __name__ == '__main__': pseudo_channel.make_xml_schedule() + if args.inject_commercials: + + pseudo_channel.run_commercial_injection() + if args.run: try: @@ -977,9 +1037,9 @@ if __name__ == '__main__': t = datetime.datetime.utcnow() - sleeptime = 60 - (t.second + t.microsecond/1000000.0) + #sleeptime = 60 - (t.second + t.microsecond/1000000.0) - sleep(sleeptime) + sleep(.5) except KeyboardInterrupt, e: diff --git a/pseudo_config.py b/pseudo_config.py index 03a83b9..8f9dd9c 100644 --- a/pseudo_config.py +++ b/pseudo_config.py @@ -59,3 +59,5 @@ plexLibraries = { } useGoogleCalendar = True + +useCommercialInjection = True diff --git a/src/PseudoChannelCommercial.py b/src/PseudoChannelCommercial.py index e69de29..ca16405 100644 --- a/src/PseudoChannelCommercial.py +++ b/src/PseudoChannelCommercial.py @@ -0,0 +1,133 @@ +"""Commercial Functionality +""" +from random import shuffle +import random +import copy +import datetime +from src import Commercial + +class PseudoChannelCommercial(): + + MIN_DURATION_FOR_COMMERCIAL = 10 #seconds + daily_schedule = [] + + def __init__(self, commercials): + + self.commercials = commercials + + def get_commercials_to_inject(self): + + self.go() + + return None + + def get_random_commercial(self): + + random_commercial = random.choice(self.commercials) + + random_commercial_dur_seconds = (int(random_commercial[4])/1000)%60 + + 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)%60 + + return random_commercial + + def go(self): + + shuffled_commercial_list = copy.deepcopy(self.commercials) + + random.shuffle(self.commercials, random.random) + + #print shuffled_commercial_list + + prev_item = None + + for entry in self.daily_schedule: + + """First Episode""" + if prev_item == None: + + prev_item = entry + + else: + + prev_item_end_time = datetime.datetime.strptime(prev_item[9], '%Y-%m-%d %H:%M:%S.%f') + + curr_item_start_time = datetime.datetime.strptime(entry[8], '%I:%M:%S %p') + + time_diff = (curr_item_start_time - prev_item_end_time) + + days, hours, minutes = time_diff.days, time_diff.seconds // 3600, time_diff.seconds // 60 % 60 + + count = 0 + + commercial_list = [] + + commercial_dur_sum = 0 + + while int(time_diff.total_seconds()) >= commercial_dur_sum and count < len(self.commercials): + + + random_commercial = self.get_random_commercial() + + commercial_list.append(random_commercial) + + commercial_dur_sum += int(random_commercial[4]) + + print commercial_list + + prev_item = entry + + def get_commercials_to_place_between_media(self, last_ep, now_ep): + + print last_ep.end_time, now_ep.start_time + + prev_item_end_time = datetime.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.datetime.strptime(now_ep.start_time, '%I:%M:%S %p') + + time_diff = (curr_item_start_time - prev_item_end_time) + + days, hours, minutes = time_diff.days, time_diff.seconds // 3600, time_diff.seconds // 60 % 60 + + count = 0 + + commercial_list = [] + + commercial_dur_sum = 0 + + while int(time_diff.total_seconds()) >= commercial_dur_sum and count < len(self.commercials): + + random_commercial = self.get_random_commercial() + + new_commercial_seconds = (int(random_commercial[4])/1000)%60 + + commercial_dur_sum += new_commercial_seconds + + new_commercial_start_time = prev_item_end_time + datetime.timedelta(seconds=commercial_dur_sum) + + new_commercial_end_time = new_commercial_start_time + datetime.timedelta(seconds=int(new_commercial_seconds)) + + 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 + ) + + commercial_list.append(new_commercial) + + #print "here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + + return commercial_list \ No newline at end of file diff --git a/src/PseudoChannelDatabase.py b/src/PseudoChannelDatabase.py index 6c424bf..f04030f 100644 --- a/src/PseudoChannelDatabase.py +++ b/src/PseudoChannelDatabase.py @@ -329,6 +329,14 @@ class PseudoChannelDatabase(): return self.get_media(title, media) + def get_commercials(self): + + self.cursor.execute("SELECT * FROM commercials ORDER BY duration ASC") + + datalist = list(self.cursor.fetchall()) + + return datalist + def update_shows_table_with_last_episode(self, showTitle, lastEpisodeTitle): sql1 = "UPDATE shows SET lastEpisodeTitle = ? WHERE title LIKE ? COLLATE NOCASE" @@ -461,7 +469,7 @@ class PseudoChannelDatabase(): return first_episode - def get_commercials(self, title): + def get_commercial(self, title): media = "commercials" diff --git a/src/PseudoDailyScheduleController.py b/src/PseudoDailyScheduleController.py index 5b81c5e..59e7556 100644 --- a/src/PseudoDailyScheduleController.py +++ b/src/PseudoDailyScheduleController.py @@ -73,7 +73,7 @@ class PseudoDailyScheduleController(): for row in datalist: - timeB = datetime.strptime(row[8], '%I:%M %p') + timeB = datetime.strptime(row[8], '%I:%M:%S %p') if currentTime == None: @@ -188,7 +188,7 @@ class PseudoDailyScheduleController(): with tag('tbody'): - timeB = datetime.strptime(row[8], '%I:%M %p') + timeB = datetime.strptime(row[8], '%I:%M:%S %p') if currentTime == None: @@ -333,6 +333,16 @@ class PseudoDailyScheduleController(): clientItem.playMedia(movie) + elif mediaType == "Commercials": + + movie = self.PLEX.library.section(mediaType).get(mediaTitle) + + for client in self.PLEX_CLIENTS: + + clientItem = self.PLEX.client(client) + + clientItem.playMedia(movie) + else: print("Not sure how to play {}".format(mediaType)) @@ -367,12 +377,14 @@ class PseudoDailyScheduleController(): if currentTime.minute == endTime.minute: - print("Ok end time found") + if currentTime.second == endTime.second: - 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)) + print("Ok end time found") - break + 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)) + + break ''' * * Check DB / current time. If that matches a scheduled shows startTime then trigger play via Plex API @@ -394,44 +406,46 @@ class PseudoDailyScheduleController(): for row in datalist: - timeB = datetime.strptime(row[8], '%I:%M %p') + timeB = datetime.strptime(row[8], '%I:%M:%S %p') if currentTime.hour == timeB.hour: if currentTime.minute == timeB.minute: - print("Starting Epsisode: " + row[3]) - print(row) + if currentTime.second == timeB.second: - self.play_media(row[11], row[6], row[3]) + print("Starting Media: " + row[3]) + print(row) - self.write_schedule_to_file( - self.get_html_from_daily_schedule( - timeB, - self.get_show_photo( - row[11], - row[6] if row[11] == "TV Shows" else row[3] - ), - datalist + self.play_media(row[11], row[6], row[3]) + + self.write_schedule_to_file( + self.get_html_from_daily_schedule( + timeB, + self.get_show_photo( + row[11], + row[6] if row[11] == "TV Shows" else row[3] + ), + datalist + ) ) - ) - """Generate / write XML to file - """ - self.write_xml_to_file( - self.get_xml_from_daily_schedule( - timeB, - self.get_show_photo( - row[11], - row[6] if row[11] == "TV Shows" else row[3] - ), - datalist + """Generate / write XML to file + """ + self.write_xml_to_file( + self.get_xml_from_daily_schedule( + timeB, + self.get_show_photo( + row[11], + row[6] if row[11] == "TV Shows" else row[3] + ), + datalist + ) ) - ) - self.my_logger.debug('Trying to play: ' + row[3]) + self.my_logger.debug('Trying to play: ' + row[3]) - break + break datalistLengthMonitor += 1 diff --git a/src/__init__.py b/src/__init__.py index 2c68fd8..027281c 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -6,4 +6,5 @@ from Media import Media from Music import Music from Video import Video from PseudoDailyScheduleController import PseudoDailyScheduleController -from GoogleCalendar import GoogleCalendar \ No newline at end of file +from GoogleCalendar import GoogleCalendar +from PseudoChannelCommercial import PseudoChannelCommercial \ No newline at end of file