2014-08-26 11:46:47 -07:00
#!/usr/bin/env python3
STREAM_STATUS_ACTIVE = 0
STREAM_STATUS_PAUSED = 1
STREAM_STATUS_ERROR = 2
import sys
import os
import os . path
import cherrypy
import json
import signal
from jinja2 import Environment , FileSystemLoader
from libs import database
from libs import recordTick
from datetime import datetime
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
if __name__ == ' __main__ ' or ' uwsgi ' in __name__ :
2020-02-06 18:47:34 -08:00
appdir = os . path . abspath ( os . path . normpath ( os . path . dirname ( __file__ ) ) )
2014-08-26 11:46:47 -07:00
appconf = {
' / ' : {
#'tools.proxy.on':True,
#'tools.proxy.base': conf["base"]["url"],
' tools.sessions.on ' : True ,
' tools.sessions.storage_type ' : ' file ' ,
' tools.sessions.storage_path ' : appdir + ' /sessions/ ' ,
' tools.sessions.timeout ' : 525600 ,
' request.show_tracebacks ' : True
} ,
2020-02-06 18:47:34 -08:00
' /static ' : {
2014-08-26 11:46:47 -07:00
' tools.staticdir.on ' : True ,
' tools.staticdir.dir ' : appdir + " /static/ "
}
}
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
cherrypy . config . update ( {
' server.socket_port ' : 3000 ,
' server.thread_pool ' : 1 ,
' server.socket_host ' : ' 0.0.0.0 ' ,
' sessionFilter.on ' : True ,
' server.show.tracebacks ' : True
} )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
cherrypy . server . socket_timeout = 5
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
# env - jinja2 template renderer
2020-02-06 18:47:34 -08:00
env = Environment ( loader = FileSystemLoader ( os . path . join ( appdir , " templates " ) ) )
2014-08-26 11:46:47 -07:00
# db - slightly custom sqlite3 object. rows = db.execute(query, args)
db = database ( )
# REC - recorder thread - see recordTick.py
2014-08-26 14:28:31 -07:00
#REC = recordTick(db)
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
def render ( template , args ) :
templatesCache = pysite . cacheTemplates ( )
defaults = { " templates " : templatesCache }
for item in args :
defaults [ item ] = args [ item ]
return quickRender ( template , defaults )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
def quickRender ( template , args ) :
template = env . get_template ( template )
return template . render ( args )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
class siteRoot ( object ) :
def __init__ ( self ) :
print ( " Siteroot init ! " )
self . templateCache = self . cacheTemplates ( )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
def cacheTemplates ( self ) :
templateFiles = os . listdir ( " jstemplates/ " )
templateList = [ ]
nameList = [ ]
for item in templateFiles :
name = item . split ( " . " )
templateList . append ( { " name " : name [ 0 ] , " content " : open ( " jstemplates/ " + item , " r " ) . read ( ) . replace ( " \t " , " " ) . replace ( " \n " , " " ) } )
nameList . append ( name [ 0 ] )
return quickRender ( " templates.html " , { " names " : json . dumps ( nameList ) , " templates " : templateList } )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
@cherrypy.expose
def index ( self ) :
return render ( " html.html " , { } )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
@cherrypy.expose
def htmltest ( self ) :
return render ( " html.tpl " , { } )
#index.exposed = True
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
@cherrypy.expose
def templates ( self ) :
return self . templateCache
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
class api ( object ) :
def __init__ ( self ) :
2014-08-26 14:29:18 -07:00
self . REC = recordTick ( db )
2020-02-06 18:47:34 -08:00
2014-08-26 15:09:40 -07:00
@cherrypy.expose
def tick ( self ) :
self . REC . tick ( )
return " OK "
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
@cherrypy.expose
def getStreams ( self ) :
2014-08-28 13:31:42 -07:00
streamList = db . execute ( ' SELECT * FROM " streams " ORDER BY " name " ASC; ' )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
for stream in streamList :
stream [ " time " ] = db . execute ( ' SELECT * FROM " times " WHERE streamid=? ' , [ stream [ " id " ] ] ) [ 0 ]
stream [ " files " ] = self . _getFiles ( stream [ " id " ] )
2014-08-26 16:12:00 -07:00
stream [ " recorder_status " ] = self . REC . streamStatus ( stream [ " id " ] )
stream [ " is_running " ] = stream [ " recorder_status " ] not in [ 0 , - 1 ] # idle states
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
return json . dumps ( streamList )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
def _getStream ( self , id ) :
streamList = db . execute ( ' SELECT * FROM " streams " WHERE " id " =? ' , [ int ( id ) ] )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
for stream in streamList :
stream [ " time " ] = db . execute ( ' SELECT * FROM " times " WHERE streamid=? ' , [ stream [ " id " ] ] ) [ 0 ]
stream [ " files " ] = self . _getFiles ( id )
2014-08-26 16:17:01 -07:00
stream [ " recorder_status " ] = self . REC . streamStatus ( stream [ " id " ] )
stream [ " is_running " ] = stream [ " recorder_status " ] not in [ 0 , - 1 ] # idle states
2014-08-26 11:46:47 -07:00
return streamList [ 0 ]
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
@cherrypy.expose
def getStream ( self , id ) :
return json . dumps ( self . _getStream ( id ) )
2020-02-06 18:47:34 -08:00
2014-08-26 16:31:39 -07:00
@cherrypy.expose
2014-08-26 16:32:18 -07:00
def changeStatus ( self , streamid , status ) :
2014-08-26 16:31:39 -07:00
streamid = int ( streamid )
2014-08-26 16:33:46 -07:00
db . execute ( ' UPDATE " streams " SET " status " =? WHERE " id " =? ; ' , [ status , streamid ] )
2014-08-26 16:31:39 -07:00
return json . dumps ( { " result " : True } )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
@cherrypy.expose
def changeTimeDay ( self , streamid , day , value ) :
streamid = int ( streamid )
value = value == " true "
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
col = " "
if day == " daysu " :
col = " su "
elif day == " daym " :
col = " m "
elif day == " dayt " :
col = " t "
elif day == " dayw " :
col = " w "
elif day == " dayr " :
col = " r "
elif day == " dayf " :
col = " f "
elif day == " daysa " :
col = " sa "
else :
raise cherrypy . HTTPError ( 500 , message = " Day not found " )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
db . execute ( ' UPDATE " times " SET " ' + col + ' " =? WHERE " streamid " =? ; ' , [ 1 if value else 0 , streamid ] )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
return json . dumps ( { " result " : True } )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
@cherrypy.expose
def changeName ( self , streamid , value ) :
streamid = int ( streamid )
db . execute ( ' UPDATE " streams " SET " name " =? WHERE " id " =? ' , [ value , streamid ] )
return json . dumps ( { " result " : True } )
@cherrypy.expose
def changeUrl ( self , streamid , value ) :
streamid = int ( streamid )
db . execute ( ' UPDATE " streams " SET " url " =? WHERE " id " =? ' , [ value , streamid ] )
return json . dumps ( { " result " : True } )
@cherrypy.expose
def changeTime ( self , streamid , startHour , startMin , endHour , endMin ) :
startHour = int ( startHour )
assert startHour > = 0 and startHour < = 23
startMin = int ( startMin )
assert startMin > = 0 and startMin < = 59
endHour = int ( endHour )
assert endHour > = 0 and endHour < = 23
endMin = int ( endMin )
assert endMin > = 0 and endMin < = 59
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
db . execute ( ' UPDATE " times " SET " starthour " =?, " startmin " =?, " endhour " =?, " endmin " =? WHERE " streamid " =? ; ' , [ startHour , startMin , endHour , endMin , streamid ] )
return json . dumps ( { " result " : True } )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
def _filterName ( self , input ) :
allowed = " abcdefghijklmnopqrstuvwxyz123456789- "
input = input . replace ( " " , " - " ) . lower ( )
output = [ ]
for i in range ( 0 , len ( allowed ) ) :
if input [ i : i + 1 ] in allowed :
output . append ( input [ i : i + 1 ] )
return ' ' . join ( output )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
@cherrypy.expose
def createStream ( self , data ) :
data = json . loads ( data )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
assert not data [ " name " ] == " "
assert not data [ " url " ] == " "
assert data [ " time " ] [ " su " ] or data [ " time " ] [ " m " ] or data [ " time " ] [ " t " ] or data [ " time " ] [ " w " ] or data [ " time " ] [ " r " ] or data [ " time " ] [ " f " ] or data [ " time " ] [ " sa " ]
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
dirName = self . _filterName ( data [ " name " ] )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
rowid = db . execute ( ' INSERT INTO " streams " ( " user " , " name " , " url " , " directory " , " status " , " message " ) VALUES (?, ?, ?, ?, ?, ?); ' , [ 0 , data [ " name " ] , data [ " url " ] , dirName , data [ " status " ] , " " ] )
db . execute ( ' INSERT INTO " times " ( " streamid " , " su " , " m " , " t " , " w " , " r " , " f " , " sa " , " starthour " , " startmin " , " endhour " , " endmin " ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?); ' , [
rowid ,
data [ " time " ] [ " su " ] ,
data [ " time " ] [ " m " ] ,
data [ " time " ] [ " t " ] ,
data [ " time " ] [ " w " ] ,
data [ " time " ] [ " r " ] ,
data [ " time " ] [ " f " ] ,
data [ " time " ] [ " sa " ] ,
data [ " time " ] [ " startHour " ] ,
data [ " time " ] [ " startMin " ] ,
data [ " time " ] [ " endHour " ] ,
data [ " time " ] [ " endMin " ]
] )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
return json . dumps ( { " result " : rowid } )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
def _getFiles ( self , id ) :
stream = db . execute ( ' SELECT * FROM " streams " WHERE " id " =? ' , [ int ( id ) ] ) [ 0 ]
recordingsDir = " files/output/ " + stream [ " directory " ] + " / "
files = [ ]
if os . path . exists ( recordingsDir ) :
files = os . listdir ( recordingsDir )
files . sort ( )
allFiles = [ ]
for i in range ( 0 , len ( files ) ) :
2014-08-28 13:33:40 -07:00
item = files [ i ]
2014-08-28 13:32:54 -07:00
if item [ 0 : 1 ] == " . " :
continue ;
2014-08-26 11:46:47 -07:00
size = os . path . getsize ( recordingsDir + item )
allFiles . append ( {
" filename " : item ,
" directory " : recordingsDir ,
" streamdir " : stream [ " directory " ] ,
" filenum " : i ,
" bytes " : size ,
" mbytes " : round ( size / 1024.0 / 1024.0 , 2 ) ,
2014-08-28 21:51:49 -07:00
" date " : os . path . getctime ( recordingsDir + item )
2014-08-26 11:46:47 -07:00
} )
return allFiles
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
@cherrypy.expose
def getFiles ( self , id ) :
files = self . _getFiles ( id )
return json . dumps ( { " data " : files } )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
@cherrypy.expose
def download ( self , id , fn ) :
files = self . _getFiles ( id )
item = files [ int ( fn ) ]
raise cherrypy . HTTPRedirect ( " /static/output/ " + item [ " streamdir " ] + " / " + item [ " filename " ] , 302 )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
@cherrypy.expose
def getUrl ( self , id , fn ) :
files = self . _getFiles ( id )
item = files [ int ( fn ) ]
return json . dumps ( { " result " : " /static/output/ " + item [ " streamdir " ] + " / " + item [ " filename " ] } )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
@cherrypy.expose
@cherrypy.tools.response_headers ( headers = [ ( ' Content-Type ' , ' application/rss+xml ' ) ] )
def getPodcast ( self , id ) :
stream = self . _getStream ( id )
# Thu, 31 Jul 2014 07:13:48 +0000
for f in stream [ " files " ] :
2014-08-28 21:51:49 -07:00
f [ " date " ] = datetime . fromtimestamp ( f [ " date " ] ) . strftime ( " %a , %d % b % Y % H: % M: % S +0800 " )
2014-08-26 11:46:47 -07:00
return str . encode ( render ( " podcast.html " , {
" stream " : stream ,
2014-08-28 21:51:49 -07:00
" builddate " : datetime . now ( ) . strftime ( " %a , %d % b % Y % H: % M: % S +0800 " ) #Thu, 31 Jul 2014 07:13:48 +0000
2014-08-26 11:46:47 -07:00
} ) )
2020-02-06 18:47:34 -08:00
2014-08-26 13:45:05 -07:00
@cherrypy.expose
def getRecStatus ( self , id ) :
2014-08-26 14:28:31 -07:00
return json . dumps ( { " data " : self . REC . streamStatus ( int ( id ) ) } )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
pysite = siteRoot ( )
pysite . api = api ( )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
print ( " Ready to start application " )
2020-02-06 18:47:34 -08:00
2014-08-26 11:46:47 -07:00
if ( len ( sys . argv ) > 1 and sys . argv [ 1 ] == " test " ) :
print ( " test! " )
application = cherrypy . quickstart ( pysite , ' / ' , appconf )
else :
sys . stdout = sys . stderr
cherrypy . config . update ( { ' environment ' : ' embedded ' } )
application = cherrypy . tree . mount ( pysite , " / " , appconf )