Python3 and installer updates

Updated installer to include web interface installation and additional client setup
Updated output text to work with web interface
This commit is contained in:
Moe Fwacky
2021-03-24 23:15:58 -07:00
committed by GitHub
parent 1a6b66a8eb
commit aaf6e8e735
7 changed files with 225 additions and 81 deletions

View File

@@ -632,20 +632,22 @@ class PseudoChannel():
def generate_daily_schedule(self):
print("#### Generating Daily Schedule")
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:
self.commercials = PseudoChannelCommercial(
print("NOTICE: Getting Commercials List from Database")
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"],
@@ -686,7 +688,7 @@ class PseudoChannel():
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" and entry[13] != "":
print("NOTICE: XTRA ARGS FOUND")
print("NOTICE: TV SHOW WITH XTRA ARGS FOUND")
shows = self.PLEX.library.section(theSection.title)
xtra = '[]'
d = {}
@@ -699,7 +701,7 @@ class PseudoChannel():
xtra = xtra.split(';')
try:
for thestr in xtra:
print("ARGUMENT = "+thestr)
print("INFO: ARGUMENT = "+thestr)
strsplit = thestr.split(':')
if strsplit[0] == "decade":
decade = strsplit[1]
@@ -710,7 +712,7 @@ class PseudoChannel():
lastdigit = lastdigit + 1
if lastdigit < 10:
thestr = thestr+","
print("ARGUMENT = "+thestr)
print("INFO: ARGUMENT = "+thestr)
#d.update(strsplit[0],strsplit[1])
elif strsplit[0] == "season":
xtraSeason = strsplit[1]
@@ -912,7 +914,7 @@ class PseudoChannel():
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("xtra args: ", entry[13])
print("INFO: Movie Xtra Arguments: ", entry[13])
movies = self.PLEX.library.section(theSection.title)
xtra = []
d = {}
@@ -949,7 +951,7 @@ class PseudoChannel():
"""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")
print("ERROR: xtra args not found, getting random movie")
the_movie = self.db.get_random_movie_duration(int(min), int(max))
movie_duration = the_movie[4]
attempt = 1
@@ -1000,7 +1002,7 @@ class PseudoChannel():
)
self.MEDIA.append(movie)
else:
print(str("Cannot find Movie, {} in the local db".format(entry[3])).encode('UTF-8'))
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:
@@ -1019,7 +1021,7 @@ class PseudoChannel():
)
self.MEDIA.append(music)
else:
print(str("Cannot find Music, {} in the local db".format(entry[3])).encode('UTF-8'))
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:
@@ -1038,14 +1040,14 @@ class PseudoChannel():
)
self.MEDIA.append(video)
else:
print(str("Cannot find Video, {} in the local db".format(entry[3])).encode('UTF-8'))
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, recreating daily_schedule")
print("INFO: Finished processing time entries, generating daily_schedule")
previous_episode = None
for entry in self.MEDIA:
if previous_episode != None:
@@ -1078,24 +1080,24 @@ class PseudoChannel():
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("Entry Duration = {}".format(str(entry.duration)))
print("Start Time Difference = {}".format(str(start_time_difference)))
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("Running Duration = {}".format(str(running_duration)))
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("New Start Time = {}".format(str(entry.start_time)))
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
)
print("End Time = {}".format(str(entry.end_time)))
print("INFO: End Time = {}".format(str(entry.end_time)))
overlap_max_seconds=int(entry.overlap_max) * 60
print(("Overlap Max is "+str(overlap_max_seconds)))
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("NOTICE: START TIME PAST MAXIMUM ALLOWED TIME, SKIPPING ENTRY")
print("ALERT: START TIME PAST MAXIMUM ALLOWED TIME, SKIPPING ENTRY")
pass
else:
"""Get List of Commercials to Inject"""
@@ -1630,7 +1632,7 @@ if __name__ == '__main__':
"""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 do to cached overlap.", item[3])
print("NOTICE: Skipping scheduling item due to cached overlap.", item[3])
except:
pass
continue

View File

@@ -9,7 +9,7 @@ from src import Commercial
class PseudoChannelCommercial():
MIN_DURATION_FOR_COMMERCIAL = 10 #seconds
MIN_DURATION_FOR_COMMERCIAL = 1 #seconds
COMMERCIAL_PADDING_IN_SECONDS = 0
daily_schedule = []
@@ -30,6 +30,8 @@ class PseudoChannelCommercial():
# random_commercial_dur_seconds = (int(random_commercial[4])/1000)%60
return random_commercial
def timedelta_milliseconds(self, td):
return td.days*86400000 + td.seconds*1000 + td.microseconds/1000
@@ -75,13 +77,9 @@ class PseudoChannelCommercial():
curr_item_start_time = curr_item_start_time.replace(day=2)
print("##############################################")
print("get_commercials_to_place_between_media DEBUG")
print("NOW: %s" % now)
print("prev_item_end_time: %s" % prev_item_end_time.replace(microsecond=0))
print("curr_item_start_time: %s" % curr_item_start_time)
print("time_diff: %s" % time_diff)
print("##############################################")
print("INFO: Last Item End Time - %s" % prev_item_end_time.replace(microsecond=0))
print("INFO: Next Item Start Time - %s" % curr_item_start_time)
print("INFO: Time to Fill - %s" % time_diff)
count = 0
commercial_list = []

View File

@@ -292,8 +292,6 @@ class PseudoChannelDatabase():
customSectionName
):
print("INFO: sectionType "+str(sectionType))
print("INFO: customSectionName"+str(customSectionName))
unix = int(time.time())
try:
self.cursor.execute("INSERT OR REPLACE INTO daily_schedule "
@@ -325,11 +323,10 @@ class PseudoChannelDatabase():
def add_media_to_daily_schedule(self, media):
try:
print(str("NOTICE: Adding media to db: {} {}".format(media.title, media.start_time)).encode('UTF-8'))
print(str("{}: {} - {}".format(media.start_time, media.title, media.custom_section_name)).encode('UTF-8'))
except:
print("ERROR: Not outputting media info due to ascii code issues.")
print("INFO: media.custom_section_name", media.custom_section_name)
self.add_daily_schedule_to_db(
0,
media.title,
@@ -525,6 +522,11 @@ class PseudoChannelDatabase():
datalist = list(self.cursor.fetchall())
return datalist
def get_random_commercial_duration(self,min,max):
sql = "SELECT * FROM commercials WHERE (duration BETWEEN ? and ?) ORDER BY RANDOM() LIMIT 1"
self.cursor.execute(sql, (min, max, ))
return self.cursor.fetchone()
def get_movies(self):
self.cursor.execute("SELECT * FROM movies ORDER BY date(lastPlayedDate) ASC")

View File

@@ -0,0 +1,25 @@
#!/usr/bin/env python
import os
import subprocess
channelsDir=os.path.abspath(os.path.dirname(__file__))
#get list of available channels and arrange in numerical order
dirList = sorted(next(os.walk(channelsDir))[1])
chanList = []
channelsList = []
for dir in dirList:
if "pseudo-channel_" in dir:
chanList.append(dir)
for chan in chanList:
channelNumber = chan.split('_')
channelNumber = channelNumber[1]
channelsList.append(channelNumber)
#execute PseudoChannel.py -g in specified channel
os.chdir(os.path.abspath(os.path.dirname(__file__)))
for channel in channelsList:
os.chdir(os.path.abspath(os.path.dirname(__file__))+'/pseudo-channel_'+channel)
print("GENERATING SCHEDULE FOR CHANNEL "+channel)
process = subprocess.call(["python", "-u", "PseudoChannel.py", "-g"], stdout=None, stderr=None, stdin=None)
os.chdir('../')
print("ALERT: ALL DAILY SCHEDULE GENERATION COMPLETE")

View File

@@ -45,6 +45,7 @@ update_call = "python PseudoChannel.py %s" % update_flags
# Step ONE: Global database update
os.chdir(os.path.abspath(os.path.dirname(__file__)))
print("ACTION: Doing global update from PLEX: %s" % update_flags)
try:
os.rename("pseudo-channel.db", "pseudo-channel.bak")

View File

@@ -12,6 +12,7 @@ OUTPUT_PID_FILE='running.pid'
OUTPUT_PID_PATH='.'
OUTPUT_LAST_FILE='last.info'
def execfile(filename, globals=None, locals=None):
if globals is None:
globals = sys._getframe(1).f_globals
@@ -36,7 +37,7 @@ def get_channels(channelsDir=os.path.abspath(os.path.dirname(__file__))):
def get_playing():
#check for pid file, if present, identify which channel is running
pids = "**/"+OUTPUT_PID_FILE
pids = os.path.abspath(os.path.dirname(__file__))+"/**/"+OUTPUT_PID_FILE
for runningPID in glob.glob(pids):
with open(runningPID) as f:
pid = f.readline()
@@ -45,7 +46,9 @@ def get_playing():
def get_last():
#check for last file, if present identify which channel is 'last'
lastFile = '**/'+OUTPUT_LAST_FILE
lastFile = os.path.abspath(os.path.dirname(__file__))+'/**/'+OUTPUT_LAST_FILE
print(lastFile)
print(glob.glob(lastFile))
for lasts in glob.glob(lastFile):
pathtofile = lasts.split('/')
lastDir = pathtofile[-2]
@@ -53,32 +56,45 @@ def get_last():
return last[1]
def start_channel(channel):
#execute PseudoChannel.py -r in specified channel\
os.chdir('./pseudo-channel_'+channel)
process = subprocess.Popen(["python", "-u", "PseudoChannel.py", "-r"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
#execute PseudoChannel.py -r in specified channel
last = get_last()
try:
os.remove(os.path.abspath(os.path.dirname(__file__))+'/pseudo-channel_'+last+"/last.info")
print("NOTICE: Previous last.info deleted")
except:
print("NOTICE: last.info not found")
os.chdir(os.path.abspath(os.path.dirname(__file__))+'/pseudo-channel_'+channel)
process = subprocess.Popen(["python", "-u", "PseudoChannel.py", "-r"], stdout=None, stderr=None, stdin=None)
#create pid file and write pid into file
print("NOTICE: Channel Process Running at "+str(process.pid))
p = open(OUTPUT_PID_FILE, 'w+')
p.write(str(process.pid))
p.close()
while True:
output = process.stdout.readline()
'''while True:
#output = process.stdout.readline()
if process.poll() is not None:
break
if output:
print(output.strip())
print(output.strip())'''
rc = process.poll()
def stop_channel(channel, pid):
#kill pid process
'''ps_dir = channel.replace('running.pid','')
script = os.path.abspath(os.path.dirname(__file__))+'/'+ps_dir+'PseudoChannel.py'
print(subprocess.Popen.poll(subprocess.Popen(['python',script])))
subprocess.Popen.terminate(subprocess.Popen(['python',script]))'''
try:
os.kill(int(pid), signal.SIGTERM)
print(pid+" PID TERMINATED")
except:
print("PID "+pid+" NOT FOUND")
#delete pid file
os.remove(channel)
print(OUTPUT_PID_FILE+" DELETED")
#write last.info file
lastFile = channel.replace(OUTPUT_PID_FILE, OUTPUT_LAST_FILE)
i = open('./'+lastFile, 'w')
i = open(lastFile, 'w')
i.write(str(time.time()))
i.close()
print(OUTPUT_LAST_FILE+" CREATED")
@@ -96,6 +112,7 @@ def channel_up(channelsList):
for channelPlaying, pid in getPlaying.items():
channelNumber = channelPlaying.replace('pseudo-channel_','')
channelNumber = channelNumber.replace('/'+OUTPUT_PID_FILE,'')
channelNumber = channelNumber.split('/')[-1]
print("NOTICE: Stopping Channel "+str(channelNumber)+" at PID "+str(pid))
stop_channel(channelPlaying, pid)
except:
@@ -106,6 +123,7 @@ def channel_up(channelsList):
for channel in channelsList:
if isnext == 1:
next_channel = channel
break
if channel == channelNumber:
isnext = 1
print("NOTICE: Starting Channel "+str(next_channel))
@@ -118,6 +136,7 @@ def channel_down(channelsList):
for channelPlaying, pid in getPlaying.items():
channelNumber = channelPlaying.replace('pseudo-channel_','')
channelNumber = channelNumber.replace('/'+OUTPUT_PID_FILE,'')
channelNumber = channelNumber.split('/')[-1]
print("NOTICE: Stopping Channel "+str(channelNumber)+" at PID "+str(pid))
stop_channel(channelPlaying, pid)
except:
@@ -129,6 +148,7 @@ def channel_down(channelsList):
for channel in channelsList:
if isnext == 1:
next_channel = channel
break
if channel == channelNumber:
isnext = 1
print("NOTICE: Starting Channel "+str(next_channel))
@@ -136,30 +156,23 @@ def channel_down(channelsList):
def generate_daily_schedules(channelsList):
#execute PseudoChannel.py -g in specified channel
print("GENERATING DAILY SCHEDULES FOR ALL CHANNELS")
os.chdir(os.path.abspath(os.path.dirname(__file__)))
for channel in channelsList:
process = subprocess.Popen(["python", "-u", "Global_DailySchedule.py"], stdout=None, stderr=None, stdin=None)
'''for channel in channelsList:
os.chdir(os.path.abspath(os.path.dirname(__file__))+'/pseudo-channel_'+channel)
print("GENERATING SCHEDULE FOR CHANNEL "+channel)
process = subprocess.Popen(["python", "-u", "PseudoChannel.py", "-g"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
while True:
output = process.stdout.readline()
if process.poll() is not None:
break
if output:
print(output.strip())
rc = process.poll()
process = subprocess.call(["python", "-u", "PseudoChannel.py", "-g"], stdout=None, stderr=None, stdin=None)
os.chdir('../')
print("ALERT: ALL DAILY SCHEDULE GENERATION COMPLETE")'''
def global_database_update():
import Global_DatabaseUpdate
'''process = subprocess.Popen(["python", "-u", "Global_DatabaseUpdate.py"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
while True:
output = process.stdout.readline()
if process.poll() is not None:
break
if output:
print(output.strip())
rc = process.poll()'''
print("UPDATING PSEUDO CHANNEL DATABASE FROM PLEX SERVER")
#import Global_DatabaseUpdate
workingDir = os.path.abspath(os.path.dirname(__file__))
os.chdir(workingDir)
print("NOTICE: Working directory changed to "+workingDir)
process = subprocess.Popen(["python", "-u", "Global_DatabaseUpdate.py"], stdout=None, stderr=None, stdin=None)
parser = argparse.ArgumentParser(description='Pseudo Channel Controls')
channelsList = get_channels()
@@ -200,8 +213,8 @@ if args.channel:
if args.stop:
playing = get_playing()
for channel, pid in playing.items():
print("STOPPING CHANNEL "+channel.replace('/running.pid','').split('_')[1])
stop_channel(channel, pid)
print("STOPPING ACTIVE CHANNEL AT PID# "+pid)
if args.stopallboxes:
print("STOPPING ALL BOXES")
stop_all_boxes()
@@ -227,8 +240,8 @@ if args.generateschedules:
try:
playing = get_playing()
for channel, pid in playing.items():
print("STOPPING CHANNEL "+channel.replace('/running.pid','').split('_')[1])
stop_channel(channel, pid)
print("STOPPING ACTIVE CHANNEL AT PID "+pid)
last = get_last()
print("GENERATING DAILY SCHEDULES")
generate_daily_schedules(channelsList)

129
setup.py
View File

@@ -8,6 +8,7 @@ import argparse
import subprocess
import signal
import shutil
import socket
from git import RemoteProgress
from datetime import datetime
from plexapi.server import PlexServer
@@ -42,6 +43,17 @@ def get_channels(channelsDir='.'):
do = "nothing"
return channelsList
def get_ip():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.connect(('10.255.255.255', 1))
IP = s.getsockname()[0]
except Exception:
IP = '127.0.0.1'
finally:
s.close()
return IP
def generate_daily_schedules(channelsList):
#execute PseudoChannel.py -g in specified channel
for channel in channelsList:
@@ -250,13 +262,11 @@ def ps_install():
dailyUpdateTime = dailyUpdateHour+':00'
#set up daily cron for schedule generation
cron = CronTab(user=True)
c = 0
for job in cron:
if job.comment == "Pseudo Channel Daily Schedule Generator":
c = 1
job.hour.on(dailyUpdateHour)
job.minute.on(0)
if c == 0:
print("NOTICE: Removing existing cron job")
cron.remove(job)
print("ACTION: Creating cron job for Daily Schedule Generator")
cronJob = cron.new(command = sys.executable+" "+os.getcwd()+"/controls.py -g", comment="Pseudo Channel Daily Schedule Generator")
cronJob.hour.on(dailyUpdateHour)
cronJob.minute.on(0)
@@ -287,6 +297,8 @@ def ps_install():
shutil.rmtree('../src')
os.remove('../pseudo_config.py')
os.remove('../plex_token.py')
web_setup()
copy_tv(clientList, clientNumbers, os.getcwd())
def global_database_update(path):
os.chdir(path)
@@ -346,19 +358,110 @@ def copyconfig(channel="all"):
chanDir = "pseudo-channel_"+str(chan)+'/'
shutil.copy('./pseudo_config.py', chanDir)
def copy_tv(client=None):
print("copy_tv") #make symlinked copy of pseudo channel files to run on another client
def copy_tv(clientList, clientNumbers, path):
print("Adding Additional Pseudo Channel Clients") #make symlinked copy of pseudo channel files to run on another client
print("SELECT DESIRED CLIENT")
for i, client in enumerate(PLEX.clients()):
print(str(i + 1)+":", client.title)
clientList.append(client.title)
clientNumbers.append(i + 1)
selectedClient = input('>:')
while int(selectedClient) not in clientNumbers:
print("ERROR: INPUT OUTSIDE OF RANGE")
selectedClient = input('>:')
ps_client = clientList[int(selectedClient)-1]
ps_client = ps_client.replace(" ","\ ")
if path[-1] == '/':
path[-1] = path[-1].replace('/','')
newChannelsDir = path+'_'+ps_client
print("Copying Files to "+newChannelsDir)
#copy all files and directories to a _CLIENT directory
files = glob.glob(path+'/*')
for file in files: #copy files into new client directory
if "pseudo-channel.db" in file: #symlink the database files
filePathList = file.split('/')
if "pseudo-channel_" in filePathList[-2]:
symLinkPath = newChannelsDir+'/'+filePathList[-2]+'/'+filePathList[-1]
else:
symLinkPath = newChannelsDir+'/'+filePathList[-1]
print("Creating symlink to database file")
print(file+" --> "+symLinkPath)
os.symlink(file,symLinkPath)
else:
shutil.copy(file, newChannelsDir)
def ps_update(branch='main'):
print("ps_update") #download and copy updates from git to all branches and boxes
def web_setup(branch='main'):
print("web_setup") #set up the web interface and api
#copy files from web interface git to ./channels/web
def web_setup():
print("Setting up the web interface and API...") #set up the web interface and api
#copy files from web interface git
branchList = ['master','develop']
b = 1
print("Select Web Interface Repository Branch (default: master)")
for branch in branchList:
print(str(b)+": "+branch)
b = b+1
branchSelect = input('>: ')
if branchSelect == "":
web_branch = 'master'
else:
try:
branchSelect = int(branchSelect)
while 0 > int(branchSelect) > b-1:
print("INVALID ENTRY")
branchSelect = input('>: ')
web_branch = branchList[branchSelect-1]
except:
while branchSelect not in branchList:
print("INVALID ENTRY")
branchSelect = input('>: ')
web_branch = branchSelect
print("Is a web server (apache, nginx, etc) running on this device? (Y/N)")
web_server = input('Y/N >: ')
responses = ['yes','y','n','no']
while web_server.lower() not in responses:
print("INVALID ENTRY")
web_server = input('Y/N >: ')
if 'y' in web_server.lower():
print("Enter Install Path (default: /var/www/html)")
pathInput = input('>: ')
if pathInput == '':
path = "/var/www/html"
else:
path = pathInput
else:
print("Enter port number for web interface (default: 8080)")
portNumber = input(">: ")
if portNumber == "":
portNumber = "8080"
while portNumber.isnumeric() == False or portNumber == "80":
print("INVALID ENTRY")
portNumber = input(">: ")
path = os.path.abspath(os.path.dirname(__file__))+'/web'
os.mkdir(path)
local_ip = get_ip()
cron = CronTab(user=True)
for job in cron:
if job.comment == "PHP Server":
print("NOTICE: Removing existing cron job")
cron.remove(job)
print("ACTION: Adding cron job to run PHP Server on Boot")
job = cron.new(command = "/usr/bin/php -S "+local_ip+":"+portNumber+" -t "+path+" &", comment="PHP Server")
job.every_reboot()
cron.write()
try:
print("Copying files to "+path)
git.Repo.clone_from('https://github.com/FakeTV/Web-Interface-for-Pseudo-Channel', path, branch=web_branch)
except Exception as e:
print("ERROR GETTING DOWNLOADING FROM GIT")
print("e")
#insert config details
#ask if other web service exists, if so copy to appropriate folder and exit
#create script to run http.server and add to startup
#run http.server
configFile = open(path+"/psConfig.php", 'r')
configData = configFile.read()
configFile = open(path+"/psConfig.php", 'w')
configData = configData.replace("$pseudochannel = '/home/pi/channels/';", "$pseudochannel = '"+os.path.abspath(os.path.dirname(__file__))+"';")
job.run()
parser = argparse.ArgumentParser(description='Pseudo Channel Controls')
try: