diff --git a/Gamez.ini b/Gamez.ini index a92a8ed..fc18e19 100644 --- a/Gamez.ini +++ b/Gamez.ini @@ -3,19 +3,17 @@ server.socket_host = "127.0.0.1" server.socket_port = 8085 [NZBMatrix] -username = -api_key = +username = "" +api_key = "" [Sabnzbd] -api_key = +api_key = "" host = "127.0.0.1" -port = 8080 -password = "" [Scheduler] download_interval = 60 [SystemGenerated] is_to_ignore_update = 0 -ignored_version = +ignored_version = "" diff --git a/Gamez.py b/Gamez.py index 665ac2e..5e48955 100644 --- a/Gamez.py +++ b/Gamez.py @@ -14,12 +14,15 @@ import cherrypy.process.plugins from cherrypy.process.plugins import Daemonizer from lib.ConfigFunctions import CheckConfigForAllKeys +from lib.DBFunctions import ValidateDB +from lib.Logger import LogEvent app_path = os.path.dirname(os.path.abspath("__FILE__")) config_path = os.path.join(app_path,'Gamez.ini') class RunApp(): def RunWebServer(self,isToDaemonize): + LogEvent("Generating CherryPy configuration") cherrypy.config.update(config_path) css_path = os.path.join(app_path,'css') images_path = os.path.join(app_path,'images') @@ -38,11 +41,15 @@ def RunWebServer(self,isToDaemonize): } daemon = Daemonizer(cherrypy.engine) - if(isToDaemonize == 1): + if(isToDaemonize == 1): + LogEvent("Preparing to run in daemon mode") daemon.subscribe() + LogEvent("Generating Post Process Script") GenerateSabPostProcessScript() RunGameTask() + + LogEvent("Getting download interval from config file and invoking scheduler") config = ConfigParser.RawConfigParser() config.read('Gamez.ini') interval = config.get('Scheduler','download_interval').replace('"','') @@ -50,8 +57,11 @@ def RunWebServer(self,isToDaemonize): workerTask = cherrypy.process.plugins.BackgroundTask(fInterval,RunGameTask) try: workerTask.start() + + LogEvent("Starting the Gamez web server") cherrypy.quickstart(WebRoot(app_path),'/',config=conf) except KeyboardInterrupt: + LogEvent("Shutting down Gamez") workerTask.cancel() if(isToDaemonize == 1): daemon.unsubscribe() @@ -103,12 +113,16 @@ def RunGameTask(): sabnzbdHost = config.get('Sabnzbd','host').replace('"','') sabnzbdPort = config.get('Sabnzbd','port').replace('"','') sabnzbdApi = config.get('Sabnzbd','api_key').replace('"','') + LogEvent("Searching for games") lib.GameTasks.GameTasks().FindGames(nzbMatrixUser,nzbMatrixApi,sabnzbdApi,sabnzbdHost,sabnzbdPort) except: print(sys.exc_info()[0]) if __name__ == '__main__': + LogEvent("Checking config file for completeness") CheckConfigForAllKeys(app_path) + LogEvent("Checking to make sure all tables exist in the database") + ValidateDB() isToDaemonize = 0 params = sys.argv for param in params: diff --git a/css/navigation.css b/css/navigation.css index dd32981..184aae3 100644 --- a/css/navigation.css +++ b/css/navigation.css @@ -171,4 +171,37 @@ div#menu li.back .left { background-color: khaki; color: Maroon; border: solid 1px silver; -} \ No newline at end of file +} + + +.clear-log-button { + border-top: 1px solid #96d1f8; + background: #65a9d7; + background: -webkit-gradient(linear, left top, left bottom, from(#3e779d), to(#65a9d7)); + background: -webkit-linear-gradient(top, #3e779d, #65a9d7); + background: -moz-linear-gradient(top, #3e779d, #65a9d7); + background: -ms-linear-gradient(top, #3e779d, #65a9d7); + background: -o-linear-gradient(top, #3e779d, #65a9d7); + padding: 5px 10px; + -webkit-border-radius: 8px; + -moz-border-radius: 8px; + border-radius: 8px; + -webkit-box-shadow: rgba(0,0,0,1) 0 1px 0; + -moz-box-shadow: rgba(0,0,0,1) 0 1px 0; + box-shadow: rgba(0,0,0,1) 0 1px 0; + text-shadow: rgba(0,0,0,.4) 0 1px 0; + color: white; + font-size: 14px; + font-family: Georgia, serif; + text-decoration: none; + vertical-align: middle; + } +.clear-log-button:hover { + border-top-color: #28597a; + background: #28597a; + color: #ccc; + } +.clear-log-button:active { + border-top-color: #1b435e; + background: #1b435e; + } \ No newline at end of file diff --git a/css/settings.css b/css/settings.css new file mode 100644 index 0000000..ea48f7c --- /dev/null +++ b/css/settings.css @@ -0,0 +1,54 @@ +body{ +font-family:"Lucida Grande", "Lucida Sans Unicode", Verdana, Arial, Helvetica, sans-serif; +font-size:12px; +} +p, h1, form, button{border:0; margin:0; padding:0;} +.spacer{clear:both; height:1px;} +/* ----------- My Form ----------- */ +.myform{ +margin:0 auto; +width:600px; +padding:14px; +} + +/* ----------- stylized ----------- */ +#stylized{ +border:solid 2px #b7ddf2; +background:#ebf4fb; +} +#stylized h1 { +font-size:14px; +font-weight:bold; +margin-bottom:10px; +} +#stylized label{ +display:block; +font-weight:bold; +text-align:right; +width:240px; +float:left; +margin-top:5px; +} +#stylized input{ +float:left; +font-size:12px; +padding:4px 2px; +border:solid 1px #aacfe4; +width:300px; +margin:2px 0 20px 10px; +} +#stylized button{ +clear:both; +margin-left:250px; +width:125px; +height:31px; +background:#666666 url(img/button.png) no-repeat; +text-align:center; +line-height:31px; +color:#FFFFFF; +font-size:11px; +font-weight:bold; +} + + + diff --git a/lib/ConfigFunctions.py b/lib/ConfigFunctions.py index 96a2744..56c8e9b 100644 --- a/lib/ConfigFunctions.py +++ b/lib/ConfigFunctions.py @@ -51,10 +51,6 @@ def CheckConfigForAllKeys(app_path): config.set('Sabnzbd','host','"127.0.0.1"') changesMade = True - if(config.has_option('Sabnzbd','password') == False): - config.set('Sabnzbd','password','""') - changesMade = True - if(config.has_option('Scheduler','download_interval') == False): config.set('Scheduler','download_interval','60') changesMade = True diff --git a/lib/ConfigFunctions.pyc b/lib/ConfigFunctions.pyc index 1363c23..c573a68 100644 Binary files a/lib/ConfigFunctions.pyc and b/lib/ConfigFunctions.pyc differ diff --git a/lib/Constants.pyc b/lib/Constants.pyc index 8ae4e41..74786fd 100644 Binary files a/lib/Constants.pyc and b/lib/Constants.pyc differ diff --git a/lib/DBFunctions.py b/lib/DBFunctions.py index e003ca2..7b74c64 100644 --- a/lib/DBFunctions.py +++ b/lib/DBFunctions.py @@ -1,6 +1,8 @@ import os import sqlite3 import sys +import datetime +from Logger import LogEvent def GetAllWiiGames(): db_path = os.path.join(os.path.abspath(""),"Gamez.db") @@ -94,6 +96,7 @@ def GetWiiGameDataFromTerm(term): return data def AddWiiGameToDb(db_id,status): + LogEvent("Adding game in 'Wanted' status") db_path = os.path.join(os.path.abspath(""),"Gamez.db") sql = "insert into requested_games(WiiGameID,status) select '" + db_id + "','" + status + "' where not exists(select 1 from requested_games where WiiGameID='" + db_id + "')" connection = sqlite3.connect(db_path) @@ -117,7 +120,14 @@ def GetRequestedGames(): game_name = str(record[1]) game_id = str(record[2]) status = str(record[3]) - rowdata = "Delete" + game_name + "" + game_id + "" + status + "" + rowdata = "Delete" + game_name + "" + game_id + "" + status + "" data = data + rowdata except: continue @@ -125,6 +135,7 @@ def GetRequestedGames(): return data def RemoveWiiGameFromDb(db_id): + LogEvent("Removing game") db_path = os.path.join(os.path.abspath(""),"Gamez.db") sql = "delete from requested_games where WiiGameID='" + db_id + "'" connection = sqlite3.connect(db_path) @@ -145,6 +156,7 @@ def GetRequestedGamesAsArray(): return result def UpdateStatus(game_id,status): + LogEvent("Update status of game to " + status) db_path = os.path.join(os.path.abspath(""),"Gamez.db") sql = "update requested_games set status='" + status + "' where WiiGameID='" + game_id + "'" connection = sqlite3.connect(db_path) @@ -152,4 +164,70 @@ def UpdateStatus(game_id,status): cursor.execute(sql) connection.commit() cursor.close() + return + +def ValidateDB(): + LogEvent("Checking to make sure database has the correct tables") + db_path = os.path.join(os.path.abspath(""),"Gamez.db") + sql = "select name from sqlite_master where type='table'" + logTableExists = False + connection = sqlite3.connect(db_path) + cursor = connection.cursor() + cursor.execute(sql) + result = cursor.fetchall() + tables = list() + for record in result: + tableName = str(record[0]) + if(tableName == 'gamez_log'): + logTableExists = True + cursor.close() + if(logTableExists == False): + LogEvent("Creating table 'gamez_log'") + sql = "create table gamez_log(ID INTEGER NOT NULL PRIMARY KEY UNIQUE,message TEXT(255) NOT NULL,created_date DATE)" + connection = sqlite3.connect(db_path) + cursor = connection.cursor() + cursor.execute(sql) + connection.commit() + cursor.close() + return + +def AddEventToDB(message): + db_path = os.path.join(os.path.abspath(""),"Gamez.db") + createdDate = datetime.datetime.now() + sql = "INSERT INTO gamez_log (message,created_date) values('" + message + "',datetime())" + connection = sqlite3.connect(db_path) + cursor = connection.cursor() + cursor.execute(sql) + connection.commit() + cursor.close() + return + +def GetLog(): + db_path = os.path.join(os.path.abspath(""),"Gamez.db") + sql = "SELECT message,created_date FROM gamez_log order by created_date desc" + data = '' + connection = sqlite3.connect(db_path) + cursor = connection.cursor() + cursor.execute(sql) + result = cursor.fetchall() + for record in result: + try: + message = str(record[0]) + created_date = str(record[1]) + rowdata = "" + message + "" + created_date + "" + data = data + rowdata + except: + continue + cursor.close() + return data + +def ClearDBLog(): + db_path = os.path.join(os.path.abspath(""),"Gamez.db") + createdDate = datetime.datetime.now() + sql = "delete from gamez_log" + connection = sqlite3.connect(db_path) + cursor = connection.cursor() + cursor.execute(sql) + connection.commit() + cursor.close() return \ No newline at end of file diff --git a/lib/DBFunctions.pyc b/lib/DBFunctions.pyc index 8eac889..cd55db8 100644 Binary files a/lib/DBFunctions.pyc and b/lib/DBFunctions.pyc differ diff --git a/lib/GameTasks.py b/lib/GameTasks.py index cc91d8f..e48c73f 100644 --- a/lib/GameTasks.py +++ b/lib/GameTasks.py @@ -6,6 +6,7 @@ import shutil import stat from subprocess import call +from Logger import LogEvent class GameTasks(): @@ -18,6 +19,7 @@ def FindGames(self, nzbmatrixusername, nzbmatrixapi,sabnzbdApi,sabnzbdHost,sabnz try: game_name = str(game[0]) game_id = str(game[1]) + LogEvent("Searching for game: " + game_name) nzbmatrixResult = GameTasks().FindGameOnNZBMatrix(game_name,game_id,nzbmatrixusername,nzbmatrixapi,sabnzbdApi,sabnzbdHost,sabnzbdPort) except: error = sys.exc_info()[0] @@ -37,6 +39,7 @@ def FindGameOnNZBMatrix(self,game_name,game_id,username,api,sabnzbdApi,sabnzbdHo nzbID = nzbID.replace(";","") if(nzbID <> "nothing_found"): + LogEvent("Game found on NZB Matrix") GameTasks().AddNZBToSab(nzbID,game_name,sabnzbdApi,sabnzbdHost,sabnzbdPort,game_id) UpdateStatus(game_id,"Snatched") return @@ -47,6 +50,7 @@ def AddNZBToSab(self,nzbID,game_name,sabnzbdApi,sabnzbdHost,sabnzbdPort,game_id) responseObject = urllib.FancyURLopener({}).open(url) responseObject.read() responseObject.close() + LogEvent("NZB added to Sabnzbd") return def CheckIfPostProcessExistsInSab(self,sabnzbdApi,sabnzbdHost,sabnzbdPort): @@ -61,10 +65,12 @@ def CheckIfPostProcessExistsInSab(self,sabnzbdApi,sabnzbdHost,sabnzbdPort): destPath = os.path.join(scriptDir,"gamezPostProcess.py") try: + LogEvent("Copying post process script to Sabnzbd scripts folder") shutil.copyfile(srcPath,destPath) except: print 'Error Copying File' try: + LogEvent("Setting permissions on post process script") cmd = "chmod +x '" + destPath + "'" os.system(cmd) except: diff --git a/lib/GameTasks.pyc b/lib/GameTasks.pyc index 2f45429..b87f989 100644 Binary files a/lib/GameTasks.pyc and b/lib/GameTasks.pyc differ diff --git a/lib/Logger.py b/lib/Logger.py new file mode 100644 index 0000000..e53db6b --- /dev/null +++ b/lib/Logger.py @@ -0,0 +1,9 @@ +import DBFunctions + +def LogEvent(message): + DBFunctions.AddEventToDB(message) + return + +def ClearLog(): + ClearDBLog() + return \ No newline at end of file diff --git a/lib/Logger.pyc b/lib/Logger.pyc new file mode 100644 index 0000000..483bcc2 Binary files /dev/null and b/lib/Logger.pyc differ diff --git a/lib/UpgradeFunctions.py b/lib/UpgradeFunctions.py index a394ca2..a30b260 100644 --- a/lib/UpgradeFunctions.py +++ b/lib/UpgradeFunctions.py @@ -7,8 +7,10 @@ import urllib2 import tarfile import shutil +from Logger import LogEvent def CheckForNewVersion(app_path): + LogEvent("Checking to see if a new version is available") newVersionAvailable = False currentVersion = VersionNumber() mostRecentVersion = GetLatestVersion() @@ -25,6 +27,7 @@ def CheckForNewVersion(app_path): return newVersionAvailable def GetLatestVersion(): + LogEvent("Retrieving the latest version") mostRecentVersion = '0.0.0.0' url = 'https://api.github.com/repos/mdlesk/Gamez/tags' opener = urllib.FancyURLopener({}) @@ -44,6 +47,7 @@ def GetLatestVersion(): return mostRecentVersion def IgnoreVersion(app_path): + LogEvent("Ignoring Version") versionToIgnore = GetLatestVersion() config = ConfigParser.RawConfigParser() configFilePath = os.path.join(app_path,'Gamez.ini') @@ -51,11 +55,12 @@ def IgnoreVersion(app_path): if(config.has_section('SystemGenerated') == False): config.add_section('SystemGenerated') config.set('SystemGenerated','is_to_ignore_update','1') - config.set('SystemGenerated','ignored_version','"versionToIgnore"') + config.set('SystemGenerated','ignored_version','"' + versionToIgnore + '"') with open(configFilePath,'wb') as configFile: config.write(configFile) def UpdateToLatestVersion(app_path): + LogEvent("Updating to latest version") filesToIgnore = ["Gamez.ini","Gamez.db"] filesToIgnoreSet = set(filesToIgnore) updatePath = os.path.join(app_path,"update") @@ -63,15 +68,18 @@ def UpdateToLatestVersion(app_path): os.makedirs(updatePath) latestVersion = GetLatestVersion() tagUrl = "https://github.com/mdlesk/Gamez/tarball/v" + latestVersion + LogEvent("Downloading from GitHub") data = urllib2.urlopen(tagUrl) downloadPath = os.path.join(app_path,data.geturl().split('/')[-1]) downloadedFile = open(downloadPath,'wb') downloadedFile.write(data.read()) downloadedFile.close() + LogEvent("Extracting files") tarredFile = tarfile.open(downloadPath) tarredFile.extractall(updatePath) tarredFile.close() os.remove(downloadPath) + LogEvent("Upgrading files") contentsDir = [x for x in os.listdir(updatePath) if os.path.isdir(os.path.join(updatePath, x))] updatedFilesPath = os.path.join(updatePath,contentsDir[0]) for dirname, dirnames, filenames in os.walk(updatedFilesPath): @@ -94,4 +102,5 @@ def UpdateToLatestVersion(app_path): config.set('SystemGenerated','ignored_version','"versionToIgnore"') with open(configFilePath,'wb') as configFile: config.write(configFile) + LogEvent("Upgrading complete") return "Successfully Upgraded to Version " + latestVersion \ No newline at end of file diff --git a/lib/UpgradeFunctions.pyc b/lib/UpgradeFunctions.pyc index a180313..1b7b6b8 100644 Binary files a/lib/UpgradeFunctions.pyc and b/lib/UpgradeFunctions.pyc differ diff --git a/lib/WebRoot.py b/lib/WebRoot.py index 463e4d1..9205a9d 100644 --- a/lib/WebRoot.py +++ b/lib/WebRoot.py @@ -1,8 +1,11 @@ import cherrypy import json import os -from DBFunctions import GetWiiGamesFromTerm, GetWiiGameDataFromTerm, AddWiiGameToDb, GetRequestedGames, RemoveWiiGameFromDb,UpdateStatus +from DBFunctions import GetWiiGamesFromTerm, GetWiiGameDataFromTerm, AddWiiGameToDb, GetRequestedGames, RemoveWiiGameFromDb, UpdateStatus, GetLog, ClearDBLog from UpgradeFunctions import CheckForNewVersion,IgnoreVersion,UpdateToLatestVersion +import ConfigParser +from time import sleep +import urllib class WebRoot: appPath = '' @@ -45,6 +48,16 @@ def index(self,status_message='',version=''): Home +
  • + + Settings + +
  • +
  • + + Log + +
  • @@ -76,6 +89,7 @@ def index(self,status_message='',version=''): html = html + """No games added. Try searching for some.""" else: html = html + """ + @@ -83,6 +97,7 @@ def index(self,status_message='',version=''): + """ @@ -114,12 +129,11 @@ def search(self,term=''): - - + - + @@ -130,12 +144,22 @@ def search(self,term=''): Home +
  • + + Settings + +
  • +
  • + + Log + +
  • -
    +
      - + + + + + + + + +
    +
    +

    General

    + + + + + + + + + + +

    SABnzbd+

    + + + + + + + + + + +

    NZB Matrix

    + + + + + + + + +
    + + + +
    + + + + + + + + """ + return html; + + @cherrypy.expose + def log(self,status_message='',version=''): + if(os.name <> 'nt'): + os.chdir(WebRoot.appPath) + html = """ + + + + + + + + + + + + + + """ + html = html + """ + + +
    """ + db_result = GetLog() + if(db_result == ''): + html = html + """No log entries.""" + else: + html = html + """ + +
    Game Name Game ID StatusUpdate Status
    + + + + + + """ + html = html + db_result + html = html + """ + +
    MessageDate / Time
    +
    + + """ + html = html + """ +
    + + + + """ return html; @@ -225,4 +456,32 @@ def ignorecurrentversion(self,verification): def upgradetolatestversion(self,verification): if(verification == "SYSTEM_DIRECTED"): status = UpdateToLatestVersion(WebRoot.appPath) - raise cherrypy.InternalRedirect("/?status_message=" + status) \ No newline at end of file + raise cherrypy.InternalRedirect("/?status_message=" + status) + + @cherrypy.expose + def savesettings(self,cherrypyHost='', nzbMatrixUsername='', downloadInterval=3600, sabPort='', nzbMatrixApi='', sabApi='', cherrypyPort='', sabHost=''): + cherrypyHost = '"' + cherrypyHost + '"' + nzbMatrixUsername = '"' + nzbMatrixUsername + '"' + nzbMatrixApi = '"' + nzbMatrixApi + '"' + sabApi = '"' + sabApi + '"' + sabHost = '"' + sabHost + '"' + config = ConfigParser.RawConfigParser() + configFilePath = os.path.join(WebRoot.appPath,'Gamez.ini') + config.read(configFilePath) + config.set('global','server.socket_host',cherrypyHost) + config.set('global','server.socket_port',cherrypyPort) + config.set('NZBMatrix','username',nzbMatrixUsername) + config.set('NZBMatrix','api_key',nzbMatrixApi) + config.set('Sabnzbd','host',sabHost) + config.set('Sabnzbd','port',sabPort) + config.set('Sabnzbd','api_key',sabApi) + config.set('Scheduler','download_interval',downloadInterval) + with open(configFilePath,'wb') as configFile: + config.write(configFile) + status = "Application Settings Updated Successfully. Gamez is restarting. If after 5 seconds, Gamez isn't working, update the Gamez.ini file and re-launch Gamez" + raise cherrypy.InternalRedirect("/?status_message=" + status) + + @cherrypy.expose + def clearlog(self): + ClearDBLog() + raise cherrypy.InternalRedirect('/') \ No newline at end of file diff --git a/lib/WebRoot.pyc b/lib/WebRoot.pyc index 9fd54e7..ecd1093 100644 Binary files a/lib/WebRoot.pyc and b/lib/WebRoot.pyc differ diff --git a/lib/__init__.pyc b/lib/__init__.pyc index da42fe5..7c98187 100644 Binary files a/lib/__init__.pyc and b/lib/__init__.pyc differ