mirror of
https://github.com/FakeTV/pseudo-channel.git
synced 2026-01-10 12:13:14 +00:00
Cleaning up code base, etc. getting ready for release.
This commit is contained in:
@@ -16,147 +16,86 @@ class PseudoChannelCommercial():
|
||||
def __init__(self, commercials, commercialPadding):
|
||||
|
||||
self.commercials = commercials
|
||||
|
||||
self.COMMERCIAL_PADDING_IN_SECONDS = commercialPadding
|
||||
|
||||
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 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):
|
||||
|
||||
#print last_ep.end_time, now_ep.start_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)
|
||||
|
||||
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
|
||||
|
||||
#print "here", time_diff.seconds
|
||||
|
||||
while curr_item_start_time > new_commercial_start_time and (count) < len(self.commercials)*100:
|
||||
|
||||
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_seconds = (int(random_commercial[4])/1000)%60
|
||||
|
||||
new_commercial_milli = int(random_commercial[4])
|
||||
|
||||
if last_commercial != None:
|
||||
|
||||
#print last_commercial[3]
|
||||
|
||||
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],
|
||||
@@ -169,15 +108,8 @@ class PseudoChannelCommercial():
|
||||
"0", # overlap_max
|
||||
"", # plex_media_id
|
||||
)
|
||||
|
||||
last_commercial = new_commercial
|
||||
|
||||
if new_commercial_end_time > curr_item_start_time:
|
||||
|
||||
break
|
||||
|
||||
commercial_list.append(new_commercial)
|
||||
|
||||
#print "here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
||||
|
||||
return commercial_list
|
||||
@@ -9,83 +9,61 @@ class PseudoChannelDatabase():
|
||||
def __init__(self, db):
|
||||
|
||||
self.db = db
|
||||
|
||||
self.conn = sqlite3.connect(self.db, check_same_thread=False)
|
||||
|
||||
self.cursor = self.conn.cursor()
|
||||
|
||||
"""Database functions.
|
||||
|
||||
Utilities, etc.
|
||||
"""
|
||||
|
||||
def create_tables(self):
|
||||
|
||||
self.cursor.execute('CREATE TABLE IF NOT EXISTS '
|
||||
'movies(id INTEGER PRIMARY KEY AUTOINCREMENT, '
|
||||
'unix INTEGER, mediaID INTEGER, title TEXT, duration INTEGER, '
|
||||
'lastPlayedDate TEXT, plexMediaID TEXT)')
|
||||
|
||||
self.cursor.execute('CREATE TABLE IF NOT EXISTS '
|
||||
'videos(id INTEGER PRIMARY KEY AUTOINCREMENT, '
|
||||
'unix INTEGER, mediaID INTEGER, title TEXT, duration INTEGER, plexMediaID TEXT)')
|
||||
|
||||
self.cursor.execute('CREATE TABLE IF NOT EXISTS '
|
||||
'music(id INTEGER PRIMARY KEY AUTOINCREMENT, '
|
||||
'unix INTEGER, mediaID INTEGER, title TEXT, duration INTEGER, plexMediaID TEXT)')
|
||||
|
||||
self.cursor.execute('CREATE TABLE IF NOT EXISTS '
|
||||
'shows(id INTEGER PRIMARY KEY AUTOINCREMENT, '
|
||||
'unix INTEGER, mediaID INTEGER, title TEXT, duration INTEGER, '
|
||||
'lastEpisodeTitle TEXT, fullImageURL TEXT, plexMediaID TEXT)')
|
||||
|
||||
self.cursor.execute('CREATE TABLE IF NOT EXISTS '
|
||||
'episodes(id INTEGER PRIMARY KEY AUTOINCREMENT, '
|
||||
'unix INTEGER, mediaID INTEGER, title TEXT, duration INTEGER, '
|
||||
'episodeNumber INTEGER, seasonNumber INTEGER, showTitle TEXT, plexMediaID TEXT)')
|
||||
|
||||
self.cursor.execute('CREATE TABLE IF NOT EXISTS '
|
||||
'commercials(id INTEGER PRIMARY KEY AUTOINCREMENT, unix INTEGER, '
|
||||
'mediaID INTEGER, title TEXT, duration INTEGER, plexMediaID TEXT)')
|
||||
|
||||
self.cursor.execute('CREATE TABLE IF NOT EXISTS '
|
||||
'schedule(id INTEGER PRIMARY KEY AUTOINCREMENT, unix INTEGER, '
|
||||
'mediaID INTEGER, title TEXT, duration INTEGER, startTime INTEGER, '
|
||||
'endTime INTEGER, dayOfWeek TEXT, startTimeUnix INTEGER, section TEXT, '
|
||||
'strictTime TEXT, timeShift TEXT, overlapMax TEXT, xtra TEXT)')
|
||||
|
||||
self.cursor.execute('CREATE TABLE IF NOT EXISTS '
|
||||
'daily_schedule(id INTEGER PRIMARY KEY AUTOINCREMENT, unix INTEGER, '
|
||||
'mediaID INTEGER, title TEXT, episodeNumber INTEGER, seasonNumber INTEGER, '
|
||||
'showTitle TEXT, duration INTEGER, startTime INTEGER, endTime INTEGER, '
|
||||
'dayOfWeek TEXT, sectionType TEXT, plexMediaID TEXT)')
|
||||
|
||||
self.cursor.execute('CREATE TABLE IF NOT EXISTS '
|
||||
'app_settings(id INTEGER PRIMARY KEY AUTOINCREMENT, version TEXT)')
|
||||
|
||||
#index
|
||||
self.cursor.execute('CREATE UNIQUE INDEX IF NOT EXISTS idx_episode_title ON episodes (title);')
|
||||
|
||||
self.cursor.execute('CREATE UNIQUE INDEX IF NOT EXISTS idx_movie_title ON movies (title);')
|
||||
|
||||
self.cursor.execute('CREATE UNIQUE INDEX IF NOT EXISTS idx_shows_title ON shows (title);')
|
||||
|
||||
self.cursor.execute('CREATE UNIQUE INDEX IF NOT EXISTS idx_video_title ON videos (title);')
|
||||
|
||||
self.cursor.execute('CREATE UNIQUE INDEX IF NOT EXISTS idx_music_title ON music (title);')
|
||||
|
||||
self.cursor.execute('CREATE UNIQUE INDEX IF NOT EXISTS idx_commercial_title ON commercials (title);')
|
||||
|
||||
self.cursor.execute('CREATE UNIQUE INDEX IF NOT EXISTS idx_settings_version ON app_settings (version);')
|
||||
|
||||
"""Setting Basic Settings
|
||||
|
||||
"""
|
||||
try:
|
||||
self.cursor.execute("INSERT OR REPLACE INTO app_settings "
|
||||
"(version) VALUES (?)",
|
||||
("0.1",))
|
||||
|
||||
self.conn.commit()
|
||||
# Catch the exception
|
||||
except Exception as e:
|
||||
@@ -104,9 +82,7 @@ class PseudoChannelDatabase():
|
||||
def drop_daily_schedule_table(self):
|
||||
|
||||
sql = "DROP TABLE IF EXISTS daily_schedule"
|
||||
|
||||
self.cursor.execute(sql)
|
||||
|
||||
self.conn.commit()
|
||||
|
||||
def create_daily_schedule_table(self):
|
||||
@@ -116,45 +92,36 @@ class PseudoChannelDatabase():
|
||||
'mediaID INTEGER, title TEXT, episodeNumber INTEGER, seasonNumber INTEGER, '
|
||||
'showTitle TEXT, duration INTEGER, startTime INTEGER, endTime INTEGER, '
|
||||
'dayOfWeek TEXT, sectionType TEXT, plexMediaID TEXT)')
|
||||
|
||||
self.conn.commit()
|
||||
|
||||
def remove_all_scheduled_items(self):
|
||||
|
||||
sql = "DELETE FROM schedule WHERE id > -1"
|
||||
|
||||
self.cursor.execute(sql)
|
||||
|
||||
self.conn.commit()
|
||||
|
||||
def remove_all_daily_scheduled_items(self):
|
||||
|
||||
sql = "DELETE FROM daily_schedule"
|
||||
|
||||
self.cursor.execute(sql)
|
||||
|
||||
self.conn.commit()
|
||||
|
||||
def clear_shows_table(self):
|
||||
|
||||
sql = "DELETE FROM shows"
|
||||
|
||||
self.cursor.execute(sql)
|
||||
|
||||
self.conn.commit()
|
||||
|
||||
"""Database functions.
|
||||
|
||||
Setters, etc.
|
||||
"""
|
||||
|
||||
def add_movies_to_db(self, mediaID, title, duration, plexMediaID):
|
||||
|
||||
unix = int(time.time())
|
||||
try:
|
||||
self.cursor.execute("REPLACE INTO movies "
|
||||
"(unix, mediaID, title, duration, plexMediaID) VALUES (?, ?, ?, ?, ?)",
|
||||
(unix, mediaID, title, duration, plexMediaID))
|
||||
|
||||
self.conn.commit()
|
||||
# Catch the exception
|
||||
except Exception as e:
|
||||
@@ -163,6 +130,7 @@ class PseudoChannelDatabase():
|
||||
raise e
|
||||
|
||||
def add_videos_to_db(self, mediaID, title, duration, plexMediaID):
|
||||
|
||||
unix = int(time.time())
|
||||
try:
|
||||
self.cursor.execute("REPLACE INTO videos "
|
||||
@@ -177,6 +145,7 @@ class PseudoChannelDatabase():
|
||||
raise e
|
||||
|
||||
def add_shows_to_db(self, mediaID, title, duration, lastEpisodeTitle, fullImageURL, plexMediaID):
|
||||
|
||||
unix = int(time.time())
|
||||
try:
|
||||
self.cursor.execute("INSERT OR IGNORE INTO shows "
|
||||
@@ -190,6 +159,7 @@ class PseudoChannelDatabase():
|
||||
raise e
|
||||
|
||||
def add_episodes_to_db(self, mediaID, title, duration, episodeNumber, seasonNumber, showTitle, plexMediaID):
|
||||
|
||||
unix = int(time.time())
|
||||
try:
|
||||
self.cursor.execute("REPLACE INTO episodes "
|
||||
@@ -203,6 +173,7 @@ class PseudoChannelDatabase():
|
||||
raise e
|
||||
|
||||
def add_commercials_to_db(self, mediaID, title, duration, plexMediaID):
|
||||
|
||||
unix = int(time.time())
|
||||
try:
|
||||
self.cursor.execute("REPLACE INTO commercials "
|
||||
@@ -258,9 +229,7 @@ class PseudoChannelDatabase():
|
||||
):
|
||||
|
||||
unix = int(time.time())
|
||||
|
||||
try:
|
||||
|
||||
self.cursor.execute("INSERT OR REPLACE INTO daily_schedule "
|
||||
"(unix, mediaID, title, episodeNumber, seasonNumber, "
|
||||
"showTitle, duration, startTime, endTime, dayOfWeek, sectionType, plexMediaID) "
|
||||
@@ -279,16 +248,11 @@ class PseudoChannelDatabase():
|
||||
sectionType,
|
||||
plexMediaID
|
||||
))
|
||||
|
||||
self.conn.commit()
|
||||
|
||||
# Catch the exception
|
||||
except Exception as e:
|
||||
|
||||
# Roll back any change if something goes wrong
|
||||
|
||||
self.conn.rollback()
|
||||
|
||||
raise e
|
||||
|
||||
def add_media_to_daily_schedule(self, media):
|
||||
@@ -297,7 +261,6 @@ class PseudoChannelDatabase():
|
||||
print str("#### Adding media to db: {} {}".format(media.title, media.start_time)).encode('UTF-8')
|
||||
except:
|
||||
print "----- Not outputting media info due to ascii code issues."
|
||||
|
||||
self.add_daily_schedule_to_db(
|
||||
0,
|
||||
media.title,
|
||||
@@ -313,6 +276,7 @@ class PseudoChannelDatabase():
|
||||
)
|
||||
|
||||
def import_shows_table_by_row(self, mediaID, title, duration, lastEpisodeTitle, fullImageURL, plexMediaID):
|
||||
|
||||
unix = int(time.time())
|
||||
try:
|
||||
self.cursor.execute("REPLACE INTO shows "
|
||||
@@ -326,102 +290,79 @@ class PseudoChannelDatabase():
|
||||
raise e
|
||||
|
||||
"""Database functions.
|
||||
|
||||
Getters, etc.
|
||||
"""
|
||||
def get_shows_table(self):
|
||||
|
||||
sql = "SELECT * FROM shows"
|
||||
|
||||
self.cursor.execute(sql)
|
||||
|
||||
return self.cursor.fetchall()
|
||||
|
||||
def get_media(self, title, mediaType):
|
||||
|
||||
media = mediaType
|
||||
|
||||
sql = "SELECT * FROM "+media+" WHERE (title LIKE ?) COLLATE NOCASE"
|
||||
self.cursor.execute(sql, ("%"+title+"%", ))
|
||||
media_item = self.cursor.fetchone()
|
||||
|
||||
return media_item
|
||||
|
||||
def get_schedule(self):
|
||||
|
||||
self.cursor.execute("SELECT * FROM schedule ORDER BY datetime(startTimeUnix) ASC")
|
||||
|
||||
datalist = list(self.cursor.fetchall())
|
||||
|
||||
return datalist
|
||||
|
||||
def get_daily_schedule(self):
|
||||
|
||||
print "##### Getting Daily Schedule from DB."
|
||||
|
||||
self.cursor.execute("SELECT * FROM daily_schedule ORDER BY datetime(startTime) ASC")
|
||||
|
||||
datalist = list(self.cursor.fetchall())
|
||||
|
||||
print "+++++ Done."
|
||||
|
||||
return datalist
|
||||
|
||||
def get_movie(self, title):
|
||||
|
||||
media = "movies"
|
||||
|
||||
return self.get_media(title, media)
|
||||
|
||||
def get_shows(self, title):
|
||||
|
||||
media = "shows"
|
||||
|
||||
return self.get_media(title, media)
|
||||
|
||||
def get_music(self, title):
|
||||
|
||||
media = "music"
|
||||
|
||||
return self.get_media(title, media)
|
||||
|
||||
def get_video(self, title):
|
||||
|
||||
media = "videos"
|
||||
|
||||
return self.get_media(title, media)
|
||||
|
||||
def get_episodes(self, title):
|
||||
|
||||
media = "episodes"
|
||||
|
||||
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"
|
||||
|
||||
self.cursor.execute(sql1, (lastEpisodeTitle, showTitle, ))
|
||||
|
||||
self.conn.commit()
|
||||
|
||||
def get_first_episode(self, tvshow):
|
||||
|
||||
sql = ("SELECT id, unix, mediaID, title, duration, MIN(episodeNumber), MIN(seasonNumber), "
|
||||
"showTitle FROM episodes WHERE ( showTitle LIKE ?) COLLATE NOCASE")
|
||||
|
||||
self.cursor.execute(sql, (tvshow, ))
|
||||
|
||||
first_episode = self.cursor.fetchone()
|
||||
|
||||
return first_episode
|
||||
|
||||
'''
|
||||
@@ -432,32 +373,24 @@ class PseudoChannelDatabase():
|
||||
def get_episode_id(self, episodeTitle):
|
||||
|
||||
sql = "SELECT id FROM episodes WHERE ( title LIKE ?) COLLATE NOCASE"
|
||||
|
||||
self.cursor.execute(sql, (episodeTitle, ))
|
||||
|
||||
episode_id = self.cursor.fetchone()
|
||||
|
||||
return episode_id
|
||||
|
||||
def get_random_episode(self):
|
||||
|
||||
sql = "SELECT * FROM episodes WHERE id IN (SELECT id FROM episodes ORDER BY RANDOM() LIMIT 1)"
|
||||
|
||||
self.cursor.execute(sql)
|
||||
|
||||
return self.cursor.fetchone()
|
||||
|
||||
def get_random_movie(self):
|
||||
|
||||
sql = "SELECT * FROM movies WHERE id IN (SELECT id FROM movies ORDER BY RANDOM() LIMIT 1)"
|
||||
|
||||
self.cursor.execute(sql)
|
||||
|
||||
return self.cursor.fetchone()
|
||||
|
||||
def get_next_episode(self, series):
|
||||
|
||||
#print(series)
|
||||
'''
|
||||
*
|
||||
* As a way of storing a "queue", I am storing the *next episode title in the "shows" table so I can
|
||||
@@ -465,7 +398,6 @@ class PseudoChannelDatabase():
|
||||
*
|
||||
'''
|
||||
self.cursor.execute("SELECT lastEpisodeTitle FROM shows WHERE title LIKE ? COLLATE NOCASE", (series, ))
|
||||
|
||||
last_title_list = self.cursor.fetchone()
|
||||
'''
|
||||
*
|
||||
@@ -480,17 +412,13 @@ class PseudoChannelDatabase():
|
||||
*
|
||||
'''
|
||||
first_episode = self.get_first_episode(series)
|
||||
|
||||
first_episode_title = first_episode[3]
|
||||
|
||||
#print(first_episode_title)
|
||||
'''
|
||||
*
|
||||
* Add this episdoe title to the "shows" table for the queue functionality to work
|
||||
*
|
||||
'''
|
||||
self.update_shows_table_with_last_episode(series, first_episode_title)
|
||||
|
||||
return first_episode
|
||||
|
||||
elif last_title_list:
|
||||
@@ -499,10 +427,6 @@ class PseudoChannelDatabase():
|
||||
* The last episode stored in the "shows" table was not empty... get the next episode in the series
|
||||
*
|
||||
'''
|
||||
#print("First episode already set in shows, advancing episodes forward")
|
||||
|
||||
#print(str(self.get_episode_id(last_title_list[0])))
|
||||
|
||||
"""
|
||||
*
|
||||
* If this isn't a first run, then grabbing the next episode by incrementing id
|
||||
@@ -510,7 +434,6 @@ class PseudoChannelDatabase():
|
||||
"""
|
||||
sql = ("SELECT * FROM episodes WHERE ( id > "+str(self.get_episode_id(last_title_list[0])[0])+
|
||||
" AND showTitle LIKE ? ) ORDER BY seasonNumber LIMIT 1 COLLATE NOCASE")
|
||||
|
||||
self.cursor.execute(sql, (series, ))
|
||||
'''
|
||||
*
|
||||
@@ -518,38 +441,23 @@ class PseudoChannelDatabase():
|
||||
*
|
||||
'''
|
||||
next_episode = self.cursor.fetchone()
|
||||
|
||||
if next_episode != None:
|
||||
|
||||
#print(next_episode[3])
|
||||
|
||||
self.update_shows_table_with_last_episode(series, next_episode[3])
|
||||
|
||||
return next_episode
|
||||
|
||||
else:
|
||||
|
||||
print("Not grabbing next episode restarting series, series must be over. Restarting from episode 1.")
|
||||
|
||||
print("+++++ Not grabbing next episode restarting series, series must be over. Restarting from episode 1.")
|
||||
first_episode = self.get_first_episode(series)
|
||||
|
||||
self.update_shows_table_with_last_episode(series, first_episode[3])
|
||||
|
||||
return first_episode
|
||||
|
||||
def get_commercial(self, title):
|
||||
|
||||
media = "commercials"
|
||||
|
||||
sql = "SELECT * FROM "+media+" WHERE (title LIKE ?) COLLATE NOCASE"
|
||||
self.cursor.execute(sql, (title, ))
|
||||
datalist = list(self.cursor.fetchone())
|
||||
if datalist > 0:
|
||||
print(datalist)
|
||||
|
||||
return datalist
|
||||
|
||||
else:
|
||||
|
||||
return None
|
||||
|
||||
return None
|
||||
@@ -1,18 +1,15 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from plexapi.server import PlexServer
|
||||
from datetime import datetime
|
||||
import sqlite3
|
||||
|
||||
import thread,SocketServer,SimpleHTTPServer
|
||||
|
||||
from yattag import Doc
|
||||
from yattag import indent
|
||||
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():
|
||||
|
||||
@@ -26,32 +23,19 @@ class PseudoDailyScheduleController():
|
||||
):
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
'''
|
||||
@@ -64,33 +48,22 @@ class PseudoDailyScheduleController():
|
||||
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):
|
||||
@@ -104,49 +77,34 @@ class PseudoDailyScheduleController():
|
||||
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('<?xml version="1.0" encoding="UTF-8"?>')
|
||||
|
||||
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'),
|
||||
@@ -154,11 +112,8 @@ class PseudoDailyScheduleController():
|
||||
('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'),
|
||||
@@ -166,11 +121,8 @@ class PseudoDailyScheduleController():
|
||||
('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'),
|
||||
@@ -178,12 +130,9 @@ class PseudoDailyScheduleController():
|
||||
('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.
|
||||
@@ -196,27 +145,18 @@ class PseudoDailyScheduleController():
|
||||
def get_html_from_daily_schedule(self, currentTime, bgImageURL, datalist):
|
||||
|
||||
now = datetime.now()
|
||||
|
||||
time = now.strftime("%B %d, %Y")
|
||||
|
||||
doc, tag, text, line = Doc(
|
||||
|
||||
).ttl()
|
||||
|
||||
doc.asis('<!DOCTYPE html>')
|
||||
|
||||
with tag('html'):
|
||||
|
||||
with tag('head'):
|
||||
|
||||
with tag('title'):
|
||||
|
||||
text(time + " - Daily Pseudo Schedule")
|
||||
|
||||
doc.asis('<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet">')
|
||||
doc.asis('<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet">')
|
||||
doc.asis('<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>')
|
||||
|
||||
doc.asis("""
|
||||
<script>
|
||||
$(function(){
|
||||
@@ -271,28 +211,17 @@ class PseudoDailyScheduleController():
|
||||
});
|
||||
</script>
|
||||
""")
|
||||
|
||||
if bgImageURL != None:
|
||||
doc.asis('<style>body{ background:transparent!important; } html { background: url('+bgImageURL+') no-repeat center center fixed; -webkit-background-size: cover;-moz-background-size: cover;-o-background-size: cover;background-size: cover;}.make-white { padding: 24px; background:rgba(255,255,255, 0.9); }</style>')
|
||||
|
||||
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', "Daily Pseudo Schedule", klass='col-12 pl-0')
|
||||
|
||||
with tag('div'):
|
||||
|
||||
line('h3', time, klass='col-12 pl-1')
|
||||
|
||||
with tag('table', klass='col-12 table table-bordered table-hover'):
|
||||
|
||||
with tag('thead', klass='table-info'):
|
||||
with tag('tr'):
|
||||
with tag('th'):
|
||||
@@ -305,23 +234,14 @@ class PseudoDailyScheduleController():
|
||||
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'):
|
||||
|
||||
timeB = datetime.strptime(row[8], '%I:%M:%S %p')
|
||||
|
||||
if currentTime == None:
|
||||
|
||||
with tag('tr'):
|
||||
with tag('th', scope='row'):
|
||||
text(numberIncrease)
|
||||
@@ -333,11 +253,8 @@ class PseudoDailyScheduleController():
|
||||
text(row[3])
|
||||
with tag('td'):
|
||||
text(row[8])
|
||||
|
||||
elif currentTime.hour == timeB.hour and currentTime.minute == timeB.minute:
|
||||
|
||||
with tag('tr', klass='bg-info'):
|
||||
|
||||
with tag('th', scope='row'):
|
||||
text(numberIncrease)
|
||||
with tag('td'):
|
||||
@@ -348,9 +265,7 @@ class PseudoDailyScheduleController():
|
||||
text(row[3])
|
||||
with tag('td'):
|
||||
text(row[8])
|
||||
|
||||
else:
|
||||
|
||||
with tag('tr'):
|
||||
with tag('th', scope='row'):
|
||||
text(numberIncrease)
|
||||
@@ -362,8 +277,6 @@ class PseudoDailyScheduleController():
|
||||
text(row[3])
|
||||
with tag('td'):
|
||||
text(row[8])
|
||||
|
||||
|
||||
return indent(doc.getvalue())
|
||||
|
||||
'''
|
||||
@@ -376,25 +289,15 @@ class PseudoDailyScheduleController():
|
||||
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()
|
||||
|
||||
'''
|
||||
@@ -407,26 +310,16 @@ class PseudoDailyScheduleController():
|
||||
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
|
||||
@@ -437,44 +330,27 @@ class PseudoDailyScheduleController():
|
||||
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")
|
||||
|
||||
#f.close()
|
||||
|
||||
'''
|
||||
*
|
||||
* Trigger "playMedia()" on the Python Plex API for specified media.
|
||||
@@ -486,61 +362,32 @@ class PseudoDailyScheduleController():
|
||||
'''
|
||||
def play_media(self, mediaType, mediaParentTitle, mediaTitle, offset):
|
||||
|
||||
|
||||
try:
|
||||
|
||||
if mediaType == "TV Shows":
|
||||
|
||||
mediaItems = self.PLEX.library.section(mediaType).get(mediaParentTitle).episodes()
|
||||
|
||||
for item in mediaItems:
|
||||
|
||||
# print(part.title)
|
||||
|
||||
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(mediaType).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(mediaType).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(mediaType))
|
||||
|
||||
print "+++++ Done."
|
||||
|
||||
except Exception as e:
|
||||
|
||||
print e.__doc__
|
||||
|
||||
print e.message
|
||||
|
||||
print "##### There was an error trying to play the media."
|
||||
|
||||
pass
|
||||
|
||||
'''
|
||||
@@ -554,49 +401,32 @@ class PseudoDailyScheduleController():
|
||||
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')
|
||||
|
||||
self.play_media(row[11], row[6], row[3], offset)
|
||||
|
||||
self.write_schedule_to_file(
|
||||
self.get_html_from_daily_schedule(
|
||||
timeB,
|
||||
@@ -607,9 +437,7 @@ class PseudoDailyScheduleController():
|
||||
datalist
|
||||
)
|
||||
)
|
||||
|
||||
self.write_refresh_bool_to_file()
|
||||
|
||||
"""Generate / write XML to file
|
||||
"""
|
||||
self.write_xml_to_file(
|
||||
@@ -622,15 +450,11 @@ class PseudoDailyScheduleController():
|
||||
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
|
||||
@@ -641,36 +465,21 @@ class PseudoDailyScheduleController():
|
||||
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])
|
||||
|
||||
self.write_schedule_to_file(
|
||||
self.get_html_from_daily_schedule(
|
||||
timeB,
|
||||
@@ -681,9 +490,7 @@ class PseudoDailyScheduleController():
|
||||
datalist
|
||||
)
|
||||
)
|
||||
|
||||
self.write_refresh_bool_to_file()
|
||||
|
||||
"""Generate / write XML to file
|
||||
"""
|
||||
self.write_xml_to_file(
|
||||
@@ -696,26 +503,18 @@ class PseudoDailyScheduleController():
|
||||
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 make_xml_schedule(self, datalist):
|
||||
|
||||
print "+++++ ", "Writing XML / HTML to file."
|
||||
|
||||
self.write_refresh_bool_to_file()
|
||||
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))
|
||||
Reference in New Issue
Block a user