Files
pseudo-channel/both-dir/PseudoChannel.py
2022-01-09 11:48:59 -08:00

2122 lines
116 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import signal
import datetime
from datetime import time
from time import mktime as mktime
import logging
import calendar
import itertools
import argparse
import textwrap
import os, sys
from xml.dom import minidom
import xml.etree.ElementTree as ET
import json
from pprint import pprint
import random
import re
from plexapi.server import PlexServer
import schedule
from time import sleep
from src import PseudoChannelDatabase
from src import Movie
from src import Commercial
from src import Episode
from src import Music
from src import Video
from src import PseudoDailyScheduleController
from src import PseudoChannelCommercial
from src import PseudoChannelRandomMovie
import pseudo_config as config
from importlib import reload
reload(sys)
#sys.setdefaultencoding('utf-8')
class PseudoChannel():
PLEX = PlexServer(config.baseurl, config.token)
MEDIA = []
GKEY = config.gkey
USING_COMMERCIAL_INJECTION = config.useCommercialInjection
DAILY_UPDATE_TIME = config.dailyUpdateTime
APP_TIME_FORMAT_STR = '%H:%M:%S'
COMMERCIAL_PADDING_IN_SECONDS = config.commercialPadding
CONTROLLER_SERVER_PATH = config.controllerServerPath
CONTROLLER_SERVER_PORT = config.controllerServerPort
USE_OVERRIDE_CACHE = config.useDailyOverlapCache
DEBUG = config.debug_mode
ROTATE_LOG = config.rotateLog
USE_DIRTY_GAP_FIX = config.useDirtyGapFix
HTML_PSEUDO_TITLE = config.htmlPseudoTitle
def __init__(self):
logging.basicConfig(filename="pseudo-channel.log", level=logging.INFO)
self.db = PseudoChannelDatabase("pseudo-channel.db")
self.controller = PseudoDailyScheduleController(
config.baseurl,
config.token,
config.plexClients,
self.CONTROLLER_SERVER_PATH,
self.CONTROLLER_SERVER_PORT,
self.DEBUG,
self.HTML_PSEUDO_TITLE
)
self.movieMagic = PseudoChannelRandomMovie()
"""Database functions.
update_db(): Grab the media from the Plex DB and store it in the local pseudo-channel.db.
drop_db(): Drop the local database. Fresh start.
update_schedule(): Update schedule with user defined times.
drop_schedule(): Drop the user defined schedule table.
generate_daily_schedule(): Generates daily schedule based on the "schedule" table.
"""
# Print iterations progress
def print_progress(self, iteration, total, prefix='', suffix='', decimals=1, bar_length=100):
"""
Call in a loop to create terminal progress bar
@params:
iteration - Required : current iteration (Int)
total - Required : total iterations (Int)
prefix - Optional : prefix string (Str)
suffix - Optional : suffix string (Str)
decimals - Optional : positive number of decimals in percent complete (Int)
bar_length - Optional : character length of bar (Int)
"""
str_format = "{0:." + str(decimals) + "f}"
percents = str_format.format(100 * (iteration / float(total)))
filled_length = int(round(bar_length * iteration / float(total)))
bar = '' * filled_length + '-' * (bar_length - filled_length)
sys.stdout.write('\x1b[2K\r%s |%s| %s%s %s' % (prefix, bar, percents, '%', suffix)),
#if iteration == total:
# sys.stdout.write('\n')
sys.stdout.flush()
def update_db(self):
print("NOTICE: Updating Local Database")
self.db.create_tables()
libs_dict = config.plexLibraries
sections = self.PLEX.library.sections()
for section in sections:
for correct_lib_name, user_lib_name in libs_dict.items():
if section.title.lower() in [x.lower() for x in user_lib_name]:
if correct_lib_name == "Movies":
sectionMedia = self.PLEX.library.section(section.title).all()
for i, media in enumerate(sectionMedia):
fetchMedia = self.PLEX.fetchItem(media.key)
try:
genres = [genre.tag for genre in fetchMedia.genres]
except:
genres = ''
try:
actors = [actor.tag for actor in fetchMedia.actors]
except:
actors = ''
try:
collections = [collection.tag for collection in fetchMedia.collections]
except:
collections = ''
#actors = {}
#for actor in fetchMedia.actors:
# actors[actor.tag] = str(actor.id)
self.db.add_movies_to_db(media.ratingKey, media.title, media.duration, media.key, section.title, media.contentRating, media.summary, media.originallyAvailableAt, str(genres), str(actors), str(collections), media.studio)
self.print_progress(
i + 1,
len(sectionMedia),
prefix = section.title+" "+str(i+1)+' of '+str(len(sectionMedia))+": ",
suffix = 'Complete ['+media.title+']',
bar_length = 40
)
#print('')
elif correct_lib_name == "TV Shows":
sectionMedia = self.PLEX.library.section(section.title).all()
for i, media in enumerate(sectionMedia):
fetchMedia = self.PLEX.fetchItem(media.key)
try:
genres = [genre.tag for genre in fetchMedia.genres]
except:
genres = ''
try:
actors = [actor.tag for actor in fetchMedia.actors]
except:
actors = ''
try:
similars = [similar.tag for similar in fetchMedia.similar]
except:
similars = ''
self.db.add_shows_to_db(
media.ratingKey,
media.title,
media.duration if media.duration else 1,
'',
media.originallyAvailableAt,
media.key,
section.title,
media.contentRating,
str(genres),
str(actors),
str(similars),
media.studio
)
self.print_progress(
i + 1,
len(sectionMedia),
prefix = 'TV Show '+str(i+1)+' of '+str(len(sectionMedia))+': ',
suffix = 'Complete ['+media.title[0:40]+']',
bar_length = 40
)
#add all episodes of each tv show to episodes table
for i, media in enumerate(sectionMedia):
episodes = self.PLEX.library.section(section.title).get(media.title).episodes()
for j, episode in enumerate(episodes):
duration = episode.duration
if duration:
self.db.add_episodes_to_db(
media.ratingKey,
episode.title,
duration,
episode.index,
episode.parentIndex,
media.title,
episode.key,
section.title,
episode.contentRating,
episode.originallyAvailableAt,
episode.summary
)
else:
self.db.add_episodes_to_db(
episode.ratingKey,
episode.title,
0,
episode.index,
episode.parentIndex,
media.title,
episode.key,
section.title,
episode.contentRating,
episode.originallyAvailableAt,
episode.summary
)
self.print_progress(
j + 1,
len(episodes),
prefix = str(i+1)+' of '+str(len(sectionMedia))+" "+media.title+': ',
suffix = 'Complete ['+episode.title[0:40]+']',
bar_length = 40
)
#print('')
elif correct_lib_name == "Commercials":
sectionMedia = self.PLEX.library.section(section.title).all()
media_length = len(sectionMedia)
for i, media in enumerate(sectionMedia):
self.db.add_commercials_to_db(3, media.title, media.duration, media.key, section.title)
self.print_progress(
i + 1,
media_length,
prefix = section.title+" "+str(i+1)+' of '+str(len(sectionMedia))+":",
suffix = 'Complete['+media.title[0:40]+']',
bar_length = 40
)
#print('')
dothething = "yes"
if dothething == "yes":
playlists = self.PLEX.playlists()
for i, playlist in enumerate(playlists):
duration_average = playlist.duration / playlist.leafCount
playlist_added = playlist.addedAt.strftime("%Y-%m-%d %H:%M:%S")
self.db.add_shows_to_db(
playlist.ratingKey,
playlist.title,
duration_average,
'',
playlist_added,
playlist.key,
playlist.type,
'',
'',
'',
'',
''
)
# add all entries of playlist to episodes table
episodes = self.PLEX.playlist(playlist.title).items()
for j, episode in enumerate(episodes):
duration = episode.duration
sectionTitle = "Playlists"
itemID = str(episode.playlistItemID)
itemData = self.PLEX.fetchItem(episode.key)
if itemData.type == "episode":
sNo = str(itemData.parentIndex)
eNo = str(itemData.index)
plTitle = episode.grandparentTitle +" - "+ episode.title + " (S" + sNo + "E" + eNo + ")"
else:
sNo = "0"
eNo = "0"
plTitle = episode.title + " ("+str(episode.year)+")"
if duration:
self.db.add_playlist_entries_to_db(
episode.ratingKey,
plTitle,
duration,
eNo,
sNo,
playlist.title,
episode.key,
sectionTitle,
episode.contentRating,
episode.originallyAvailableAt,
episode.summary
)
else:
self.db.add_playlist_entries_to_db(
episode.ratingKey,
episode.title,
0,
eNo,
sNo,
playlist.title,
episode.key,
sectionTitle,
episode.contentRating,
episode.originallyAvailableAt,
episode.summary
)
self.print_progress(
j + 1,
len(episodes),
prefix = 'Playlist '+str(i+1)+' of '+str(len(playlists))+': ',
suffix = 'Complete ['+playlist.title[0:40]+']',
bar_length = 40
)
#print('', end='\r')
sys.stdout.write("\033[K")
sys.stdout.write('\rNOTICE: Database Update Complete!')
print('')
def update_db_playlist(self):
dothething = "yes"
if dothething == "yes":
playlists = self.PLEX.playlists()
for i, playlist in enumerate(playlists):
duration_average = playlist.duration / playlist.leafCount
self.db.add_shows_to_db(
2,
playlist.title,
duration_average,
'',
'',
playlist.key,
playlist.type
)
# add all entries of playlist to episodes table
episodes = self.PLEX.playlist(playlist.title).items()
for j, episode in enumerate(episodes):
duration = episode.duration
sectionTitle = "Playlists"
itemID = str(episode.playlistItemID)
itemData = self.PLEX.fetchItem(episode.key)
if itemData.type == "episode":
sNo = str(itemData.parentIndex)
eNo = str(itemData.index)
plTitle = episode.grandparentTitle +" - "+ episode.title + " (S" + sNo + "E" + eNo + ")"
else:
sNo = "0"
eNo = "0"
plTitle = episode.title + " ("+str(episode.year)+")"
if duration:
self.db.add_playlist_entries_to_db(
5,
plTitle,
duration,
eNo,
sNo,
playlist.title,
episode.key,
sectionTitle
)
else:
self.db.add_playlist_entries_to_db(
5,
episode.title,
0,
eNo,
sNo,
playlist.title,
episode.key,
sectionTitle
)
self.print_progress(
j + 1,
len(episodes),
prefix = 'Progress Playlist '+str(i+1)+' of '+str(len(playlists))+': ',
suffix = 'Complete ['+playlist.title+']',
bar_length = 40
)
#print('', end='\r')
sys.stdout.write("\033[K")
sys.stdout.write('\rNOTICE: Playlist Database Update Complete!')
print('')
def update_db_movies(self):
print("NOTICE: Updating Local Movies Database")
self.db.create_tables()
libs_dict = config.plexLibraries
sections = self.PLEX.library.sections()
for section in sections:
for correct_lib_name, user_lib_name in libs_dict.items():
if section.title.lower() in [x.lower() for x in user_lib_name]:
if correct_lib_name == "Movies":
sectionMedia = self.PLEX.library.section(section.title).all()
for i, media in enumerate(sectionMedia):
fetchMedia = self.PLEX.fetchItem(media.key)
try:
genres = [genre.tag for genre in fetchMedia.genres]
except:
genres = ''
try:
actors = [actor.tag for actor in fetchMedia.actors]
except:
actors = ''
try:
collections = [collection.tag for collection in fetchMedia.collections]
except:
collections = ''
#actors = {}
#for actor in fetchMedia.actors:
# actors[actor.tag] = str(actor.id)
self.db.add_movies_to_db(media.key.replace('/library/metadata/',''), media.title, media.duration, media.key, section.title, media.contentRating, media.summary, media.originallyAvailableAt, str(genres), str(actors), str(collections), media.studio)
self.print_progress(
i + 1,
len(sectionMedia),
prefix = 'Progress '+section.title+": ",
suffix = 'Complete ['+media.title+']',
bar_length = 40
)
def update_db_tv(self):
print("NOTICE: Updating Local Database, TV ONLY")
self.db.create_tables()
libs_dict = config.plexLibraries
sections = self.PLEX.library.sections()
for section in sections:
for correct_lib_name, user_lib_name in libs_dict.items():
if section.title.lower() in [x.lower() for x in user_lib_name]:
if correct_lib_name == "TV Shows":
sectionMedia = self.PLEX.library.section(section.title).all()
for i, media in enumerate(sectionMedia):
backgroundImagePath = self.PLEX.library.section(section.title).get(media.title)
backgroundImgURL = ''
if isinstance(backgroundImagePath.art, str):
backgroundImgURL = config.baseurl+backgroundImagePath.art+"?X-Plex-Token="+config.token
self.db.add_shows_to_db(
2,
media.title,
media.duration if media.duration else 1,
'',
backgroundImgURL,
media.key,
section.title
)
#add all episodes of each tv show to episodes table
episodes = self.PLEX.library.section(section.title).get(media.title).episodes()
for j, episode in enumerate(episodes):
duration = episode.duration
if duration:
self.db.add_episodes_to_db(
4,
episode.title,
duration,
episode.index,
episode.parentIndex,
media.title,
episode.key,
section.title
)
else:
self.db.add_episodes_to_db(
4,
episode.title,
0,
episode.index,
episode.parentIndex,
media.title,
episode.key,
section.title
)
self.print_progress(
j + 1,
len(episodes),
prefix = 'Progress TV Show '+str(i+1)+' of '+str(len(sectionMedia))+': ',
suffix = 'Complete ['+media.title+']',
bar_length = 40
)
#print('', end='\r')
sys.stdout.write("\033[K")
sys.stdout.write('\rNOTICE: TV Shows Database Update Complete!')
print('')
def update_db_comm(self):
print("NOTICE: Updating Local Database, COMMERCIALS ONLY")
self.db.create_tables()
libs_dict = config.plexLibraries
sections = self.PLEX.library.sections()
for section in sections:
for correct_lib_name, user_lib_name in libs_dict.items():
if section.title.lower() in [x.lower() for x in user_lib_name]:
if correct_lib_name == "Commercials":
sectionMedia = self.PLEX.library.section(section.title).all()
media_length = len(sectionMedia)
for i, media in enumerate(sectionMedia):
self.db.add_commercials_to_db(3, media.title, media.duration, media.key, section.title)
self.print_progress(
i + 1,
media_length,
prefix = 'Progress '+section.title+":",
suffix = 'Complete ['+media.title[0:12]+']',
bar_length = 40
)
#print('', end='\r')
sys.stdout.write("\033[K")
sys.stdout.write('\rNOTICE: Commercials Database Update Complete!')
print('')
def update_schedule(self):
"""Changing dir to the schedules dir."""
abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
os.chdir(dname)
self.db.create_tables()
self.db.remove_all_scheduled_items()
scheduled_days_list = [
"mondays",
"tuesdays",
"wednesdays",
"thursdays",
"fridays",
"saturdays",
"sundays",
"weekdays",
"weekends",
"everyday"
]
section_dict = {
"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"]
}
tree = ET.parse('pseudo_schedule.xml')
root = tree.getroot()
for child in root:
if child.tag in scheduled_days_list:
for time in child.iter("time"):
for key, value in section_dict.items():
if time.attrib['type'] == key or time.attrib['type'] in value:
title = time.attrib['title'] if 'title' in time.attrib else ''
natural_start_time = self.translate_time(time.text)
natural_end_time = 0
section = key
if section == "TV Shows" and time.attrib['title'] == "random":
mediaID_place=999
elif time.attrib['type'] == "random":
mediaID_place=9999
else:
mediaID_place=0
day_of_week = child.tag
duration = time.attrib['duration'] if 'duration' in time.attrib else '0,43200000'
strict_time = time.attrib['strict-time'] if 'strict-time' in time.attrib else 'false'
time_shift = time.attrib['time-shift'] if 'time-shift' in time.attrib else '1'
overlap_max = time.attrib['overlap-max'] if 'overlap-max' in time.attrib else '0'
seriesOffset = time.attrib['series-offset'] if 'series-offset' in time.attrib else ''
xtra = time.attrib['xtra'] if 'xtra' in time.attrib else ''
# start_time_unix = self.translate_time(time.text)
now = datetime.datetime.now()
start_time_unix = mktime(
datetime.datetime.strptime(
self.translate_time(natural_start_time),
self.APP_TIME_FORMAT_STR).replace(day=now.day, month=now.month, year=now.year).timetuple()
)
print("Adding: ", time.tag, section, time.text, time.attrib['title'])
self.db.add_schedule_to_db(
mediaID_place, # mediaID
title, # title
duration, # duration
natural_start_time, # startTime
natural_end_time, # endTime
day_of_week, # dayOfWeek
start_time_unix, # startTimeUnix
section, # section
strict_time, # strictTime
time_shift, # timeShift
overlap_max, # overlapMax
xtra, # xtra kargs (i.e. 'director=director')
)
def drop_db(self):
self.db.drop_db()
def drop_schedule(self):
self.db.drop_schedule()
def remove_all_scheduled_items():
self.db.remove_all_scheduled_items()
def translate_time(self, timestr):
try:
return datetime.datetime.strptime(timestr, '%I:%M %p').strftime(self.APP_TIME_FORMAT_STR)
except ValueError as e:
pass
try:
return datetime.datetime.strptime(timestr, '%I:%M:%S %p').strftime(self.APP_TIME_FORMAT_STR)
except ValueError as e:
pass
try:
return datetime.datetime.strptime(timestr, '%H:%M').strftime(self.APP_TIME_FORMAT_STR)
except ValueError as e:
pass
return timestr
def time_diff(self, time1,time2):
'''
*
* Getting the offest by comparing both times from the unix epoch time and getting the difference.
*
'''
timeA = datetime.datetime.strptime(time1, pseudo_channel.APP_TIME_FORMAT_STR)
timeB = datetime.datetime.strptime(time2, pseudo_channel.APP_TIME_FORMAT_STR)
timeAEpoch = calendar.timegm(timeA.timetuple())
timeBEpoch = calendar.timegm(timeB.timetuple())
tdelta = abs(timeAEpoch) - abs(timeBEpoch)
return int(tdelta/60)
'''
*
* Passing in the endtime from the prev episode and desired start time of this episode, calculate the best start time
* Returns time - for new start time
*
'''
def calculate_start_time(self, prevEndTime, intendedStartTime, timeGap, overlapMax):
self.TIME_GAP = timeGap
self.OVERLAP_GAP = timeGap
self.OVERLAP_MAX = overlapMax
time1 = prevEndTime.strftime(self.APP_TIME_FORMAT_STR)
timeB = datetime.datetime.strptime(intendedStartTime, self.APP_TIME_FORMAT_STR).strftime(self.APP_TIME_FORMAT_STR)
print("INFO: Previous End Time: ", time1, "Intended start time: ", timeB)
timeDiff = self.time_diff(time1, timeB)
print("INFO: Time Difference = "+ str(timeDiff))
newTimeObj = timeB
newStartTime = timeB
'''
*
* ADDED PIECE 6/21/18: Need to check if we are near the day's end
* We will do this by checking if our previous end time is larger than ALL times
* Listed in the "timeset" variable. If it is, we must have hit the end of a
* day and can simply pick the first value of the timeset.
*
* If this doesn't apply, simply move on to the regular "checks"
*
'''
time1A=prevEndTime.strftime('%H:%M:%S')
time1A_comp = datetime.datetime.strptime(time1A, '%H:%M:%S') # there was an issue with the date changing to 1/2, so we had to do this for correct comparison
timeset=[datetime.time(h,m).strftime("%H:%M:%S") for h,m in itertools.product(range(0,24),range(0,60,int(self.OVERLAP_GAP)))]
timeset_last = timeset[-1]
theTimeSetInterval_last = datetime.datetime.strptime(timeset_last, '%H:%M:%S')
prevEndTime = time1A_comp #maybe this will change things?
print("INFO: Previous End Time: ", time1A_comp)
print("INFO: Last Element of the Day: ", theTimeSetInterval_last)
if time1A_comp > theTimeSetInterval_last:
print("NOTICE: We are starting a show with the new day. Using first element of the next day")
theTimeSetInterval = datetime.datetime.strptime(timeset[0], '%H:%M:%S') #This must be the element we are looking for
newStartTime = theTimeSetInterval
'''
*
* If time difference is negative, then we know there is overlap
*
'''
elif timeDiff < 0:
'''
*
* If there is an overlap, then the overlapGap var in config will determine the next increment. If it is set to "15", then the show will will bump up to the next 15 minute interval past the hour.
*
'''
print("NOTICE: OVERLAP DETECTED - elif timeDiff < 0")
timeSetToUse = None
for time in timeset:
theTimeSetInterval = datetime.datetime.strptime(time, '%H:%M:%S')
print("INFO: Time Set Interval: "+str(theTimeSetInterval))
if theTimeSetInterval >= prevEndTime:
print("NOTICE: There is overlap. Setting new time-interval:", theTimeSetInterval)
newStartTime = theTimeSetInterval
break
elif (timeDiff >= 0) and (self.TIME_GAP != -1):
'''
*
* If this value is configured, then the timeGap var in config will determine the next increment.
* If it is set to "15", then the show will will bump up to the next 15 minute interval past the hour.
*
'''
print("NOTICE: OVERLAP DETECTED - (timeDiff >= 0) and (self.TIME_GAP != -1)")
for time in timeset:
theTimeSetInterval = datetime.datetime.strptime(time, '%H:%M:%S')
tempTimeTwoStr = datetime.datetime.strptime(time1, self.APP_TIME_FORMAT_STR).strftime('%H:%M:%S')
formatted_time_two = datetime.datetime.strptime(tempTimeTwoStr, '%H:%M:%S')
if theTimeSetInterval >= formatted_time_two:
print("INFO: Setting new time-interval:", theTimeSetInterval)
newStartTime = theTimeSetInterval
break
else:
print("NOTICE: time1A_comp < theTimeSetInterval_last")
print("INFO: New Start Time = "+newStartTime.strftime(self.APP_TIME_FORMAT_STR))
return newStartTime.strftime(self.APP_TIME_FORMAT_STR)
def get_end_time_from_duration(self, startTime, duration):
time = datetime.datetime.strptime(startTime, self.APP_TIME_FORMAT_STR)
show_time_plus_duration = time + datetime.timedelta(milliseconds=int(duration))
return show_time_plus_duration
def generate_daily_schedule(self):
print("ACTION: Generating Daily Schedule")
#logging.info("##### Dropping previous daily_schedule database")
#self.db.remove_all_daily_scheduled_items()
print("NOTICE: Removing Previous Daily Schedule")
self.db.drop_daily_schedule_table()
print("NOTICE: Adding New Daily Schedule Table to Database")
self.db.create_daily_schedule_table()
if self.USING_COMMERCIAL_INJECTION:
print("NOTICE: Getting Commercials List from Database")
self.commercials = PseudoChannelCommercial(
self.db.get_commercials(),
self.COMMERCIAL_PADDING_IN_SECONDS,
self.USE_DIRTY_GAP_FIX
)
print("NOTICE: Getting Base Schedule")
schedule = self.db.get_schedule_alternate(config.dailyUpdateTime)
weekday_dict = {
"0" : ["mondays", "weekdays", "everyday"],
"1" : ["tuesdays", "weekdays", "everyday"],
"2" : ["wednesdays", "weekdays", "everyday"],
"3" : ["thursdays", "weekdays", "everyday"],
"4" : ["fridays", "weekdays", "everyday"],
"5" : ["saturdays", "weekends", "everyday"],
"6" : ["sundays", "weekends", "everyday"],
}
weekno = datetime.datetime.today().weekday()
schedule_advance_watcher = 0
xtraSeason = None
xtraEpisode = None
last_movie = ""
actors_list = {}
prev_actors = []
prev_movies = []
for entry in schedule:
schedule_advance_watcher += 1
section = entry[9]
for key, val in weekday_dict.items():
if str(entry[7]) in str(val) and int(weekno) == int(key):
media_id = entry[2]
if section == "TV Shows":
next_episode = None
try:
minmax = entry[4].split(",")
min = int(minmax[0])
min = min * 60000
max = int(minmax[1])
max = max * 60000
except:
minmax = entry[4]
min = int(minmax)
min = min * 60000
max = int(minmax)
max = max * 60000
if str(entry[3]).lower() == "random":
if entry[14] == 0:
media_id = 998
else:
media_id = 999
advance_episode = "no"
sections = self.PLEX.library.sections()
shows_list = []
libs_dict = config.plexLibraries
for theSection in sections:
for correct_lib_name, user_lib_name in libs_dict.items():
if theSection.title.lower() in [x.lower() for x in user_lib_name]:
if correct_lib_name == "TV Shows":
while next_episode is None:
print("----------------------------------")
shows = self.PLEX.library.section(theSection.title)
print("NOTICE: Getting Show That Matches Data Filters")
the_show = self.db.get_random_show_data("TV Shows",int(min),int(max),entry[15],entry[16],entry[17],entry[18],entry[19],entry[20])
print("INFO: " + the_show[3])
if (the_show == None):
print("NOTICE: Failed to get shows with data filters, trying with less")
the_show = self.db.get_random_show_data("TV Shows",int(min),int(max),entry[15],None,None,None,entry[19],None)
#the_show = self.db.get_shows(random.choice(shows_list).title)
try:
print("INFO: "+str(the_show[3]))
except:
print("NOTICE: FAILED TO GET RANDOM SHOW")
if (the_show is None):
print("ACTION: Getting random episode of random show")
next_episode = self.db.get_random_episode_duration(int(min), int(max))
attempt = 1
episode_duration = next_episode[4]
while episode_duration < min or episode_duration > max:
print("NOTICE: EPISODE LENGTH OUTSIDE PARAMETERS")
print("ACTION: Getting random episode of random show")
next_episode = self.db.get_random_episode_duration(int(min), int(max))
episode_duration = int(next_episode[4])
attempt = attempt + 1
if attempt > 1000:
episode_duration = max
else:
episode_duration = int(next_episode[4])
print("INFO: Random Selection: "+next_episode[7]+" - S"+str(next_episode[6])+"E"+str(next_episode[5])+" - "+next_episode[3])
else:
print("INFO: entry[2] = " + str(entry[2]))
print("INFO: media_id = " + str(media_id))
if entry[2] == 999 or media_id == 999:
media_id = 999
print("ACTION: Choosing random episode of "+the_show[3].upper())
try:
next_episode = self.db.get_random_episode_of_show_by_data(the_show[2],int(min),int(max),entry[15],entry[21].split(',')[0],entry[21].split(',')[1])
except:
next_episode = self.db.get_random_episode_of_show_by_data(the_show[2],int(min),int(max),entry[15])
elif entry[2] == 998 or media_id == 998:
media_id = 998
if entry[14] == 1:
print("ACTION: Choosing last episode of " +the_show[3].upper())
advance_episode = "no"
next_episode = self.db.get_last_episode(the_show[2]) #get last episode
try:
print("INFO: Scheduled: "+next_episode[7]+" - (S"+str(next_episode[6])+"E"+str(next_episode[5])+") "+next_episode[3])
except:
pass
else:
print("ACTION: Choosing next episode of " +the_show[3].upper())
advance_episode = "yes"
next_episode = self.db.get_next_episode(the_show[3],entry) #get next episode
try:
print("INFO: Scheduled: "+next_episode[7]+" - (S"+str(next_episode[6])+"E"+str(next_episode[5])+") "+next_episode[3])
except:
pass
episode_duration = int(next_episode[4])
show_title = next_episode[7]
xtraSeason = None
xtraEpisode = None
print("INFO: " + next_episode[7] + " - " + next_episode[3] + " (S" + str(next_episode[6]) + "E" + str(next_episode[5]) + ")")
print("----------------------------------")
elif entry[2] == 9999:
media_id = 9999
advance_episode = "no"
print("ACTION: Getting random episode of "+entry[3])
if entry[15] != None:
if entry[15][3] == '*':
print("INFO: Decade = " + str(entry[15]))
airDate=entry[15][0:3]
else:
print("INFO: Air Date = " + str(entry[15]))
airDate=entry[15]
else:
airDate=None
try:
next_episode = self.db.get_random_episode_of_show_by_data_alt(entry[3], int(min), int(max), airDate, entry[21].split(',')[0], entry[21].split(',')[1])
except Exception as e:
print("ERROR: " + str(e))
next_episode = self.db.get_random_episode_of_show_by_data_alt(entry[3], int(min), int(max), airDate)
print("INFO: Episode Selected: S"+str(next_episode[6])+"E"+str(next_episode[5])+" "+next_episode[3].upper())
show_title = next_episode[7]
episode_duration = next_episode[4]
attempt = 1
while int(episode_duration) < min or episode_duration > max:
print("ACTION: Getting random episode of "+entry[3])
next_episode = self.db.get_random_episode_of_show(entry[3])
print("INFO: Episode Selected: S"+str(next_episode[6])+"E"+str(next_episode[5])+" "+next_episode[3].upper())
attempt = attempt + 1
if attempt > 500:
episode_duration = max
else:
episode_duration = next_episode[4]
show_title = next_episode[7]
else:
print("----------------------------------")
if entry[14] == 1:
advance_episode = "no"
print("ACTION: RERUNNING LAST SCHEDULED EPISODE")
#check for same show in MEDIA list
for m in self.MEDIA:
try:
seriesTitle = m.show_series_title
except:
seriesTitle = None
if seriesTitle == entry[3]:
next_episode = self.db.get_episode_from_plexMediaID(m.plex_media_id)
if next_episode == None:
next_episode = self.db.get_last_episode_alt(entry[3]) #get last episode
else:
advance_episode = "yes"
#print("ACTION: GETTING NEXT EPISODE")
#check for same show in MEDIA list
episodeID = None
for m in self.MEDIA:
try:
seriesTitle = m.show_series_title
except:
seriesTitle = None
if seriesTitle == entry[3] and m.media_id == 2:
episodeID = self.db.get_episode_id_alternate(m.plex_media_id,seriesTitle)[0]
#print("INFO: episode ID = "+str(episodeID))
#print("INFO: plex_media_id = "+str(m.plex_media_id))
if episodeID != None:
print("ACTION: GETTING NEXT EPISODE FROM SERIES TITLE ["+seriesTitle+"] AND EPISODE ID ["+str(episodeID)+"]")
next_episode = self.db.get_next_episode_alt(seriesTitle, episodeID, entry)
if next_episode == None:
print("ACTION: GETTING NEXT EPISODE FROM SERIES TITLE["+entry[3]+"]")
next_episode = self.db.get_next_episode(entry[3],entry) #get next episode
try:
print("INFO: Scheduled: "+next_episode[7]+" - (S"+str(next_episode[6])+"E"+str(next_episode[5])+") "+next_episode[3])
except:
pass
show_title = next_episode[7]
try:
episode_rating = str(next_episode[10])
except Exception as e:
print(e)
episode_rating = "None"
try:
episode_notes = str(next_episode[12])
except Exception as e:
print(e)
episode_notes = ""
notes_data = "Rated " + episode_rating + "</br>" + episode_notes
if next_episode != None:
customSectionName = next_episode[9]
episode = Episode(
section, # section_type
next_episode[3], # title
entry[5], # natural_start_time
self.get_end_time_from_duration(self.translate_time(entry[5]), next_episode[4]), # natural_end_time
next_episode[4], # duration
entry[7], # day_of_week
entry[10], # is_strict_time
entry[11], # time_shift
entry[12], # overlap_max
#next_episode[8] if len(next_episode) >= 9 else '', # plex id
next_episode[8], # plex_media_id
customSectionName, # custom lib name
media_id, #media_id
show_title, # show_series_title
next_episode[5], # episode_number
next_episode[6], # season_number
advance_episode, # advance_episode
notes_data #notes
)
self.MEDIA.append(episode)
else:
print("ERROR: Cannot find TV Show Episode, {} in the local db".format(entry[3]))
elif section == "Movies":
minmax = entry[4].split(",")
min = int(minmax[0])
min = min * 60000
max = int(minmax[1])
max = max * 60000
movies_list = []
movies_list_filtered = []
if str(entry[3]).lower() == "random":
if(entry[13] != ''): # xtra params
"""
Using specified Movies library names
"""
libs_dict = config.plexLibraries
sections = self.PLEX.library.sections()
for theSection in sections:
for correct_lib_name, user_lib_name in libs_dict.items():
if theSection.title.lower() in [x.lower() for x in user_lib_name]:
if correct_lib_name == "Movies" and entry[13] != "":
print("----------------------------------")
print("INFO: Movie Xtra Arguments: ", entry[13])
movies = self.PLEX.library.section(theSection.title)
xtra = []
d = {}
if ";" in xtra:
xtra = entry[13].split(';')
else:
if xtra != None:
xtra = str(entry[13]) + ';'
xtra = xtra.split(';')
print(xtra)
try:
"""for thestr in xtra:
print ("INFO: "+thestr)
regex = re.compile(r"\b(\w+)\s*:\s*([^:]*)(?=\s+\w+\s*:|$)")
d.update(regex.findall(thestr))
# turn values into list
for key, val in d.items():
d[key] = val.split(',')"""
if entry[13] != "" and entry[13] != None:
movie_search = self.db.get_movies_xtra(correct_lib_name,int(min),int(max),xtra)
else:
movie_search = self.db.get_movies_data("Movies",int(min),int(max),entry[15],entry[16],entry[17],entry[18],entry[19],entry[20])
for movie in movie_search:
movies_list.append(movie)
except:
pass
if (len(movies_list) > 0):
movie_get = random.choice(movies_list)
movies_list.remove(movie_get)
try:
print("INFO: Movie Title - " + movie_get[3])
the_movie = self.db.get_movie_by_id(movie_get[6])
except Exception as e:
print("ERROR: Key not found")
print(e)
print("INFO: " + movie_get[3])
the_movie = self.db.get_movie(movie_get[3])
movie_duration = the_movie[4]
attempt = 1
while int(movie_duration) < min or movie_duration > max:
movie_get = random.choice(movies_list)
movies_list.remove(movie_get)
try:
print("INFO: Movie Title - " + movie_get[3])
the_movie = self.db.get_movie_by_id(movie_get[6])
except Exception as e:
print("ERROR: Key not found")
print(e)
print("INFO: " + movie_get[3])
the_movie = self.db.get_movie(movie_get[6])
attempt = attempt + 1
if attempt > 500:
movie_duration = max
else:
movie_duration = the_movie[4]
"""Updating movies table in the db with lastPlayedDate entry"""
self.db.update_movies_table_with_last_played_date(the_movie[3])
else:
print("ERROR: xtra args not found, getting random movie")
movie_search = self.db.get_movies_data("Movies",int(min),int(max),None,None,None,None,entry[19],None)
for movie in movie_search:
if movie not in movies_list and movie[3] not in last_movie:
movies_list.append(movie)
movie_get = random.choice(movies_list)
movies_list.remove(movie_get)
try:
print("INFO: Movie Title - " + movie_get[3])
the_movie = self.db.get_movie_by_id(movie_get[6])
except Exception as e:
print("ERROR: Key not found")
print(e)
print("INFO: " + movie_get[3])
the_movie = self.db.get_movie(movie_get[6])
print("INFO: Movie Title - " + str(the_movie[3]))
movie_duration = the_movie[4]
attempt = 1
while int(movie_duration) < min or movie_duration > max:
the_movie = self.db.get_random_movie_duration(int(min), int(max))
attempt = attempt + 1
if attempt > 500:
movie_duration = max
else:
movie_duration = the_movie[4]
"""Updating movies table in the db with lastPlayedDate entry"""
self.db.update_movies_table_with_last_played_date(the_movie[3])
"""minmax = str(entry[4]).split(",")
min = int(minmax[0])
min = min * 60000
max = int(minmax[1])
max = max * 60000
the_movie = self.db.get_random_movie_duration(int(min), int(max))
movie_duration = the_movie[4]
attempt = 1
while int(movie_duration) < min or movie_duration > max:
the_movie = self.db.get_random_movie_duration(int(min), int(max))
attempt = attempt + 1
if attempt > 500:
movie_duration = max
else:
movie_duration = the_movie[4]
movies_list = []
libs_dict = config.plexLibraries
sections = self.PLEX.library.sections()
#Updating movies table in the db with lastPlayedDate entry
self.db.update_movies_table_with_last_played_date(the_movie[3])"""
elif str(entry[3]).lower() == "kevinbacon":
#kevin bacon mode
print("----------------------------------")
print("NOTICE: Kevin Bacon Mode Initiated")
backup_list = []
delete_list = []
xtra = []
for k in actors_list:
if actors_list[k] in prev_actors:
delete_list.append(k)
for dL in delete_list:
actors_list.pop(dL)
"""
Using specified Movies library names
"""
libs_dict = config.plexLibraries
sections = self.PLEX.library.sections()
for theSection in sections:
for correct_lib_name, user_lib_name in libs_dict.items():
if theSection.title.lower() in [x.lower() for x in user_lib_name]:
if correct_lib_name == "Movies":
movies = self.PLEX.library.section(theSection.title)
'''if(entry[13] != None or len(actors_list) > 0): # xtra params
xtra = []
try:
print("INFO: Movie Xtra Arguments: ", entry[13])
except:
print("INFO: Xtra Arguments Not Found")
d = {}'''
if len(actors_list) > 0:
xtra_actors = []
if entry[17] != None and ',' in entry[17]:
xtra_actors = entry[17].split(',')
elif entry[17] != None and ',' not in entry[17]:
xtra_actors.append(entry[17])
for actorName in actors_list:
the_actors = []
for xActor in xtra_actors:
print("INFO: xtra actor = " + xActor)
the_actors.append(xActor)
the_actors.append(actorName)
aLoop = 1
actor_data = ''
print("----------------------------------")
print("INFO: Actor from " + last_movie + " selected - " + actorName)
print("NOTICE: Executing movies search for matches")
print("INFO: " + str(entry[15]) + ', ' + str(entry[16]) + ', ' + str(the_actors) + ', ' + str(entry[18]) + ', ' + str(entry[19]) + ', ' + str(entry[20]))
movie_search = self.db.get_movies_data("Movies",int(min),int(max),entry[15],entry[16],the_actors,entry[18],entry[19],entry[20])
print("INFO: " + str(len(movie_search)) + " results found")
#except Exception as e:
#print(e)
for movie in movie_search:
if movie not in movies_list and movie[3] not in last_movie:
print(str(movie[3]))
movies_list.append(movie)
#print("INFO: Match Found - " + str(movie))
#for movie in movies.search(None, **d):
# movies_list.append(movie)
# print("INFO: Match Found - " + str(movie))
#except Exception as e:
# print("ERROR: " + str(e))
# pass
#print("INFO: Movies List: " + str(movies_list))
else:
print("NOTICE: No previous actor data, skipping...")
'''if ";" in entry[13]:
xtra = entry[13].split(';')
else:
if entry[13] != None:
xtra = str(entry[13]) + ';'
xtra = xtra.split(';')
print(xtra)'''
try:
"""for thestr in xtra:
print ("INFO: "+thestr)
regex = re.compile(r"\b(\w+)\s*:\s*([^:]*)(?=\s+\w+\s*:|$)")
d.update(regex.findall(thestr))
# turn values into list
for key, val in d.items():
d[key] = val.split(',')"""
movie_search = self.db.get_movies_data("Movies",int(min),int(max),entry[15],entry[16],entry[17],entry[18],entry[19],entry[20])
for movie in movie_search:
movies_list.append(movie)
#print("INFO: Match Found - " + movie)
except Exception as e:
print("ERROR: " + str(e))
pass
#print(xtra)
if (len(movies_list) > 0):
print("----------------------------------")
print("INFO: " + str(len(movies_list)) + " movies in list")
movie_get = random.choice(movies_list)
movies_list.remove(movie_get)
try:
print("INFO: Movie Title - " + movie_get[3])
the_movie = self.db.get_movie_by_id(movie_get[6])
except Exception as e:
print("ERROR: Key not found")
print(e)
print("INFO: " + movie_get[3])
the_movie = self.db.get_movie(movie_get[3])
attempt = 1
while the_movie[6] in prev_movies and last_movie in the_movie[3] and attempt < 500:
movie_get = random.choice(movies_list)
try:
print("INFO: Movie Title - " + movie_get[3])
the_movie = self.db.get_movie_by_id(movie_get[6])
except Exception as e:
print("ERROR: Key not found")
print(e)
print("INFO: " + movie_get[3])
the_movie = self.db.get_movie(movie_get[3])
attempt = attempt + 1
movie_duration = the_movie[4]
attempt = 1
while int(movie_duration) < min or movie_duration > max:
if len(movies_list) > 0:
movie_get = random.choice(movies_list)
movies_list.remove(movie_get)
try:
print("INFO: Movie Title - " + movie_get[3])
the_movie = self.db.get_movie_by_id(movie_get[6])
except Exception as e:
print("ERROR: Key not found")
print(e)
print("INFO: " + movie_get[3])
the_movie = self.db.get_movie(movie_get[3])
else:
the_movie = self.db.get_random_movie_duration(int(min), int(max))
print("ERROR: Falling back to random movie that fits in the duration window")
print("INFO: Movie Title - " + str(the_movie[3]))
attempt = attempt + 1
if attempt > 500:
movie_duration = max
else:
movie_duration = the_movie[4]
"""Updating movies table in the db with lastPlayedDate entry"""
self.db.update_movies_table_with_last_played_date(the_movie[3])
else:
print("----------------------------------")
print("ERROR: No movies found, re-rolling without xtra args")
d = {}
if len(actors_list) > 0:
for actorName in actors_list:
actorID = actorName
print("INFO: Actor from " + last_movie + " selected - " + actorName)
try:
xtra = xtra.append("actor:"+str(actorID))
except:
xtra = ["actor:"+str(actorID)]
try:
"""for thestr in xtra:
print ("INFO: "+thestr)
regex = re.compile(r"\b(\w+)\s*:\s*([^:]*)(?=\s+\w+\s*:|$)")
d.update(regex.findall(thestr))
# turn values into list
for key, val in d.items():
d[key] = val.split(',')"""
movie_search = self.db.get_movies_data("Movies",int(min),int(max),None,None,actor_data,None,entry[19],None)
#movie_search = movies.search(None, **d)
for movie in movie_search:
if movie not in movies_list and movie[3] not in last_movie:
movies_list.append(movie)
#print("INFO: Match Found - " + movie)
except Exception as e:
print("ERROR: " + str(e))
pass
print("INFO: " + str(len(movie_search)) + " results found")
if (len(movies_list) > 0):
print("----------------------------------")
print("INFO: " + str(len(movies_list)) + " movies in list")
movie_get = random.choice(movies_list)
movies_list.remove(movie_get)
try:
print("INFO: Movie Title - " + movie_get[3])
the_movie = self.db.get_movie_by_id(movie_get[6])
except Exception as e:
print("ERROR: Key not found")
print(e)
print("INFO: " + movie_get[3])
the_movie = self.db.get_movie(movie_get[3])
attempt = 1
while the_movie[6] in prev_movies and last_movie in the_movie[3] and attempt < 500:
movie_get = random.choice(movies_list)
movies_list.remove(movie_get)
try:
print("INFO: Movie Title - " + movie_get[3])
the_movie = self.db.get_movie_by_id(movie_get[6])
except Exception as e:
print("ERROR: Key not found")
print(e)
print("INFO: " + movie_get[3])
the_movie = self.db.get_movie(movie_get[6])
attempt = attempt + 1
attempt = 1
movie_duration = the_movie[4]
while int(movie_duration) < min or movie_duration > max:
if len(movies_list) > 0:
try:
movies_list.remove(the_movie)
except Exception as e:
print(the_movie)
print(e)
movie_get = random.choice(movies_list)
try:
print("INFO: Movie Title - " + movie_get[3])
the_movie = self.db.get_movie_by_id(movie_get[6])
except Exception as e:
print("ERROR: Key not found")
print(e)
print("INFO: " + movie_get[3])
the_movie = self.db.get_movie(movie_get[3])
else:
the_movie = self.db.get_random_movie_duration(int(min), int(max))
print("ERROR: Falling back to random movie that fits in the duration window")
print("INFO: Movie Title - " + str(the_movie[3]))
attempt = attempt + 1
if attempt > 500:
movie_duration = max
else:
movie_duration = the_movie[4]
else:
print("ERROR: Kevin Bacon Mode failed to find a match, selecting random movie")
movies_list = []
movie_search = self.db.get_movies_data("Movies",int(min),int(max),entry[14],entry[15],entry[16],entry[17],entry[18],entry[19])
for movie in movie_search:
if movie not in movies_list and movie[3] not in last_movie:
movies_list.append(movie)
if len(movies_list) < 1:
print("ERROR: xtra args not found, getting random movie")
movie_search = self.db.get_movies_data("Movies",int(min),int(max),None,None,None,None,entry[19],None)
try:
for movie in movie_search:
if movie not in movies_list and movie[3] not in last_movie:
movies_list.append(movie)
except:
movies_list.append(movie)
movie_get = random.choice(movies_list)
movies_list.remove(movie_get)
try:
print("INFO: Movie Title - " + movie_get[3])
the_movie = self.db.get_movie_by_id(movie_get[6])
except Exception as e:
print("ERROR: Key not found")
print(e)
print("INFO: " + movie_get[3])
the_movie = self.db.get_movie(movie_get[6])
print("INFO: Movie Title - " + str(the_movie[3]))
print("----------------------------------")
movie_duration = the_movie[4]
attempt = 1
while int(movie_duration) < min or movie_duration > max:
the_movie = self.db.get_random_movie_duration(int(min), int(max))
attempt = attempt + 1
if attempt > 500:
movie_duration = max
else:
movie_duration = the_movie[4]
"""Updating movies table in the db with lastPlayedDate entry"""
self.db.update_movies_table_with_last_played_date(the_movie[3])
try:
prev_actors.append(actorID)
except:
pass
prev_movies.append(the_movie[6])
#last_movie = the_movie[3]
"""Updating movies table in the db with lastPlayedDate entry"""
self.db.update_movies_table_with_last_played_date(the_movie[3])
else:
the_movie = self.db.get_movie(entry[3])
if str(entry[3]).lower() == "kevinbacon":
media_id = 112
else:
media_id = 1
if the_movie != None:
print("----------------------------------")
print("NOTICE: Movie Selected - " + the_movie[3])
#get plex metadata
plex_movie = self.PLEX.fetchItem(the_movie[6])
last_data = ""
notes_data = ""
if str(entry[3]).lower() == "kevinbacon":
actors_list_old = actors_list
actors_list = {}
actor_match = ""
print("NOTICE: Replacing Actors List with list from " + the_movie[3])
for actor in plex_movie.actors:
actors_list[actor.tag] = actor.id
if actor.tag in actors_list_old.keys():
print("INFO: Match between movies - " + actor.tag)
prev_actors.append(actor.id)
if actor_match == "":
actor_match = actor.tag
if actor_match != "":
notes_data = "This movie derived from " + last_movie + " through " + actor_match + "\n"
else:
notes_data = ""
last_movie = the_movie[3]
actors_data = the_movie[12].strip('][').split(',')
try:
notes_data = notes_data + "Rated " + str(the_movie[8]) + "</br>Starring: " + str(actors_data[0]) + ", " + str(actors_data[1]) + " and " + str(actors_data[2]) + "</br>" + str(the_movie[10]) + "</br>" + str(the_movie[14])
except:
notes_data = notes_data
movie = Movie(
section, # section_type
the_movie[3], # title
entry[5], # natural_start_time
self.get_end_time_from_duration(entry[5], the_movie[4]), # natural_end_time
the_movie[4], # duration
entry[7], # day_of_week
entry[10], # is_strict_time
entry[11], # time_shift
entry[12], # overlap_max
the_movie[6], # plex id
the_movie[7], # custom lib name
media_id, # media_id
notes_data # notes (for storing kevin bacon data)
)
self.MEDIA.append(movie)
else:
print(str("ERROR: Cannot find Movie, {} in the local db".format(entry[3])).encode('UTF-8'))
elif section == "Music":
the_music = self.db.get_music(entry[3])
if the_music != None:
music = Music(
section, # section_type
the_music[3], # title
entry[5], # natural_start_time
self.get_end_time_from_duration(entry[5], the_music[4]), # natural_end_time
the_music[4], # duration
entry[7], # day_of_week
entry[10], # is_strict_time
entry[11], # time_shift
entry[12], # overlap_max
the_music[6], # plex id
the_music[7], # custom lib name
)
self.MEDIA.append(music)
else:
print(str("ERROR: Cannot find Music, {} in the local db".format(entry[3])).encode('UTF-8'))
elif section == "Video":
the_video = self.db.get_video(entry[3])
if the_music != None:
video = Video(
section, # section_type
the_video[3], # title
entry[5], # natural_start_time
self.get_end_time_from_duration(entry[5], the_video[4]), # natural_end_time
the_video[4], # duration
entry[7], # day_of_week
entry[10], # is_strict_time
entry[11], # time_shift
entry[12], # overlap_max
the_video[6], # plex id
the_video[7], # custom lib name
)
self.MEDIA.append(video)
else:
print(str("ERROR: Cannot find Video, {} in the local db".format(entry[3])).encode('UTF-8'))
else:
pass
"""If we reached the end of the scheduled items for today, add them to the daily schedule
"""
if schedule_advance_watcher >= len(schedule):
print("INFO: Finished processing time entries, generating daily_schedule")
previous_episode = None
for entry in self.MEDIA:
if previous_episode != None:
natural_start_time = datetime.datetime.strptime(entry.natural_start_time, self.APP_TIME_FORMAT_STR)
natural_end_time = entry.natural_end_time
if entry.is_strict_time.lower() == "true":
print("INFO: Strict-time: {}".format(str(entry.title)))
entry.end_time = self.get_end_time_from_duration(
self.translate_time(entry.start_time),
entry.duration
)
if entry.end_time.hour >= 0 and entry.end_time.hour < int(config.dailyUpdateTime[0]):
entry.end_time = entry.end_time + datetime.timedelta(days=1)
if natural_start_time.hour < int(config.dailyUpdateTime[0]) and entry.end_time.hour >= int(config.dailyUpdateTime[0]):
entry.end_time = datetime.datetime.strptime('1900-01-02 0' + str(int(config.dailyUpdateTime[0])-1) + ':59:59', '%Y-%m-%d %H:%M:%S')
"""Get List of Commercials to inject"""
if self.USING_COMMERCIAL_INJECTION:
list_of_commercials = self.commercials.get_commercials_to_place_between_media(
previous_episode,
entry,
entry.is_strict_time.lower(),
config.dailyUpdateTime
)
for commercial in list_of_commercials:
self.db.add_media_to_daily_schedule(commercial)
self.db.add_media_to_daily_schedule(entry)
previous_episode = entry
if entry.custom_section_name == "TV Shows" and entry.advance_episode != "no":
self.db.update_shows_table_with_last_episode(entry.show_series_title, entry.plex_media_id)
elif entry.custom_section_name == "Playlists" and entry.advance_episode != "no":
self.db.update_shows_table_with_last_episode(entry.show_series_title, entry.plex_media_id)
elif entry.is_strict_time.lower() == "secondary": #This mode starts a show "already in progress" if the previous episode or movie runs past the start time of this one
print("INFO Pre-empt Allowed: {}".format(str(entry.title)))
try:
prev_end_time = datetime.datetime.strptime(str(previous_episode.end_time), '%Y-%m-%d %H:%M:%S.%f')
except ValueError:
prev_end_time = datetime.datetime.strptime(str(previous_episode.end_time), '%Y-%m-%d %H:%M:%S')
prev_end_time = prev_end_time.strftime(self.APP_TIME_FORMAT_STR)
start_time_difference=self.time_diff(str(entry.natural_start_time),str(prev_end_time))
start_time_difference=start_time_difference*60
print("INFO: Entry Duration = {}".format(str(entry.duration)))
print("INFO: Start Time Difference = {}".format(str(start_time_difference)))
if start_time_difference > 0:
running_duration = entry.duration - abs(start_time_difference)
print("INFO: Running Duration = {}".format(str(running_duration)))
entry.start_time = datetime.datetime.strptime(entry.natural_start_time, self.APP_TIME_FORMAT_STR) + datetime.timedelta(seconds=abs(start_time_difference))
entry.start_time = datetime.datetime.strftime(entry.start_time, self.APP_TIME_FORMAT_STR)
print("INFO: New Start Time = {}".format(str(entry.start_time)))
entry.end_time = self.get_end_time_from_duration(
self.translate_time(natural_start_time.strftime(self.APP_TIME_FORMAT_STR)),
entry.duration
)
if entry.end_time.hour >= 0 and entry.end_time.hour < int(config.dailyUpdateTime[0]):
entry.end_time = entry.end_time + datetime.timedelta(days=1)
if natural_start_time.hour < int(config.dailyUpdateTime[0]) and entry.end_time.hour >= int(config.dailyUpdateTime[0]):
entry.end_time = datetime.datetime.strptime('1900-01-02 0' + str(int(config.dailyUpdateTime[0])-1) + ':59:59', '%Y-%m-%d %H:%M:%S')
print("INFO: End Time = {}".format(str(entry.end_time)))
overlap_max_seconds=int(entry.overlap_max) * 60
print(("INFO: Overlap Max is "+str(overlap_max_seconds)))
max_end_time=datetime.datetime.strptime(entry.natural_start_time, self.APP_TIME_FORMAT_STR) + datetime.timedelta(seconds=overlap_max_seconds)
if datetime.datetime.strptime(entry.start_time, self.APP_TIME_FORMAT_STR) > max_end_time or datetime.datetime.strptime(entry.start_time, self.APP_TIME_FORMAT_STR) > entry.end_time:
print("ALERT: START TIME PAST MAXIMUM ALLOWED TIME, SKIPPING ENTRY")
pass
else:
"""Get List of Commercials to Inject"""
if self.USING_COMMERCIAL_INJECTION:
list_of_commercials = self.commercials.get_commercials_to_place_between_media(
previous_episode,
entry,
entry.is_strict_time.lower(),
config.dailyUpdateTime
)
for commercial in list_of_commercials:
self.db.add_media_to_daily_schedule(commercial)
self.db.add_media_to_daily_schedule(entry)
previous_episode = entry
if entry.custom_section_name == "TV Shows" and entry.advance_episode != "no":
self.db.update_shows_table_with_last_episode(entry.show_series_title, entry.plex_media_id)
elif entry.custom_section_name == "Playlists" and entry.advance_episode != "no":
self.db.update_shows_table_with_last_episode(entry.show_series_title, entry.plex_media_id)
else:
try:
print("INFO: Variable Time: {}".format(str(entry.title).encode(sys.stdout.encoding, errors='replace')))
except:
pass
try:
new_starttime = self.calculate_start_time(
previous_episode.end_time,
entry.natural_start_time,
previous_episode.time_shift,
""
)
except Exception as e:
print("ERROR: Error in calculate_start_time")
print(e)
new_starttime = self.calculate_start_time(
previous_episode.end_time,
entry.natural_start_time,
5,
""
)
print("INFO: New start time:", new_starttime)
entry.start_time = datetime.datetime.strptime(new_starttime, self.APP_TIME_FORMAT_STR).strftime(self.APP_TIME_FORMAT_STR)
entry.end_time = self.get_end_time_from_duration(entry.start_time, entry.duration)
if entry.end_time.hour >= 0 and entry.end_time.hour < int(config.dailyUpdateTime[0]):
entry.end_time = entry.end_time + datetime.timedelta(days=1)
if natural_start_time.hour < int(config.dailyUpdateTime[0]) and entry.end_time.hour >= int(config.dailyUpdateTime[0]):
entry.end_time = datetime.datetime.strptime('1900-01-02 0' + str(int(config.dailyUpdateTime[0])-1) + ':59:59', '%Y-%m-%d %H:%M:%S')
"""Get List of Commercials to inject"""
if self.USING_COMMERCIAL_INJECTION:
list_of_commercials = self.commercials.get_commercials_to_place_between_media(
previous_episode,
entry,
entry.is_strict_time.lower(),
config.dailyUpdateTime
)
for commercial in list_of_commercials:
self.db.add_media_to_daily_schedule(commercial)
self.db.add_media_to_daily_schedule(entry)
previous_episode = entry
if entry.custom_section_name == "TV Shows" and entry.advance_episode != "no":
self.db.update_shows_table_with_last_episode(entry.show_series_title, entry.plex_media_id)
elif entry.custom_section_name == "Playlists" and entry.advance_episode != "no":
self.db.update_shows_table_with_last_episode(entry.show_series_title, entry.plex_media_id)
else:
self.db.add_media_to_daily_schedule(entry)
previous_episode = entry
if entry.custom_section_name == "TV Shows" and entry.advance_episode != "no":
self.db.update_shows_table_with_last_episode(entry.show_series_title, entry.plex_media_id)
elif entry.custom_section_name == "Playlists" and entry.advance_episode != "no":
self.db.update_shows_table_with_last_episode(entry.show_series_title, entry.plex_media_id)
if self.USING_COMMERCIAL_INJECTION:
list_of_commercials = self.commercials.get_commercials_to_place_between_media(
previous_episode,
"reset",
"true",
config.dailyUpdateTime
)
for commercial in list_of_commercials:
self.db.add_media_to_daily_schedule(commercial)
print("NOTICE: END OF DAY - RESET TIME REACHED")
def run_commercial_injection(self):
pass
def make_xml_schedule(self):
self.controller.make_xml_schedule(self.db.get_daily_schedule())
def show_clients(self):
print("Connected Clients:")
for i, client in enumerate(self.PLEX.clients()):
print("INFO: ", str(i + 1)+".", "Client:", client.title)
def show_schedule(self):
print("Daily Pseudo Schedule:")
daily_schedule = self.db.get_daily_schedule()
for i , entry in enumerate(daily_schedule):
print(str("INFO {} {} {} {} {} {}".format(str(i + 1)+".", entry[8], entry[11], entry[6], " - ", entry[3])).encode(sys.stdout.encoding, errors='replace'))
def last_episode(self):
print("----- Change the 'Last Episode' set for a show. -----")
print("Enter the name of the show.")
showName = input("Show Name: ")
showData = self.db.get_shows(showName)
#print("SHOW SELECTED: "+showData[3])
if(showData is not None):
print("Enter the 'ratingKey' value (also integer following '/library/metadata/' in the URL) of the 'last episode' from the API, or leave blank to select by season and episode number (does not work for Playlists).")
plexID = input('/library/metadata/')
episodeData = self.db.get_episode_from_plexMediaID('/library/metadata/'+plexID)
if episodeData != None:
print("Setting "+episodeData[7]+" - "+episodeData[3]+" S"+str(episodeData[6])+"E"+str(episodeData[5])+" as the Last Episode in the Shows Database for "+showName)
self.db.update_shows_table_with_last_episode(showName, episodeData[8])
else:
print("Enter the season and episode numbers for the 'last episode' (episode previous to the episode you wish to be scheduled on next -g run")
sNo = input("Season Number: ")
eNo = input("Episode Number: ")
episodeData = self.db.get_episode_from_season_episode(showName,sNo,eNo)
if(episodeData is not None):
print("Setting "+episodeData[7]+" - "+episodeData[3]+" S"+str(episodeData[6])+"E"+str(episodeData[5])+" as the Last Episode in the Shows Database for "+showName)
self.db.update_shows_table_with_last_episode(showName, episodeData[8])
else:
print("ERROR: EPISODE NOT FOUND IN PSEUDO CHANNEL DATABASE")
sys.exit(1)
else:
print("ERROR: SHOW NOT FOUND IN PSEUDO CHANNEL DATABASE")
sys.exit(1)
def episode_randomizer(self):
all_shows = list(self.db.get_shows_titles())
shows_list = []
for one_show in all_shows:
shows_list.append(str(one_show[0]))
for a_show in shows_list:
a_show = str(a_show)
try:
random_episode = self.db.get_random_episode_of_show(a_show)
print(a_show + " - " + random_episode[3])
self.db.update_shows_table_with_last_episode(a_show, random_episode[8])
except TypeError as e:
print("ERROR: "+a_show)
print(e)
random_episode = self.db.get_random_episode_of_show_alt(a_show)
print(a_show + " - " + random_episode[3])
self.db.update_shows_table_with_last_episode_alt(a_show, random_episode[8])
continue
def write_json_to_file(self, data, fileName):
fileName = fileName
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)
def export_queue(self):
shows_table = self.db.get_shows_table()
json_string = json.dumps(shows_table)
print("NOTICE: Exporting queue ")
self.write_json_to_file(json_string, "pseudo-queue.json")
print("NOTICE: Done.")
self.export_daily_schedule()
def import_queue(self):
"""Dropping previous shows table before adding the imported data"""
#self.db.clear_shows_table()
with open('pseudo-queue.json') as data_file:
data = json.load(data_file)
#print(data)
for row in data:
print("lastEpisodeTitle:", row[5])
self.db.import_shows_table_by_row(
row[2],
row[3],
row[4],
row[5],
row[6],
row[7],
)
print("NOTICE: Queue Import Complete")
self.import_daily_schedule()
def export_daily_schedule(self):
daily_schedule_table = self.db.get_daily_schedule()
json_string = json.dumps(daily_schedule_table)
print("NOTICE: Exporting Daily Schedule ")
self.write_json_to_file(json_string, "pseudo-daily_schedule.json")
print("NOTICE: Done.")
def import_daily_schedule(self):
"""Dropping previous Daily Schedule table before adding the imported data"""
self.db.remove_all_daily_scheduled_items()
with open('pseudo-daily_schedule.json') as data_file:
data = json.load(data_file)
#pprint(data)
for row in data:
"""print row"""
self.db.import_daily_schedule_table_by_row(
row[2],
row[3],
row[4],
row[5],
row[6],
row[7],
row[8],
row[9],
row[10],
row[11],
row[12],
row[13],
)
print("NOTICE: Daily Schedule Import Complete")
def get_daily_schedule_cache_as_json(self):
data = []
try:
with open('../.pseudo-cache/daily-schedule.json') as data_file:
data = json.load(data_file)
#pprint(data)
except IOError as e:
print("ERROR: Having issues opening the pseudo-cache file.")
print(e)
return data
def save_daily_schedule_as_json(self):
daily_schedule_table = self.db.get_daily_schedule()
json_string = json.dumps(daily_schedule_table)
print("NOTICE: Saving Daily Schedule Cache ")
self.save_file(json_string, 'daily-schedule.json', '../.pseudo-cache/')
def save_file(self, data, filename, path="./"):
fileName = filename
writepath = path
if not os.path.exists(writepath):
os.makedirs(writepath)
if os.path.exists(writepath+fileName):
os.remove(writepath+fileName)
mode = 'w'
with open(writepath+fileName, mode) as f:
f.write(data)
def rotate_log(self):
try:
os.remove('../pseudo-channel.log')
except OSError:
pass
try:
os.remove('./pseudo-channel.log')
except OSError:
pass
def signal_term_handler(self, signal, frame):
logging.info('NOTICE: got SIGTERM')
self.controller.stop_media()
self.exit_app()
sys.exit(0)
def exit_app(self):
logging.info('NOTICE: - Exiting Pseudo TV & cleaning up.')
for i in self.MEDIA:
del i
self.MEDIA = None
self.controller = None
self.db = None
sleep(1)
if __name__ == '__main__':
pseudo_channel = PseudoChannel()
banner = textwrap.dedent('''\
# __ __
# |__)_ _ _| _ / |_ _ _ _ _| _
# | _)(-|_|(_|(_)\__| )(_|| )| )(-|. |_)\/
# | /
A Custom TV Channel for Plex
''')
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description = banner)
'''
*
* Primary arguments: "python PseudoChannel.py -u -xml -g -r"
*
'''
parser.add_argument('-u', '--update',
action='store_true',
help='Update the local database with Plex libraries.')
parser.add_argument('-um', '--update_movies',
action='store_true',
help='Update the local database with Plex MOVIE libraries ONLY.')
parser.add_argument('-utv', '--update_tv',
action='store_true',
help='Update the local database with Plex TV libraries ONLY.')
parser.add_argument('-up', '--update_playlist',
action='store_true',
help='Update the local database with Plex PLAYLIST libraries ONLY.')
parser.add_argument('-uc', '--update_commercials',
action='store_true',
help='Update the local database with Plex COMMERCIAL libraries ONLY.')
parser.add_argument('-xml', '--xml',
action='store_true',
help='Update the local database with the pseudo_schedule.xml.')
parser.add_argument('-g', '--generate_schedule',
action='store_true',
help='Generate the daily schedule.')
parser.add_argument('-r', '--run',
action='store_true',
help='Run this program.')
parser.add_argument('-ep', '--episode_randomizer',
action='store_true',
help='Randomize all shows episode progress.')
parser.add_argument('-le', '--last_episode',
action='store_true',
help='Set last episode for a show. The next time -g is run, it will start with the episode after the one set.')
'''
*
* Show connected clients: "python PseudoChannel.py -c"
*
'''
parser.add_argument('-c', '--show_clients',
action='store_true',
help='Show Plex clients.')
'''
*
* Show schedule (daily): "python PseudoChannel.py -s"
*
'''
parser.add_argument('-s', '--show_schedule',
action='store_true',
help='Show scheduled media for today.')
'''
*
* Make XML / HTML Schedule: "python PseudoChannel.py -m"
*
'''
parser.add_argument('-m', '--make_html',
action='store_true',
help='Makes the XML / HTML schedule based on the daily_schedule table.')
'''
*
* Export queue: "python PseudoChannel.py -e"
*
'''
parser.add_argument('-e', '--export_queue',
action='store_true',
help='Exports the current queue for episodes.')
'''
*
* Import queue: "python PseudoChannel.py -i"
*
'''
parser.add_argument('-i', '--import_queue',
action='store_true',
help='Imports the current queue for episodes.')
'''
*
* Export Daily Schedule: "python PseudoChannel.py -eds"
*
'''
parser.add_argument('-eds', '--export_daily_schedule',
action='store_true',
help='Exports the current Daily Schedule.')
'''
*
* Import Daily Schedule: "python PseudoChannel.py -ids"
*
'''
parser.add_argument('-ids', '--import_daily_schedule',
action='store_true',
help='Imports the current Daily Schedule.')
globals().update(vars(parser.parse_args()))
args = parser.parse_args()
if args.update:
pseudo_channel.update_db()
if args.update_movies:
pseudo_channel.update_db_movies()
if args.update_playlist:
pseudo_channel.update_db_playlist()
if args.update_tv:
pseudo_channel.update_db_tv()
if args.update_commercials:
pseudo_channel.update_db_comm()
if args.xml:
pseudo_channel.update_schedule()
if args.episode_randomizer:
pseudo_channel.episode_randomizer()
if args.last_episode:
pseudo_channel.last_episode()
if args.show_clients:
pseudo_channel.show_clients()
if args.show_schedule:
pseudo_channel.show_schedule()
if args.export_queue:
pseudo_channel.export_queue()
if args.import_queue:
pseudo_channel.import_queue()
if args.export_daily_schedule:
pseudo_channel.export_daily_schedule()
if args.import_daily_schedule:
pseudo_channel.import_daily_schedule()
if args.generate_schedule:
if pseudo_channel.DEBUG:
pseudo_channel.generate_daily_schedule()
else:
try:
pseudo_channel.generate_daily_schedule()
except:
print("ERROR: Recieved error when running generate_daily_schedule()")
if args.make_html:
pseudo_channel.make_xml_schedule()
if args.run:
print(banner)
print("INFO: To run this in the background:")
print("screen -d -m bash -c 'python PseudoChannel.py -r; exec sh'")
"""Every minute on the minute check the DB startTimes of all media to
determine whether or not to play. Also, check the now_time to
see if it's midnight (or 23.59), if so then generate a new daily_schedule
"""
"""Every <user specified day> rotate log"""
dayToRotateLog = pseudo_channel.ROTATE_LOG.lower()
schedule.every().friday.at("00:00").do(pseudo_channel.rotate_log)
logging.info("NOTICE: Running PseudoChannel.py -r")
def trigger_what_should_be_playing_now():
def nearest(items, pivot):
return min(items, key=lambda x: abs(x - pivot))
#dates_list = [datetime.datetime.strptime(''.join(str(date[8])), pseudo_channel.APP_TIME_FORMAT_STR) for date in daily_schedule]
now = datetime.datetime.now()
now = now.replace(year=1900, month=1, day=1)
#closest_media = nearest(dates_list, now)
#print(closest_media)
prevItem = None
db = PseudoChannelDatabase("pseudo-channel.db")
item = db.get_now_playing()
item_time = datetime.datetime.strptime(''.join(str(item[8])), pseudo_channel.APP_TIME_FORMAT_STR)
#if item_time == closest_media:
#print "Line 1088, Here", item
elapsed_time = item_time - now
print("INFO: "+str(elapsed_time.total_seconds()))
try:
endTime = datetime.datetime.strptime(item[9], '%Y-%m-%d %H:%M:%S.%f')
except ValueError:
endTime = datetime.datetime.strptime(item[9], '%Y-%m-%d %H:%M:%S')
# we need to play the content and add an offest
if elapsed_time.total_seconds() < 0 and \
endTime > now:
print(str("NOTICE: Queueing up {} to play right away.".format(item[3])).encode('UTF-8'))
offset = int(abs(elapsed_time.total_seconds() * 1000))
try:
nat_start = datetime.datetime.strptime(item[9], '%Y-%m-%d %H:%M:%S.%f') - datetime.timedelta(milliseconds=item[7])
except:
nat_start = datetime.datetime.strptime(item[9], '%Y-%m-%d %H:%M:%S') - datetime.timedelta(milliseconds=item[7])
schedule_offset = nat_start - datetime.datetime.strptime(item[8], pseudo_channel.APP_TIME_FORMAT_STR)
schedule_offset = schedule_offset.total_seconds()
print("INFO: Schedule Offset = " + str(schedule_offset))
nat_start = nat_start.strftime(pseudo_channel.APP_TIME_FORMAT_STR)
print("INFO: Natural Start Time:")
print(nat_start)
daily_schedule = pseudo_channel.db.get_daily_schedule()
if schedule_offset < 0:
schedule_offset_ms = abs(schedule_offset) * 1000
offset_plus = int(offset + abs(schedule_offset_ms))
print("INFO: Updated Offset = " + str(offset_plus))
pseudo_channel.controller.play(item, daily_schedule, offset_plus)
else:
print("INFO: No Offset Update")
pseudo_channel.controller.play(item, daily_schedule, offset)
def job_that_executes_once(item, schedulelist):
print(str("NOTICE: Readying media: '{}'".format(item[3])).encode('UTF-8'))
next_start_time = datetime.datetime.strptime(item[8], pseudo_channel.APP_TIME_FORMAT_STR)
now = datetime.datetime.now()
#now = now.replace(year=1900, month=1, day=1)
time_diff = next_start_time - now
nat_start = datetime.datetime.strptime(item[9], '%Y-%m-%d %H:%M:%S.%f') - datetime.timedelta(milliseconds=item[7])
schedule_offset = nat_start - datetime.datetime.strptime(item[8], pseudo_channel.APP_TIME_FORMAT_STR)
schedule_offset = schedule_offset.total_seconds()
print("INFO: Schedule Offset = " + str(schedule_offset))
nat_start = nat_start.strftime(pseudo_channel.APP_TIME_FORMAT_STR)
print("INFO: Natural Start Time: " + str(nat_start))
daily_schedule = pseudo_channel.db.get_daily_schedule()
if time_diff.total_seconds() > 0:
nat_start = datetime.datetime.strptime(item[9], '%Y-%m-%d %H:%M:%S.%f') - datetime.timedelta(milliseconds=item[7])
schedule_offset = nat_start - datetime.datetime.strptime(item[8], pseudo_channel.APP_TIME_FORMAT_STR)
schedule_offset = schedule_offset.total_seconds()
print("INFO: Schedule Offset = " + str(schedule_offset))
nat_start = nat_start.strftime(pseudo_channel.APP_TIME_FORMAT_STR)
print("INFO: Natural Start Time: " + str(nat_start))
print("NOTICE: Sleeping for {} seconds before playing: '{}'".format(time_diff.total_seconds(), item[3]))
sleep(int(time_diff.total_seconds()))
if pseudo_channel.DEBUG:
print("NOTICE: Woke up!")
if schedule_offset < 0: #OFFSET CHECKER
schedule_offset_ms = abs(schedule_offset) * 1000
print("INFO: Updated Offset = " + str(schedule_offset_ms))
pseudo_channel.controller.play(item, daily_schedule, schedule_offset_ms)
else:
print("INFO: job_that_executes_once - No offset")
pseudo_channel.controller.play(item, daily_schedule)
else:
nat_start = datetime.datetime.strptime(item[9], '%Y-%m-%d %H:%M:%S.%f') - datetime.timedelta(milliseconds=item[7])
schedule_offset = nat_start - datetime.datetime.strptime(item[8], pseudo_channel.APP_TIME_FORMAT_STR)
schedule_offset = schedule_offset.total_seconds()
print("INFO: Schedule Offset = " + str(schedule_offset))
nat_start = nat_start.strftime(pseudo_channel.APP_TIME_FORMAT_STR)
print("INFO: Natural Start Time: " + str(nat_start))
if schedule_offset < 0:
schedule_offset_ms = int(abs(schedule_offset) * 1000)
print("INFO: Updated Offset = " + str(schedule_offset_ms))
pseudo_channel.controller.play(item, daily_schedule, schedule_offset_ms)
else:
print("INFO: job_that_executes_once - No offset 2")
pseudo_channel.controller.play(item, daily_schedule)
return schedule.CancelJob
def generate_memory_schedule(schedulelist, isforupdate=False):
print("NOTICE: Generating Memory Schedule.")
now = datetime.datetime.now()
#now = now.replace(year=1900, month=1, day=1)
pseudo_cache = pseudo_channel.get_daily_schedule_cache_as_json()
prev_end_time_to_watch_for = None
if pseudo_channel.USE_OVERRIDE_CACHE and isforupdate:
for cached_item in pseudo_cache:
prev_start_time = datetime.datetime.strptime(cached_item[8], pseudo_channel.APP_TIME_FORMAT_STR)
try:
prev_end_time = datetime.datetime.strptime(cached_item[9], '%Y-%m-%d %H:%M:%S.%f')
except ValueError:
prev_end_time = datetime.datetime.strptime(cached_item[9], '%Y-%m-%d %H:%M:%S')
"""If update time is in between the prev media start / stop then there is overlap"""
if prev_start_time < now and prev_end_time > now:
try:
print("INFO: It looks like there is update schedule overlap", cached_item[3])
except:
pass
prev_end_time_to_watch_for = prev_end_time
for item in schedulelist:
try:
trans_time = datetime.datetime.strptime(item[8], pseudo_channel.APP_TIME_FORMAT_STR).strftime("%H:%M:%S")
except Exception as e:
print("ERROR: " + str(e))
trans_time = datetime.datetime.strptime(item[8], pseudo_channel.APP_TIME_FORMAT_STR).strftime("%H:%M")
new_start_time = datetime.datetime.strptime(item[8], pseudo_channel.APP_TIME_FORMAT_STR)
if prev_end_time_to_watch_for == None:
schedule.every().day.at(trans_time).do(job_that_executes_once, item, schedulelist).tag('daily-tasks')
else:
"""If prev end time is more then the start time of this media, skip it"""
if prev_end_time_to_watch_for > new_start_time:
try:
print("NOTICE: Skipping scheduling item due to cached overlap.", item[3])
except:
pass
continue
else:
schedule.every().day.at(trans_time).do(job_that_executes_once, item, schedulelist).tag('daily-tasks')
print("NOTICE: Done.")
generate_memory_schedule(pseudo_channel.db.get_daily_schedule())
daily_update_time = datetime.datetime.strptime(
pseudo_channel.translate_time(
pseudo_channel.DAILY_UPDATE_TIME
),
pseudo_channel.APP_TIME_FORMAT_STR
).strftime('%H:%M')
def go_generate_daily_sched():
"""Saving current daily schedule as cached .json"""
pseudo_channel.save_daily_schedule_as_json()
schedule.clear('daily-tasks')
sleep(1)
try:
pseudo_channel.generate_daily_schedule()
except:
print("ERROR: Recieved error when running generate_daily_schedule()")
generate_memory_schedule(pseudo_channel.db.get_daily_schedule(), True)
"""Commenting out below and leaving all updates to be handled by cron task"""
"""schedule.every().day.at(daily_update_time).do(
go_generate_daily_sched
).tag('daily-update')"""
sleep_before_triggering_play_now = 0.1
'''When the process is killed, stop any currently playing media & cleanup'''
signal.signal(signal.SIGTERM, pseudo_channel.signal_term_handler)
try:
while True:
schedule.run_pending()
sleep(0.1)
if sleep_before_triggering_play_now:
logging.info("NOTICE: Successfully started PseudoChannel.py")
trigger_what_should_be_playing_now()
sleep_before_triggering_play_now = 0
#generate_memory_schedule(pseudo_channel.db.get_daily_schedule())
except KeyboardInterrupt:
print('ALERT: Manual break by user!')