diff --git a/CouchPotato.py b/CouchPotato.py old mode 100644 new mode 100755 index a07f235..f4083f6 --- a/CouchPotato.py +++ b/CouchPotato.py @@ -1,167 +1,63 @@ -from threading import Thread -from wx.lib.softwareupdate import SoftwareUpdate +#!/usr/bin/env python +# -*- coding: utf-8 -*- +'''Wrapper for the command line interface.''' + +from os.path import dirname import os import sys -import webbrowser -import wx +import subprocess +import time -# Include proper dirs -if hasattr(sys, 'frozen'): - import libs - base_path = os.path.dirname(os.path.dirname(os.path.abspath(libs.__file__))) - print base_path -else: - base_path = os.path.dirname(os.path.abspath(__file__)) +# Root path +base_path = dirname(os.path.abspath(__file__)) -lib_dir = os.path.join(base_path, 'libs') +# Insert local directories into path +sys.path.insert(0, os.path.join(base_path, 'libs')) -sys.path.insert(0, base_path) -sys.path.insert(0, lib_dir) +from couchpotato.core.logger import CPLog +log = CPLog(__name__) # Get options via arg from couchpotato.runner import getOptions -from couchpotato.runner import runCouchPotato - - -class TaskBarIcon(wx.TaskBarIcon): - - TBMENU_OPEN = wx.NewId() - TBMENU_SETTINGS = wx.NewId() - TBMENU_ABOUT = wx.ID_ABOUT - TBMENU_EXIT = wx.ID_EXIT - - def __init__(self, frame): - wx.TaskBarIcon.__init__(self) - self.frame = frame - - icon = wx.Icon('icon.ico', wx.BITMAP_TYPE_ANY) - self.SetIcon(icon) - - self.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.onTaskBarActivate) - - self.Bind(wx.EVT_MENU, self.onOpen, id = self.TBMENU_OPEN) - self.Bind(wx.EVT_MENU, self.onSettings, id = self.TBMENU_SETTINGS) - self.Bind(wx.EVT_MENU, self.onAbout, id = self.TBMENU_ABOUT) - self.Bind(wx.EVT_MENU, self.onTaskBarClose, id = self.TBMENU_EXIT) - - - def CreatePopupMenu(self): - menu = wx.Menu() - menu.Append(self.TBMENU_OPEN, "Open") - menu.Append(self.TBMENU_SETTINGS, "Settings") - menu.Append(self.TBMENU_ABOUT, "About") - menu.Append(self.TBMENU_EXIT, "Close") - return menu - - def onOpen(self, event): - url = self.frame.parent.getSetting('base_url') - webbrowser.open(url) - - def onSettings(self, event): - url = self.frame.parent.getSetting('base_url') + '/settings/' - webbrowser.open(url) - - def onAbout(self, event): - print 'onAbout' - - def onTaskBarActivate(self, evt): - if not self.frame.IsShown(): - self.frame.Show(True) - self.frame.Raise() - - def onTaskBarClose(self, evt): - wx.CallAfter(self.frame.Close) - - def makeIcon(self, img): - if "wxMSW" in wx.PlatformInfo: - img = img.Scale(16, 16) - elif "wxGTK" in wx.PlatformInfo: - img = img.Scale(22, 22) - - icon = wx.IconFromBitmap(img.CopyFromBitmap()) - return icon - - -class MainFrame(wx.Frame): - - def __init__(self, parent): - wx.Frame.__init__(self, None) - - self.parent = parent - self.tbicon = TaskBarIcon(self) - +from couchpotato.core.helpers.variable import getDataDir +options = getOptions(base_path, sys.argv[1:]) +data_dir = getDataDir() + +def start(): + try: + args = [sys.executable] + sys.argv + new_environ = os.environ.copy() + new_environ['cp_main'] = 'true' + + if os.name == 'nt': + for key, value in new_environ.iteritems(): + if isinstance(value, unicode): + new_environ[key] = value.encode('iso-8859-1') + + subprocess.call(args, env = new_environ) + return os.path.isfile(os.path.join(data_dir, 'restart')) + except KeyboardInterrupt, e: + pass + except Exception, e: + log.critical(e) + return 0 -class WorkerThread(Thread): - - def __init__(self, desktop): - Thread.__init__(self) - self._desktop = desktop - - self.start() - - def run(self): - - args = ['--nogit', '--console_log']#, '--quiet'] - options = getOptions(base_path, args) +from couchpotato.runner import runCouchPotato +if __name__ == '__main__': + if os.environ.get('cp_main', 'false') == 'true': try: - runCouchPotato(options, base_path, args, desktop = self._desktop) - except KeyboardInterrupt, e: - raise + runCouchPotato(options, base_path, sys.argv[1:]) except Exception, e: - raise - finally: - pass - - -class CouchPotatoApp(wx.App, SoftwareUpdate): - - settings = {} - events = {} - restart = False - - def OnInit(self): - - # Updater - base_url = 'http://couchpotatoapp.com/updates/' - self.InitUpdates(base_url, base_url + 'changelog.txt', - icon = wx.Icon('icon.ico')) - - self.frame = MainFrame(self) - self.frame.Bind(wx.EVT_CLOSE, self.onClose) - - # CouchPotato thread - self.worker = WorkerThread(self) - - return True - - def setSettings(self, settings = {}): - self.settings = settings - - def getSetting(self, name): - return self.settings.get(name) - - def addEvents(self, events = {}): - for name in events.iterkeys(): - self.events[name] = events[name] - - def onClose(self, event): - onClose = self.events.get('onClose') - if self.events.get('onClose'): - onClose(event) - else: - self.afterShutdown() - - def afterShutdown(self, restart = False): - self.frame.Destroy() - self.restart = restart - - -if __name__ == '__main__': - app = CouchPotatoApp(redirect = False) - app.MainLoop() - - #path = os.path.join(sys.path[0].decode(sys.getfilesystemencoding()), sys.argv[0]) - #if app.restart: - # wx.Process.Open(sys.executable + ' ' + path) + log.critical(e) + else: + while 1: + restart = start() + if not restart: + break + + from couchpotato.core.event import fireEvent + fireEvent('app.crappy_shutdown', single = True) + time.sleep(1) + sys.exit() diff --git a/README.md b/README.md index 8226558..4f70d09 100644 --- a/README.md +++ b/README.md @@ -1 +1,5 @@ -CouchPotato Desktop \ No newline at end of file +CouchPotato Server +===== + +CouchPotato (CP) is an automatic NZB and torrent downloader. You can keep a "movies I want"-list and it will search for NZBs/torrents of these movies every X hours. +Once a movie is found, it will send it to SABnzbd or download the torrent to a specified directory. \ No newline at end of file diff --git a/couchpotato/core/_base/_core/main.py b/couchpotato/core/_base/_core/main.py index 4c7e75b..e9b4bdf 100644 --- a/couchpotato/core/_base/_core/main.py +++ b/couchpotato/core/_base/_core/main.py @@ -1,3 +1,4 @@ +from couchpotato import app from couchpotato.api import addApiView from couchpotato.core.event import fireEvent, addEvent from couchpotato.core.helpers.request import jsonified @@ -6,6 +7,7 @@ from couchpotato.core.logger import CPLog from couchpotato.core.plugins.base import Plugin from couchpotato.environment import Env from flask import request +from flask.helpers import url_for import os import time import traceback @@ -27,7 +29,6 @@ class Core(Plugin): addEvent('app.crappy_restart', self.crappyRestart) addEvent('app.load', self.launchBrowser, priority = 1) addEvent('app.base_url', self.createBaseUrl) - addEvent('app.api_url', self.createApiUrl) addEvent('setting.save.core.password', self.md5Password) @@ -42,10 +43,16 @@ class Core(Plugin): }) def crappyShutdown(self): - self.urlopen('%sapp.shutdown' % self.createApiUrl()) + ctx = app.test_request_context() + ctx.push() + self.urlopen('%s%sapp.shutdown' % (fireEvent('app.base_url', single = True), url_for('api.index'))) + ctx.pop() def crappyRestart(self): - self.urlopen('%sapp.restart' % self.createApiUrl()) + ctx = app.test_request_context() + ctx.push() + self.urlopen('%s%sapp.restart' % (fireEvent('app.base_url', single = True), url_for('api.index'))) + ctx.pop() def shutdown(self): self.initShutdown() @@ -56,7 +63,6 @@ class Core(Plugin): return 'restarting' def initShutdown(self, restart = False): - log.info('Shutting down' if not restart else 'Restarting') fireEvent('app.shutdown') @@ -116,7 +122,3 @@ class Core(Plugin): port = Env.setting('port') return '%s:%d' % (cleanHost(host).rstrip('/'), int(port)) - - def createApiUrl(self): - - return '%s/%s/' % (self.createBaseUrl(), Env.setting('api_key')) diff --git a/couchpotato/core/_base/desktop/main.py b/couchpotato/core/_base/desktop/main.py index ce1ff28..bd52dcd 100644 --- a/couchpotato/core/_base/desktop/main.py +++ b/couchpotato/core/_base/desktop/main.py @@ -7,28 +7,25 @@ log = CPLog(__name__) if Env.get('desktop'): + #import os + #import sys + import wx + class Desktop(Plugin): def __init__(self): desktop = Env.get('desktop') desktop.setSettings({ - 'base_url': fireEvent('app.base_url', single = True), - 'api_url': fireEvent('app.api_url', single = True), - 'api': Env.setting('api'), + 'url': fireEvent('app.base_url', single = True) }) - # Events from desktop - desktop.addEvents({ - 'onClose': self.onClose, - }) + def onClose(event): + return fireEvent('app.crappy_shutdown') + desktop.close_handler = onClose - # Events to desktop addEvent('app.after_shutdown', desktop.afterShutdown) - def onClose(self, event): - return fireEvent('app.crappy_shutdown', single = True) - else: class Desktop(Plugin): diff --git a/couchpotato/environment.py b/couchpotato/environment.py index 39adb3d..c6b427e 100644 --- a/couchpotato/environment.py +++ b/couchpotato/environment.py @@ -14,7 +14,7 @@ class Env(object): _args = None _quiet = False _deamonize = False - _desktop = None + _version = 0.5 ''' Data paths and directories ''' _app_dir = "" diff --git a/icon.icns b/icon.icns deleted file mode 100644 index 04cbc86..0000000 Binary files a/icon.icns and /dev/null differ diff --git a/icon.ico b/icon.ico deleted file mode 100644 index f93f9fb..0000000 Binary files a/icon.ico and /dev/null differ diff --git a/libs/guessit/fileutils.py b/libs/guessit/fileutils.py index 1c263b8..7c07af7 100644 --- a/libs/guessit/fileutils.py +++ b/libs/guessit/fileutils.py @@ -18,6 +18,7 @@ # along with this program. If not, see . # +import ntpath import os.path @@ -44,7 +45,7 @@ def split_path(path): """ result = [] while True: - head, tail = os.path.split(path) + head, tail = ntpath.split(path) # on Unix systems, the root folder is '/' if head == '/' and tail == '': diff --git a/setup.py b/setup.py deleted file mode 100644 index c505c6b..0000000 --- a/setup.py +++ /dev/null @@ -1,86 +0,0 @@ -from esky import bdist_esky -from setuptools import setup -import sys -import version -import os - - -# Include proper dirs -base_path = os.path.dirname(os.path.abspath(__file__)) -lib_dir = os.path.join(base_path, 'libs') - -sys.path.insert(0, base_path) -sys.path.insert(0, lib_dir) - - - -# Windows -if sys.platform == "win32": - import py2exe - - FREEZER = 'py2exe' - FREEZER_OPTIONS = dict( - compressed = 0, - optimize = 0, - bundle_files = 3, - dll_excludes = [ - 'MSVCP90.dll', - 'mswsock.dll', - 'powrprof.dll', - 'USP10.dll', - ], - packages = ['couchpotato', 'libs'], - includes = [ - 'telnetlib', - 'xml.etree.ElementTree', - 'xml.etree.cElementTree', - 'xml.dom', - 'xml.dom.minidom', - ], - ) - exeICON = 'icon.ico' - - -# OSX -elif sys.platform == "darwin": - import py2app - - FREEZER = 'py2app' - FREEZER_OPTIONS = dict( - argv_emulation = False, - iconfile = 'icon.icns', - plist = dict( - LSUIElement = True, - ), - packages = ['couchpotato', 'libs'], - includes = [ - 'telnetlib', - 'xml.etree.ElementTree', - 'xml.etree.cElementTree', - 'xml.dom', - 'xml.dom.minidom', - ], - ) - exeICON = None - -# Common -NAME = "CouchPotato" -APP = [bdist_esky.Executable("CouchPotato.py", gui_only = True, icon = exeICON,)] -DATA_FILES = ['icon.ico'] -ESKY_OPTIONS = dict( - freezer_module = FREEZER, - freezer_options = FREEZER_OPTIONS, - bundle_msvcrt = True, -) - - -# Build the app and the esky bundle -setup( - name = NAME, - scripts = APP, - version = version.VERSION, - data_files = DATA_FILES, - options = dict(bdist_esky = ESKY_OPTIONS), -) - - diff --git a/version.py b/version.py deleted file mode 100644 index f424186..0000000 --- a/version.py +++ /dev/null @@ -1 +0,0 @@ -VERSION = '0.5'