Browse Source

Code cleanup

pull/2742/merge
Ruud 11 years ago
parent
commit
799299c7cc
  1. 8
      CouchPotato.py
  2. 28
      couchpotato/__init__.py
  3. 10
      couchpotato/api.py
  4. 1
      couchpotato/core/_base/_core/__init__.py
  5. 2
      couchpotato/core/_base/_core/main.py
  6. 1
      couchpotato/core/_base/clientscript/__init__.py
  7. 6
      couchpotato/core/_base/clientscript/main.py
  8. 1
      couchpotato/core/_base/desktop/__init__.py
  9. 1
      couchpotato/core/_base/scheduler/__init__.py
  10. 1
      couchpotato/core/_base/updater/__init__.py
  11. 24
      couchpotato/core/_base/updater/main.py
  12. 1
      couchpotato/core/downloaders/blackhole/__init__.py
  13. 1
      couchpotato/core/downloaders/deluge/__init__.py
  14. 1
      couchpotato/core/downloaders/deluge/main.py
  15. 1
      couchpotato/core/downloaders/nzbget/__init__.py
  16. 8
      couchpotato/core/downloaders/nzbget/main.py
  17. 1
      couchpotato/core/downloaders/nzbvortex/__init__.py
  18. 8
      couchpotato/core/downloaders/nzbvortex/main.py
  19. 1
      couchpotato/core/downloaders/pneumatic/__init__.py
  20. 12
      couchpotato/core/downloaders/pneumatic/main.py
  21. 1
      couchpotato/core/downloaders/rtorrent/__init__.py
  22. 1
      couchpotato/core/downloaders/rtorrent/main.py
  23. 1
      couchpotato/core/downloaders/sabnzbd/__init__.py
  24. 4
      couchpotato/core/downloaders/sabnzbd/main.py
  25. 1
      couchpotato/core/downloaders/synology/__init__.py
  26. 1
      couchpotato/core/downloaders/synology/main.py
  27. 1
      couchpotato/core/downloaders/transmission/__init__.py
  28. 2
      couchpotato/core/downloaders/transmission/main.py
  29. 1
      couchpotato/core/downloaders/utorrent/__init__.py
  30. 2
      couchpotato/core/downloaders/utorrent/main.py
  31. 28
      couchpotato/core/event.py
  32. 14
      couchpotato/core/helpers/encoding.py
  33. 1
      couchpotato/core/helpers/request.py
  34. 3
      couchpotato/core/helpers/rss.py
  35. 42
      couchpotato/core/helpers/variable.py
  36. 3
      couchpotato/core/logger.py
  37. 4
      couchpotato/core/media/__init__.py
  38. 1
      couchpotato/core/media/_base/media/__init__.py
  39. 3
      couchpotato/core/media/_base/media/main.py
  40. 1
      couchpotato/core/media/_base/search/__init__.py
  41. 1
      couchpotato/core/media/_base/searcher/__init__.py
  42. 4
      couchpotato/core/media/_base/searcher/base.py
  43. 4
      couchpotato/core/media/_base/searcher/main.py
  44. 1
      couchpotato/core/media/movie/_base/__init__.py
  45. 1
      couchpotato/core/media/movie/_base/main.py
  46. 1
      couchpotato/core/media/movie/library/movie/__init__.py
  47. 2
      couchpotato/core/media/movie/library/movie/main.py
  48. 1
      couchpotato/core/media/movie/searcher/__init__.py
  49. 4
      couchpotato/core/media/movie/searcher/main.py
  50. 1
      couchpotato/core/media/movie/suggestion/__init__.py
  51. 2
      couchpotato/core/media/movie/suggestion/main.py
  52. 1
      couchpotato/core/migration/versions/002_Movie_category.py
  53. 1
      couchpotato/core/notifications/boxcar/__init__.py
  54. 1
      couchpotato/core/notifications/core/__init__.py
  55. 1
      couchpotato/core/notifications/core/main.py
  56. 1
      couchpotato/core/notifications/email/__init__.py
  57. 2
      couchpotato/core/notifications/email/main.py
  58. 1
      couchpotato/core/notifications/growl/__init__.py
  59. 2
      couchpotato/core/notifications/growl/main.py
  60. 1
      couchpotato/core/notifications/nmj/__init__.py
  61. 7
      couchpotato/core/notifications/nmj/main.py
  62. 1
      couchpotato/core/notifications/notifymyandroid/__init__.py
  63. 1
      couchpotato/core/notifications/notifymywp/__init__.py
  64. 3
      couchpotato/core/notifications/notifymywp/main.py
  65. 1
      couchpotato/core/notifications/plex/__init__.py
  66. 7
      couchpotato/core/notifications/plex/main.py
  67. 1
      couchpotato/core/notifications/prowl/__init__.py
  68. 2
      couchpotato/core/notifications/prowl/main.py
  69. 1
      couchpotato/core/notifications/pushalot/__init__.py
  70. 1
      couchpotato/core/notifications/pushalot/main.py
  71. 1
      couchpotato/core/notifications/pushbullet/__init__.py
  72. 1
      couchpotato/core/notifications/pushover/__init__.py
  73. 6
      couchpotato/core/notifications/pushover/main.py
  74. 1
      couchpotato/core/notifications/synoindex/__init__.py
  75. 2
      couchpotato/core/notifications/synoindex/main.py
  76. 1
      couchpotato/core/notifications/toasty/__init__.py
  77. 1
      couchpotato/core/notifications/toasty/main.py
  78. 1
      couchpotato/core/notifications/trakt/__init__.py
  79. 1
      couchpotato/core/notifications/trakt/main.py
  80. 1
      couchpotato/core/notifications/twitter/__init__.py
  81. 2
      couchpotato/core/notifications/twitter/main.py
  82. 1
      couchpotato/core/notifications/xbmc/__init__.py
  83. 3
      couchpotato/core/notifications/xbmc/main.py
  84. 1
      couchpotato/core/notifications/xmpp/__init__.py
  85. 1
      couchpotato/core/plugins/automation/__init__.py
  86. 9
      couchpotato/core/plugins/base.py
  87. 1
      couchpotato/core/plugins/browser/__init__.py
  88. 2
      couchpotato/core/plugins/browser/main.py
  89. 1
      couchpotato/core/plugins/category/__init__.py
  90. 2
      couchpotato/core/plugins/category/main.py
  91. 1
      couchpotato/core/plugins/custom/__init__.py
  92. 1
      couchpotato/core/plugins/dashboard/__init__.py
  93. 2
      couchpotato/core/plugins/dashboard/main.py
  94. 1
      couchpotato/core/plugins/file/__init__.py
  95. 1
      couchpotato/core/plugins/file/main.py
  96. 1
      couchpotato/core/plugins/log/__init__.py
  97. 2
      couchpotato/core/plugins/log/main.py
  98. 1
      couchpotato/core/plugins/manage/__init__.py
  99. 1
      couchpotato/core/plugins/manage/main.py
  100. 1
      couchpotato/core/plugins/profile/__init__.py

8
CouchPotato.py

@ -132,14 +132,14 @@ if __name__ == '__main__':
pass pass
except SystemExit: except SystemExit:
raise raise
except socket.error as (nr, msg): except socket.error as e:
# log when socket receives SIGINT, but continue. # log when socket receives SIGINT, but continue.
# previous code would have skipped over other types of IO errors too. # previous code would have skipped over other types of IO errors too.
if nr != 4: if nr != 4:
try: try:
l.log.critical(traceback.format_exc()) l.log.critical(traceback.format_exc())
except: except:
print traceback.format_exc() print(traceback.format_exc())
raise raise
except: except:
try: try:
@ -148,7 +148,7 @@ if __name__ == '__main__':
if l: if l:
l.log.critical(traceback.format_exc()) l.log.critical(traceback.format_exc())
else: else:
print traceback.format_exc() print(traceback.format_exc())
except: except:
print traceback.format_exc() print(traceback.format_exc())
raise raise

28
couchpotato/__init__.py

@ -9,13 +9,12 @@ import os
import time import time
import traceback import traceback
log = CPLog(__name__)
log = CPLog(__name__)
views = {} views = {}
template_loader = template.Loader(os.path.join(os.path.dirname(__file__), 'templates')) template_loader = template.Loader(os.path.join(os.path.dirname(__file__), 'templates'))
class BaseHandler(RequestHandler): class BaseHandler(RequestHandler):
def get_current_user(self): def get_current_user(self):
@ -24,9 +23,10 @@ class BaseHandler(RequestHandler):
if username and password: if username and password:
return self.get_secure_cookie('user') return self.get_secure_cookie('user')
else: # Login when no username or password are set else: # Login when no username or password are set
return True return True
# Main web handler # Main web handler
class WebHandler(BaseHandler): class WebHandler(BaseHandler):
@ -43,9 +43,11 @@ class WebHandler(BaseHandler):
log.error("Failed doing web request '%s': %s", (route, traceback.format_exc())) log.error("Failed doing web request '%s': %s", (route, traceback.format_exc()))
self.write({'success': False, 'error': 'Failed returning results'}) self.write({'success': False, 'error': 'Failed returning results'})
def addView(route, func, static = False): def addView(route, func, static = False):
views[route] = func views[route] = func
def get_session(engine = None): def get_session(engine = None):
return Env.getSession(engine) return Env.getSession(engine)
@ -55,6 +57,7 @@ def index():
return template_loader.load('index.html').generate(sep = os.sep, fireEvent = fireEvent, Env = Env) return template_loader.load('index.html').generate(sep = os.sep, fireEvent = fireEvent, Env = Env)
addView('', index) addView('', index)
# API docs # API docs
def apiDocs(): def apiDocs():
routes = [] routes = []
@ -70,21 +73,22 @@ def apiDocs():
addView('docs', apiDocs) addView('docs', apiDocs)
# Make non basic auth option to get api key # Make non basic auth option to get api key
class KeyHandler(RequestHandler): class KeyHandler(RequestHandler):
def get(self, *args, **kwargs): def get(self, *args, **kwargs):
api = None api_key = None
try: try:
username = Env.setting('username') username = Env.setting('username')
password = Env.setting('password') password = Env.setting('password')
if (self.get_argument('u') == md5(username) or not username) and (self.get_argument('p') == password or not password): if (self.get_argument('u') == md5(username) or not username) and (self.get_argument('p') == password or not password):
api = Env.setting('api_key') api_key = Env.setting('api_key')
self.write({ self.write({
'success': api is not None, 'success': api_key is not None,
'api_key': api 'api_key': api_key
}) })
except: except:
log.error('Failed doing key request: %s', (traceback.format_exc())) log.error('Failed doing key request: %s', (traceback.format_exc()))
@ -102,20 +106,21 @@ class LoginHandler(BaseHandler):
def post(self, *args, **kwargs): def post(self, *args, **kwargs):
api = None api_key = None
username = Env.setting('username') username = Env.setting('username')
password = Env.setting('password') password = Env.setting('password')
if (self.get_argument('username') == username or not username) and (md5(self.get_argument('password')) == password or not password): if (self.get_argument('username') == username or not username) and (md5(self.get_argument('password')) == password or not password):
api = Env.setting('api_key') api_key = Env.setting('api_key')
if api: if api_key:
remember_me = tryInt(self.get_argument('remember_me', default = 0)) remember_me = tryInt(self.get_argument('remember_me', default = 0))
self.set_secure_cookie('user', api, expires_days = 30 if remember_me > 0 else None) self.set_secure_cookie('user', api_key, expires_days = 30 if remember_me > 0 else None)
self.redirect(Env.get('web_base')) self.redirect(Env.get('web_base'))
class LogoutHandler(BaseHandler): class LogoutHandler(BaseHandler):
def get(self, *args, **kwargs): def get(self, *args, **kwargs):
@ -136,4 +141,3 @@ def page_not_found(rh):
rh.set_status(404) rh.set_status(404)
rh.write('Wrong API key used') rh.write('Wrong API key used')

10
couchpotato/api.py

@ -20,6 +20,7 @@ api_nonblock = {}
api_docs = {} api_docs = {}
api_docs_missing = [] api_docs_missing = []
def run_async(func): def run_async(func):
@wraps(func) @wraps(func)
def async_func(*args, **kwargs): def async_func(*args, **kwargs):
@ -29,6 +30,7 @@ def run_async(func):
return async_func return async_func
# NonBlock API handler # NonBlock API handler
class NonBlockHandler(RequestHandler): class NonBlockHandler(RequestHandler):
@ -61,6 +63,7 @@ class NonBlockHandler(RequestHandler):
self.stopper = None self.stopper = None
def addNonBlockApiView(route, func_tuple, docs = None, **kwargs): def addNonBlockApiView(route, func_tuple, docs = None, **kwargs):
api_nonblock[route] = func_tuple api_nonblock[route] = func_tuple
@ -69,6 +72,7 @@ def addNonBlockApiView(route, func_tuple, docs = None, **kwargs):
else: else:
api_docs_missing.append(route) api_docs_missing.append(route)
# Blocking API handler # Blocking API handler
class ApiHandler(RequestHandler): class ApiHandler(RequestHandler):
@ -98,11 +102,12 @@ class ApiHandler(RequestHandler):
@run_async @run_async
def run_handler(callback): def run_handler(callback):
try: try:
result = api[route](**kwargs) res = api[route](**kwargs)
callback(result) callback(res)
except: except:
log.error('Failed doing api request "%s": %s', (route, traceback.format_exc())) log.error('Failed doing api request "%s": %s', (route, traceback.format_exc()))
callback({'success': False, 'error': 'Failed returning results'}) callback({'success': False, 'error': 'Failed returning results'})
result = yield tornado.gen.Task(run_handler) result = yield tornado.gen.Task(run_handler)
# Check JSONP callback # Check JSONP callback
@ -122,6 +127,7 @@ class ApiHandler(RequestHandler):
api_locks[route].release() api_locks[route].release()
def addApiView(route, func, static = False, docs = None, **kwargs): def addApiView(route, func, static = False, docs = None, **kwargs):
if static: func(route) if static: func(route)

1
couchpotato/core/_base/_core/__init__.py

@ -1,6 +1,7 @@
from .main import Core from .main import Core
from uuid import uuid4 from uuid import uuid4
def start(): def start():
return Core() return Core()

2
couchpotato/core/_base/_core/main.py

@ -117,7 +117,7 @@ class Core(Plugin):
if len(still_running) == 0: if len(still_running) == 0:
break break
elif starttime < time.time() - 30: # Always force break after 30s wait elif starttime < time.time() - 30: # Always force break after 30s wait
break break
running = list(set(still_running) - set(self.ignore_restart)) running = list(set(still_running) - set(self.ignore_restart))

1
couchpotato/core/_base/clientscript/__init__.py

@ -1,5 +1,6 @@
from .main import ClientScript from .main import ClientScript
def start(): def start():
return ClientScript() return ClientScript()

6
couchpotato/core/_base/clientscript/main.py

@ -53,9 +53,9 @@ class ClientScript(Plugin):
} }
urls = {'style': {}, 'script': {}, } urls = {'style': {}, 'script': {}}
minified = {'style': {}, 'script': {}, } minified = {'style': {}, 'script': {}}
paths = {'style': {}, 'script': {}, } paths = {'style': {}, 'script': {}}
comment = { comment = {
'style': '/*** %s:%d ***/\n', 'style': '/*** %s:%d ***/\n',
'script': '// %s:%d\n' 'script': '// %s:%d\n'

1
couchpotato/core/_base/desktop/__init__.py

@ -1,5 +1,6 @@
from .main import Desktop from .main import Desktop
def start(): def start():
return Desktop() return Desktop()

1
couchpotato/core/_base/scheduler/__init__.py

@ -1,5 +1,6 @@
from .main import Scheduler from .main import Scheduler
def start(): def start():
return Scheduler() return Scheduler()

1
couchpotato/core/_base/updater/__init__.py

@ -2,6 +2,7 @@ from .main import Updater
from couchpotato.environment import Env from couchpotato.environment import Env
import os import os
def start(): def start():
return Updater() return Updater()

24
couchpotato/core/_base/updater/main.py

@ -63,7 +63,7 @@ class Updater(Plugin):
fireEvent('schedule.remove', 'updater.check', single = True) fireEvent('schedule.remove', 'updater.check', single = True)
if self.isEnabled(): if self.isEnabled():
fireEvent('schedule.interval', 'updater.check', self.autoUpdate, hours = 6) fireEvent('schedule.interval', 'updater.check', self.autoUpdate, hours = 6)
self.autoUpdate() # Check after enabling self.autoUpdate() # Check after enabling
def autoUpdate(self): def autoUpdate(self):
if self.isEnabled() and self.check() and self.conf('automatic') and not self.updater.update_failed: if self.isEnabled() and self.check() and self.conf('automatic') and not self.updater.update_failed:
@ -151,6 +151,9 @@ class BaseUpdater(Plugin):
'branch': self.branch, 'branch': self.branch,
} }
def getVersion(self):
pass
def check(self): def check(self):
pass pass
@ -179,7 +182,6 @@ class BaseUpdater(Plugin):
log.error('Couldn\'t remove empty directory %s: %s', (full_path, traceback.format_exc())) log.error('Couldn\'t remove empty directory %s: %s', (full_path, traceback.format_exc()))
class GitUpdater(BaseUpdater): class GitUpdater(BaseUpdater):
def __init__(self, git_command): def __init__(self, git_command):
@ -206,7 +208,7 @@ class GitUpdater(BaseUpdater):
if not self.version: if not self.version:
try: try:
output = self.repo.getHead() # Yes, please output = self.repo.getHead() # Yes, please
log.debug('Git version output: %s', output.hash) log.debug('Git version output: %s', output.hash)
self.version = { self.version = {
'repr': 'git:(%s:%s % s) %s (%s)' % (self.repo_user, self.repo_name, self.branch, output.hash[:8], datetime.fromtimestamp(output.getDate())), 'repr': 'git:(%s:%s % s) %s (%s)' % (self.repo_user, self.repo_name, self.branch, output.hash[:8], datetime.fromtimestamp(output.getDate())),
@ -214,7 +216,7 @@ class GitUpdater(BaseUpdater):
'date': output.getDate(), 'date': output.getDate(),
'type': 'git', 'type': 'git',
} }
except Exception, e: except Exception as e:
log.error('Failed using GIT updater, running from source, you need to have GIT installed. %s', e) log.error('Failed using GIT updater, running from source, you need to have GIT installed. %s', e)
return 'No GIT' return 'No GIT'
@ -250,7 +252,6 @@ class GitUpdater(BaseUpdater):
return False return False
class SourceUpdater(BaseUpdater): class SourceUpdater(BaseUpdater):
def __init__(self): def __init__(self):
@ -276,9 +277,9 @@ class SourceUpdater(BaseUpdater):
# Extract # Extract
if download_data.get('type') == 'zip': if download_data.get('type') == 'zip':
zip = zipfile.ZipFile(destination) zip_file = zipfile.ZipFile(destination)
zip.extractall(extracted_path) zip_file.extractall(extracted_path)
zip.close() zip_file.close()
else: else:
tar = tarfile.open(destination) tar = tarfile.open(destination)
tar.extractall(path = extracted_path) tar.extractall(path = extracted_path)
@ -345,7 +346,6 @@ class SourceUpdater(BaseUpdater):
return True return True
def removeDir(self, path): def removeDir(self, path):
try: try:
if os.path.isdir(path): if os.path.isdir(path):
@ -366,7 +366,7 @@ class SourceUpdater(BaseUpdater):
self.version = output self.version = output
self.version['type'] = 'source' self.version['type'] = 'source'
self.version['repr'] = 'source:(%s:%s % s) %s (%s)' % (self.repo_user, self.repo_name, self.branch, output.get('hash', '')[:8], datetime.fromtimestamp(output.get('date', 0))) self.version['repr'] = 'source:(%s:%s % s) %s (%s)' % (self.repo_user, self.repo_name, self.branch, output.get('hash', '')[:8], datetime.fromtimestamp(output.get('date', 0)))
except Exception, e: except Exception as e:
log.error('Failed using source updater. %s', e) log.error('Failed using source updater. %s', e)
return {} return {}
@ -396,7 +396,7 @@ class SourceUpdater(BaseUpdater):
return { return {
'hash': commit['sha'], 'hash': commit['sha'],
'date': int(time.mktime(parse(commit['commit']['committer']['date']).timetuple())), 'date': int(time.mktime(parse(commit['commit']['committer']['date']).timetuple())),
} }
except: except:
log.error('Failed getting latest request from github: %s', traceback.format_exc()) log.error('Failed getting latest request from github: %s', traceback.format_exc())
@ -441,7 +441,7 @@ class DesktopUpdater(BaseUpdater):
if latest and latest != current_version.get('hash'): if latest and latest != current_version.get('hash'):
self.update_version = { self.update_version = {
'hash': latest, 'hash': latest,
'date': None, 'date': None,
'changelog': self.desktop._changelogURL, 'changelog': self.desktop._changelogURL,
} }

1
couchpotato/core/downloaders/blackhole/__init__.py

@ -1,6 +1,7 @@
from .main import Blackhole from .main import Blackhole
from couchpotato.core.helpers.variable import getDownloadDir from couchpotato.core.helpers.variable import getDownloadDir
def start(): def start():
return Blackhole() return Blackhole()

1
couchpotato/core/downloaders/deluge/__init__.py

@ -1,5 +1,6 @@
from .main import Deluge from .main import Deluge
def start(): def start():
return Deluge() return Deluge()

1
couchpotato/core/downloaders/deluge/main.py

@ -157,6 +157,7 @@ class Deluge(Downloader):
log.debug('Requesting Deluge to remove the torrent %s%s.', (release_download['name'], ' and cleanup the downloaded files' if delete_files else '')) log.debug('Requesting Deluge to remove the torrent %s%s.', (release_download['name'], ' and cleanup the downloaded files' if delete_files else ''))
return self.drpc.remove_torrent(release_download['id'], remove_local_data = delete_files) return self.drpc.remove_torrent(release_download['id'], remove_local_data = delete_files)
class DelugeRPC(object): class DelugeRPC(object):
host = 'localhost' host = 'localhost'

1
couchpotato/core/downloaders/nzbget/__init__.py

@ -1,5 +1,6 @@
from .main import NZBGet from .main import NZBGet
def start(): def start():
return NZBGet() return NZBGet()

8
couchpotato/core/downloaders/nzbget/main.py

@ -42,7 +42,7 @@ class NZBGet(Downloader):
except socket.error: except socket.error:
log.error('NZBGet is not responding. Please ensure that NZBGet is running and host setting is correct.') log.error('NZBGet is not responding. Please ensure that NZBGet is running and host setting is correct.')
return False return False
except xmlrpclib.ProtocolError, e: except xmlrpclib.ProtocolError as e:
if e.errcode == 401: if e.errcode == 401:
log.error('Password is incorrect.') log.error('Password is incorrect.')
else: else:
@ -56,7 +56,7 @@ class NZBGet(Downloader):
if xml_response: if xml_response:
log.info('NZB sent successfully to NZBGet') log.info('NZB sent successfully to NZBGet')
nzb_id = md5(data['url']) # about as unique as they come ;) nzb_id = md5(data['url']) # about as unique as they come ;)
couchpotato_id = "couchpotato=" + nzb_id couchpotato_id = "couchpotato=" + nzb_id
groups = rpc.listgroups() groups = rpc.listgroups()
file_id = [item['LastID'] for item in groups if item['NZBFilename'] == nzb_name] file_id = [item['LastID'] for item in groups if item['NZBFilename'] == nzb_name]
@ -83,7 +83,7 @@ class NZBGet(Downloader):
except socket.error: except socket.error:
log.error('NZBGet is not responding. Please ensure that NZBGet is running and host setting is correct.') log.error('NZBGet is not responding. Please ensure that NZBGet is running and host setting is correct.')
return [] return []
except xmlrpclib.ProtocolError, e: except xmlrpclib.ProtocolError as e:
if e.errcode == 401: if e.errcode == 401:
log.error('Password is incorrect.') log.error('Password is incorrect.')
else: else:
@ -169,7 +169,7 @@ class NZBGet(Downloader):
except socket.error: except socket.error:
log.error('NZBGet is not responding. Please ensure that NZBGet is running and host setting is correct.') log.error('NZBGet is not responding. Please ensure that NZBGet is running and host setting is correct.')
return False return False
except xmlrpclib.ProtocolError, e: except xmlrpclib.ProtocolError as e:
if e.errcode == 401: if e.errcode == 401:
log.error('Password is incorrect.') log.error('Password is incorrect.')
else: else:

1
couchpotato/core/downloaders/nzbvortex/__init__.py

@ -1,5 +1,6 @@
from .main import NZBVortex from .main import NZBVortex
def start(): def start():
return NZBVortex() return NZBVortex()

8
couchpotato/core/downloaders/nzbvortex/main.py

@ -62,7 +62,7 @@ class NZBVortex(Downloader):
'name': nzb['uiTitle'], 'name': nzb['uiTitle'],
'status': status, 'status': status,
'original_status': nzb['state'], 'original_status': nzb['state'],
'timeleft':-1, 'timeleft': -1,
'folder': sp(nzb['destinationPath']), 'folder': sp(nzb['destinationPath']),
}) })
@ -102,7 +102,6 @@ class NZBVortex(Downloader):
log.error('Login failed, please check you api-key') log.error('Login failed, please check you api-key')
return False return False
def call(self, call, parameters = None, repeat = False, auth = True, *args, **kwargs): def call(self, call, parameters = None, repeat = False, auth = True, *args, **kwargs):
# Login first # Login first
@ -123,7 +122,7 @@ class NZBVortex(Downloader):
if data: if data:
return json.loads(data) return json.loads(data)
except URLError, e: except URLError as e:
if hasattr(e, 'code') and e.code == 403: if hasattr(e, 'code') and e.code == 403:
# Try login and do again # Try login and do again
if not repeat: if not repeat:
@ -145,7 +144,7 @@ class NZBVortex(Downloader):
try: try:
data = self.urlopen(url, show_error = False) data = self.urlopen(url, show_error = False)
self.api_level = float(json.loads(data).get('apilevel')) self.api_level = float(json.loads(data).get('apilevel'))
except URLError, e: except URLError as e:
if hasattr(e, 'code') and e.code == 403: if hasattr(e, 'code') and e.code == 403:
log.error('This version of NZBVortex isn\'t supported. Please update to 2.8.6 or higher') log.error('This version of NZBVortex isn\'t supported. Please update to 2.8.6 or higher')
else: else:
@ -175,6 +174,7 @@ class HTTPSConnection(httplib.HTTPSConnection):
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version = ssl.PROTOCOL_TLSv1) self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, ssl_version = ssl.PROTOCOL_TLSv1)
class HTTPSHandler(urllib2.HTTPSHandler): class HTTPSHandler(urllib2.HTTPSHandler):
def https_open(self, req): def https_open(self, req):
return self.do_open(HTTPSConnection, req) return self.do_open(HTTPSConnection, req)

1
couchpotato/core/downloaders/pneumatic/__init__.py

@ -1,5 +1,6 @@
from .main import Pneumatic from .main import Pneumatic
def start(): def start():
return Pneumatic() return Pneumatic()

12
couchpotato/core/downloaders/pneumatic/main.py

@ -26,26 +26,26 @@ class Pneumatic(Downloader):
log.error('No nzb available!') log.error('No nzb available!')
return False return False
fullPath = os.path.join(directory, self.createFileName(data, filedata, media)) full_path = os.path.join(directory, self.createFileName(data, filedata, media))
try: try:
if not os.path.isfile(fullPath): if not os.path.isfile(full_path):
log.info('Downloading %s to %s.', (data.get('protocol'), fullPath)) log.info('Downloading %s to %s.', (data.get('protocol'), full_path))
with open(fullPath, 'wb') as f: with open(full_path, 'wb') as f:
f.write(filedata) f.write(filedata)
nzb_name = self.createNzbName(data, media) nzb_name = self.createNzbName(data, media)
strm_path = os.path.join(directory, nzb_name) strm_path = os.path.join(directory, nzb_name)
strm_file = open(strm_path + '.strm', 'wb') strm_file = open(strm_path + '.strm', 'wb')
strmContent = self.strm_syntax % (fullPath, nzb_name) strmContent = self.strm_syntax % (full_path, nzb_name)
strm_file.write(strmContent) strm_file.write(strmContent)
strm_file.close() strm_file.close()
return self.downloadReturnId('') return self.downloadReturnId('')
else: else:
log.info('File %s already exists.', fullPath) log.info('File %s already exists.', full_path)
return self.downloadReturnId('') return self.downloadReturnId('')
except: except:

1
couchpotato/core/downloaders/rtorrent/__init__.py

@ -1,5 +1,6 @@
from .main import rTorrent from .main import rTorrent
def start(): def start():
return rTorrent() return rTorrent()

1
couchpotato/core/downloaders/rtorrent/main.py

@ -111,7 +111,6 @@ class rTorrent(Downloader):
if self.conf('label'): if self.conf('label'):
torrent_params['label'] = self.conf('label') torrent_params['label'] = self.conf('label')
if not filedata and data.get('protocol') == 'torrent': if not filedata and data.get('protocol') == 'torrent':
log.error('Failed sending torrent, no data') log.error('Failed sending torrent, no data')
return False return False

1
couchpotato/core/downloaders/sabnzbd/__init__.py

@ -1,5 +1,6 @@
from .main import Sabnzbd from .main import Sabnzbd
def start(): def start():
return Sabnzbd() return Sabnzbd()

4
couchpotato/core/downloaders/sabnzbd/main.py

@ -166,8 +166,8 @@ class Sabnzbd(Downloader):
def call(self, request_params, use_json = True, **kwargs): def call(self, request_params, use_json = True, **kwargs):
url = cleanHost(self.conf('host'), ssl = self.conf('ssl')) + 'api?' + tryUrlencode(mergeDicts(request_params, { url = cleanHost(self.conf('host'), ssl = self.conf('ssl')) + 'api?' + tryUrlencode(mergeDicts(request_params, {
'apikey': self.conf('api_key'), 'apikey': self.conf('api_key'),
'output': 'json' 'output': 'json'
})) }))
data = self.urlopen(url, timeout = 60, show_error = False, headers = {'User-Agent': Env.getIdentifier()}, **kwargs) data = self.urlopen(url, timeout = 60, show_error = False, headers = {'User-Agent': Env.getIdentifier()}, **kwargs)

1
couchpotato/core/downloaders/synology/__init__.py

@ -1,5 +1,6 @@
from .main import Synology from .main import Synology
def start(): def start():
return Synology() return Synology()

1
couchpotato/core/downloaders/synology/main.py

@ -65,6 +65,7 @@ class Synology(Downloader):
return super(Synology, self).isEnabled(manual, data) and\ return super(Synology, self).isEnabled(manual, data) and\
((self.conf('use_for') in for_protocol)) ((self.conf('use_for') in for_protocol))
class SynologyRPC(object): class SynologyRPC(object):
"""SynologyRPC lite library""" """SynologyRPC lite library"""

1
couchpotato/core/downloaders/transmission/__init__.py

@ -1,5 +1,6 @@
from .main import Transmission from .main import Transmission
def start(): def start():
return Transmission() return Transmission()

2
couchpotato/core/downloaders/transmission/main.py

@ -105,7 +105,7 @@ class Transmission(Downloader):
for torrent in queue['torrents']: for torrent in queue['torrents']:
if torrent['hashString'] in ids: if torrent['hashString'] in ids:
log.debug('name=%s / id=%s / downloadDir=%s / hashString=%s / percentDone=%s / status=%s / isStalled=%s / eta=%s / uploadRatio=%s / isFinished=%s / incomplete-dir-enabled=%s / incomplete-dir=%s', log.debug('name=%s / id=%s / downloadDir=%s / hashString=%s / percentDone=%s / status=%s / isStalled=%s / eta=%s / uploadRatio=%s / isFinished=%s / incomplete-dir-enabled=%s / incomplete-dir=%s',
(torrent['name'], torrent['id'], torrent['downloadDir'], torrent['hashString'], torrent['percentDone'], torrent['status'], torrent.get('isStalled', 'N/A'), torrent['eta'], torrent['uploadRatio'], torrent['isFinished'], session['incomplete-dir-enabled'], session['incomplete-dir'])) (torrent['name'], torrent['id'], torrent['downloadDir'], torrent['hashString'], torrent['percentDone'], torrent['status'], torrent.get('isStalled', 'N/A'), torrent['eta'], torrent['uploadRatio'], torrent['isFinished'], session['incomplete-dir-enabled'], session['incomplete-dir']))
status = 'busy' status = 'busy'
if torrent.get('isStalled') and not torrent['percentDone'] == 1 and self.conf('stalled_as_failed'): if torrent.get('isStalled') and not torrent['percentDone'] == 1 and self.conf('stalled_as_failed'):

1
couchpotato/core/downloaders/utorrent/__init__.py

@ -1,5 +1,6 @@
from .main import uTorrent from .main import uTorrent
def start(): def start():
return uTorrent() return uTorrent()

2
couchpotato/core/downloaders/utorrent/main.py

@ -66,7 +66,7 @@ class uTorrent(Downloader):
new_settings['seed_prio_limitul_flag'] = True new_settings['seed_prio_limitul_flag'] = True
log.info('Updated uTorrent settings to set a torrent to complete after it the seeding requirements are met.') log.info('Updated uTorrent settings to set a torrent to complete after it the seeding requirements are met.')
if settings.get('bt.read_only_on_complete'): #This doesn't work as this option seems to be not available through the api. Mitigated with removeReadOnly function if settings.get('bt.read_only_on_complete'): #This doesn't work as this option seems to be not available through the api. Mitigated with removeReadOnly function
new_settings['bt.read_only_on_complete'] = False new_settings['bt.read_only_on_complete'] = False
log.info('Updated uTorrent settings to not set the files to read only after completing.') log.info('Updated uTorrent settings to not set the files to read only after completing.')

28
couchpotato/core/event.py

@ -7,6 +7,7 @@ import traceback
log = CPLog(__name__) log = CPLog(__name__)
events = {} events = {}
def runHandler(name, handler, *args, **kwargs): def runHandler(name, handler, *args, **kwargs):
try: try:
return handler(*args, **kwargs) return handler(*args, **kwargs)
@ -14,6 +15,7 @@ def runHandler(name, handler, *args, **kwargs):
from couchpotato.environment import Env from couchpotato.environment import Env
log.error('Error in event "%s", that wasn\'t caught: %s%s', (name, traceback.format_exc(), Env.all() if not Env.get('dev') else '')) log.error('Error in event "%s", that wasn\'t caught: %s%s', (name, traceback.format_exc(), Env.all() if not Env.get('dev') else ''))
def addEvent(name, handler, priority = 100): def addEvent(name, handler, priority = 100):
if not events.get(name): if not events.get(name):
@ -48,22 +50,24 @@ def addEvent(name, handler, priority = 100):
'priority': priority, 'priority': priority,
}) })
def removeEvent(name, handler): def removeEvent(name, handler):
e = events[name] e = events[name]
e -= handler e -= handler
def fireEvent(name, *args, **kwargs): def fireEvent(name, *args, **kwargs):
if not events.has_key(name): return if name not in events: return
#log.debug('Firing event %s', name) #log.debug('Firing event %s', name)
try: try:
options = { options = {
'is_after_event': False, # Fire after event 'is_after_event': False, # Fire after event
'on_complete': False, # onComplete event 'on_complete': False, # onComplete event
'single': False, # Return single handler 'single': False, # Return single handler
'merge': False, # Merge items 'merge': False, # Merge items
'in_order': False, # Fire them in specific order, waits for the other to finish 'in_order': False, # Fire them in specific order, waits for the other to finish
} }
# Do options # Do options
@ -101,11 +105,14 @@ def fireEvent(name, *args, **kwargs):
# Fire # Fire
result = e(*args, **kwargs) result = e(*args, **kwargs)
result_keys = result.keys()
result_keys.sort(natcmp)
if options['single'] and not options['merge']: if options['single'] and not options['merge']:
results = None results = None
# Loop over results, stop when first not None result is found. # Loop over results, stop when first not None result is found.
for r_key in sorted(result.iterkeys(), cmp = natcmp): for r_key in result_keys:
r = result[r_key] r = result[r_key]
if r[0] is True and r[1] is not None: if r[0] is True and r[1] is not None:
results = r[1] results = r[1]
@ -117,7 +124,7 @@ def fireEvent(name, *args, **kwargs):
else: else:
results = [] results = []
for r_key in sorted(result.iterkeys(), cmp = natcmp): for r_key in result_keys:
r = result[r_key] r = result[r_key]
if r[0] == True and r[1]: if r[0] == True and r[1]:
results.append(r[1]) results.append(r[1])
@ -160,18 +167,21 @@ def fireEvent(name, *args, **kwargs):
except Exception: except Exception:
log.error('%s: %s', (name, traceback.format_exc())) log.error('%s: %s', (name, traceback.format_exc()))
def fireEventAsync(*args, **kwargs): def fireEventAsync(*args, **kwargs):
try: try:
t = threading.Thread(target = fireEvent, args = args, kwargs = kwargs) t = threading.Thread(target = fireEvent, args = args, kwargs = kwargs)
t.setDaemon(True) t.setDaemon(True)
t.start() t.start()
return True return True
except Exception, e: except Exception as e:
log.error('%s: %s', (args[0], e)) log.error('%s: %s', (args[0], e))
def errorHandler(error): def errorHandler(error):
etype, value, tb = error etype, value, tb = error
log.error(''.join(traceback.format_exception(etype, value, tb))) log.error(''.join(traceback.format_exception(etype, value, tb)))
def getEvent(name): def getEvent(name):
return events[name] return events[name]

14
couchpotato/core/helpers/encoding.py

@ -11,16 +11,18 @@ log = CPLog(__name__)
def toSafeString(original): def toSafeString(original):
valid_chars = "-_.() %s%s" % (ascii_letters, digits) valid_chars = "-_.() %s%s" % (ascii_letters, digits)
cleanedFilename = unicodedata.normalize('NFKD', toUnicode(original)).encode('ASCII', 'ignore') cleaned_filename = unicodedata.normalize('NFKD', toUnicode(original)).encode('ASCII', 'ignore')
valid_string = ''.join(c for c in cleanedFilename if c in valid_chars) valid_string = ''.join(c for c in cleaned_filename if c in valid_chars)
return ' '.join(valid_string.split()) return ' '.join(valid_string.split())
def simplifyString(original): def simplifyString(original):
string = stripAccents(original.lower()) string = stripAccents(original.lower())
string = toSafeString(' '.join(re.split('\W+', string))) string = toSafeString(' '.join(re.split('\W+', string)))
split = re.split('\W+|_', string.lower()) split = re.split('\W+|_', string.lower())
return toUnicode(' '.join(split)) return toUnicode(' '.join(split))
def toUnicode(original, *args): def toUnicode(original, *args):
try: try:
if isinstance(original, unicode): if isinstance(original, unicode):
@ -38,16 +40,18 @@ def toUnicode(original, *args):
ascii_text = str(original).encode('string_escape') ascii_text = str(original).encode('string_escape')
return toUnicode(ascii_text) return toUnicode(ascii_text)
def ss(original, *args): def ss(original, *args):
u_original = toUnicode(original, *args) u_original = toUnicode(original, *args)
try: try:
from couchpotato.environment import Env from couchpotato.environment import Env
return u_original.encode(Env.get('encoding')) return u_original.encode(Env.get('encoding'))
except Exception, e: except Exception as e:
log.debug('Failed ss encoding char, force UTF8: %s', e) log.debug('Failed ss encoding char, force UTF8: %s', e)
return u_original.encode('UTF-8') return u_original.encode('UTF-8')
def sp(path, *args): def sp(path, *args):
# Standardise encoding, normalise case, path and strip trailing '/' or '\' # Standardise encoding, normalise case, path and strip trailing '/' or '\'
@ -73,6 +77,7 @@ def sp(path, *args):
return path return path
def ek(original, *args): def ek(original, *args):
if isinstance(original, (str, unicode)): if isinstance(original, (str, unicode)):
try: try:
@ -83,6 +88,7 @@ def ek(original, *args):
return original return original
def isInt(value): def isInt(value):
try: try:
int(value) int(value)
@ -90,9 +96,11 @@ def isInt(value):
except ValueError: except ValueError:
return False return False
def stripAccents(s): def stripAccents(s):
return ''.join((c for c in unicodedata.normalize('NFD', toUnicode(s)) if unicodedata.category(c) != 'Mn')) return ''.join((c for c in unicodedata.normalize('NFD', toUnicode(s)) if unicodedata.category(c) != 'Mn'))
def tryUrlencode(s): def tryUrlencode(s):
new = u'' new = u''
if isinstance(s, dict): if isinstance(s, dict):

1
couchpotato/core/helpers/request.py

@ -37,6 +37,7 @@ def getParams(params):
return dictToList(temp) return dictToList(temp)
def dictToList(params): def dictToList(params):
if type(params) is dict: if type(params) is dict:

3
couchpotato/core/helpers/rss.py

@ -3,6 +3,7 @@ import xml.etree.ElementTree as XMLTree
log = CPLog(__name__) log = CPLog(__name__)
class RSS(object): class RSS(object):
def getTextElements(self, xml, path): def getTextElements(self, xml, path):
@ -46,6 +47,6 @@ class RSS(object):
def getItems(self, data, path = 'channel/item'): def getItems(self, data, path = 'channel/item'):
try: try:
return XMLTree.parse(data).findall(path) return XMLTree.parse(data).findall(path)
except Exception, e: except Exception as e:
log.error('Error parsing RSS. %s', e) log.error('Error parsing RSS. %s', e)
return [] return []

42
couchpotato/core/helpers/variable.py

@ -11,8 +11,10 @@ import sys
log = CPLog(__name__) log = CPLog(__name__)
def fnEscape(pattern): def fnEscape(pattern):
return pattern.replace('[','[[').replace(']','[]]').replace('[[','[[]') return pattern.replace('[', '[[').replace(']', '[]]').replace('[[', '[[]')
def link(src, dst): def link(src, dst):
if os.name == 'nt': if os.name == 'nt':
@ -21,6 +23,7 @@ def link(src, dst):
else: else:
os.link(src, dst) os.link(src, dst)
def symlink(src, dst): def symlink(src, dst):
if os.name == 'nt': if os.name == 'nt':
import ctypes import ctypes
@ -28,6 +31,7 @@ def symlink(src, dst):
else: else:
os.symlink(src, dst) os.symlink(src, dst)
def getUserDir(): def getUserDir():
try: try:
import pwd import pwd
@ -37,6 +41,7 @@ def getUserDir():
return os.path.expanduser('~') return os.path.expanduser('~')
def getDownloadDir(): def getDownloadDir():
user_dir = getUserDir() user_dir = getUserDir()
@ -49,6 +54,7 @@ def getDownloadDir():
return user_dir return user_dir
def getDataDir(): def getDataDir():
# Windows # Windows
@ -68,8 +74,10 @@ def getDataDir():
# Linux # Linux
return os.path.join(user_dir, '.couchpotato') return os.path.join(user_dir, '.couchpotato')
def isDict(object):
return isinstance(object, dict) def isDict(obj):
return isinstance(obj, dict)
def mergeDicts(a, b, prepend_list = False): def mergeDicts(a, b, prepend_list = False):
assert isDict(a), isDict(b) assert isDict(a), isDict(b)
@ -91,6 +99,7 @@ def mergeDicts(a, b, prepend_list = False):
current_dst[key] = current_src[key] current_dst[key] = current_src[key]
return dst return dst
def removeListDuplicates(seq): def removeListDuplicates(seq):
checked = [] checked = []
for e in seq: for e in seq:
@ -98,26 +107,32 @@ def removeListDuplicates(seq):
checked.append(e) checked.append(e)
return checked return checked
def flattenList(l): def flattenList(l):
if isinstance(l, list): if isinstance(l, list):
return sum(map(flattenList, l)) return sum(map(flattenList, l))
else: else:
return l return l
def md5(text): def md5(text):
return hashlib.md5(ss(text)).hexdigest() return hashlib.md5(ss(text)).hexdigest()
def sha1(text): def sha1(text):
return hashlib.sha1(text).hexdigest() return hashlib.sha1(text).hexdigest()
def isLocalIP(ip): def isLocalIP(ip):
ip = ip.lstrip('htps:/') ip = ip.lstrip('htps:/')
regex = '/(^127\.)|(^192\.168\.)|(^10\.)|(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^::1)$/' regex = '/(^127\.)|(^192\.168\.)|(^10\.)|(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^::1)$/'
return re.search(regex, ip) is not None or 'localhost' in ip or ip[:4] == '127.' return re.search(regex, ip) is not None or 'localhost' in ip or ip[:4] == '127.'
def getExt(filename): def getExt(filename):
return os.path.splitext(filename)[1][1:] return os.path.splitext(filename)[1][1:]
def cleanHost(host, protocol = True, ssl = False, username = None, password = None): def cleanHost(host, protocol = True, ssl = False, username = None, password = None):
if not '://' in host and protocol: if not '://' in host and protocol:
@ -137,6 +152,7 @@ def cleanHost(host, protocol = True, ssl = False, username = None, password = No
return host return host
def getImdb(txt, check_inside = False, multiple = False): def getImdb(txt, check_inside = False, multiple = False):
if not check_inside: if not check_inside:
@ -161,10 +177,12 @@ def getImdb(txt, check_inside = False, multiple = False):
return False return False
def tryInt(s, default = 0): def tryInt(s, default = 0):
try: return int(s) try: return int(s)
except: return default except: return default
def tryFloat(s): def tryFloat(s):
try: try:
if isinstance(s, str): if isinstance(s, str):
@ -173,17 +191,24 @@ def tryFloat(s):
return float(s) return float(s)
except: return 0 except: return 0
def natsortKey(s): def natsortKey(s):
return map(tryInt, re.findall(r'(\d+|\D+)', s)) return map(tryInt, re.findall(r'(\d+|\D+)', s))
def natcmp(a, b): def natcmp(a, b):
return cmp(natsortKey(a), natsortKey(b)) a2 = natsortKey(a)
b2 = natsortKey(b)
return (a2 > b2) - (a2 < b2)
def toIterable(value): def toIterable(value):
if isinstance(value, collections.Iterable): if isinstance(value, collections.Iterable):
return value return value
return [value] return [value]
def getTitle(library_dict): def getTitle(library_dict):
try: try:
try: try:
@ -206,6 +231,7 @@ def getTitle(library_dict):
log.error('Could not get title for library item: %s', library_dict) log.error('Could not get title for library item: %s', library_dict)
return None return None
def possibleTitles(raw_title): def possibleTitles(raw_title):
titles = [ titles = [
@ -220,16 +246,20 @@ def possibleTitles(raw_title):
return list(set(titles)) return list(set(titles))
def randomString(size = 8, chars = string.ascii_uppercase + string.digits): def randomString(size = 8, chars = string.ascii_uppercase + string.digits):
return ''.join(random.choice(chars) for x in range(size)) return ''.join(random.choice(chars) for x in range(size))
def splitString(str, split_on = ',', clean = True): def splitString(str, split_on = ',', clean = True):
list = [x.strip() for x in str.split(split_on)] if str else [] l = [x.strip() for x in str.split(split_on)] if str else []
return filter(None, list) if clean else list return filter(None, l) if clean else l
def dictIsSubset(a, b): def dictIsSubset(a, b):
return all([k in b and b[k] == v for k, v in a.items()]) return all([k in b and b[k] == v for k, v in a.items()])
def isSubFolder(sub_folder, base_folder): def isSubFolder(sub_folder, base_folder):
# Returns True if sub_folder is the same as or inside base_folder # Returns True if sub_folder is the same as or inside base_folder
return base_folder and sub_folder and os.path.normpath(base_folder).rstrip(os.path.sep) + os.path.sep in os.path.normpath(sub_folder).rstrip(os.path.sep) + os.path.sep return base_folder and sub_folder and os.path.normpath(base_folder).rstrip(os.path.sep) + os.path.sep in os.path.normpath(sub_folder).rstrip(os.path.sep) + os.path.sep

3
couchpotato/core/logger.py

@ -1,6 +1,7 @@
import logging import logging
import re import re
class CPLog(object): class CPLog(object):
context = '' context = ''
@ -49,7 +50,7 @@ class CPLog(object):
msg = msg % tuple([ss(x) for x in list(replace_tuple)]) msg = msg % tuple([ss(x) for x in list(replace_tuple)])
else: else:
msg = msg % ss(replace_tuple) msg = msg % ss(replace_tuple)
except Exception, e: except Exception as e:
self.logger.error(u'Failed encoding stuff to log "%s": %s' % (msg, e)) self.logger.error(u'Failed encoding stuff to log "%s": %s' % (msg, e))
if not Env.get('dev'): if not Env.get('dev'):

4
couchpotato/core/media/__init__.py

@ -10,8 +10,8 @@ class MediaBase(Plugin):
default_dict = { default_dict = {
'profile': {'types': {'quality': {}}}, 'profile': {'types': {'quality': {}}},
'releases': {'status': {}, 'quality': {}, 'files':{}, 'info': {}}, 'releases': {'status': {}, 'quality': {}, 'files': {}, 'info': {}},
'library': {'titles': {}, 'files':{}}, 'library': {'titles': {}, 'files': {}},
'files': {}, 'files': {},
'status': {}, 'status': {},
'category': {}, 'category': {},

1
couchpotato/core/media/_base/media/__init__.py

@ -1,5 +1,6 @@
from .main import MediaPlugin from .main import MediaPlugin
def start(): def start():
return MediaPlugin() return MediaPlugin()

3
couchpotato/core/media/_base/media/main.py

@ -102,7 +102,6 @@ class MediaPlugin(MediaBase):
def handler(): def handler():
fireEvent('library.update.%s' % media.type, identifier = identifier, default_title = default_title, force = True, on_complete = self.createOnComplete(id)) fireEvent('library.update.%s' % media.type, identifier = identifier, default_title = default_title, force = True, on_complete = self.createOnComplete(id))
return handler return handler
def addSingleRefreshView(self): def addSingleRefreshView(self):
@ -254,7 +253,7 @@ class MediaPlugin(MediaBase):
# Merge releases with movie dict # Merge releases with movie dict
movies.append(mergeDicts(movie_dict[media_id].to_dict({ movies.append(mergeDicts(movie_dict[media_id].to_dict({
'library': {'titles': {}, 'files':{}}, 'library': {'titles': {}, 'files': {}},
'files': {}, 'files': {},
}), { }), {
'releases': releases, 'releases': releases,

1
couchpotato/core/media/_base/search/__init__.py

@ -1,5 +1,6 @@
from .main import Search from .main import Search
def start(): def start():
return Search() return Search()

1
couchpotato/core/media/_base/searcher/__init__.py

@ -1,5 +1,6 @@
from .main import Searcher from .main import Searcher
def start(): def start():
return Searcher() return Searcher()

4
couchpotato/core/media/_base/searcher/base.py

@ -12,7 +12,6 @@ class SearcherBase(Plugin):
def __init__(self): def __init__(self):
super(SearcherBase, self).__init__() super(SearcherBase, self).__init__()
addEvent('searcher.progress', self.getProgress) addEvent('searcher.progress', self.getProgress)
addEvent('%s.searcher.progress' % self.getType(), self.getProgress) addEvent('%s.searcher.progress' % self.getType(), self.getProgress)
@ -26,9 +25,8 @@ class SearcherBase(Plugin):
_type = self.getType() _type = self.getType()
def setCrons(): def setCrons():
fireEvent('schedule.cron', '%s.searcher.all' % _type, self.searchAll, fireEvent('schedule.cron', '%s.searcher.all' % _type, self.searchAll,
day = self.conf('cron_day'), hour = self.conf('cron_hour'), minute = self.conf('cron_minute')) day = self.conf('cron_day'), hour = self.conf('cron_hour'), minute = self.conf('cron_minute'))
addEvent('app.load', setCrons) addEvent('app.load', setCrons)
addEvent('setting.save.%s_searcher.cron_day.after' % _type, setCrons) addEvent('setting.save.%s_searcher.cron_day.after' % _type, setCrons)

4
couchpotato/core/media/_base/searcher/main.py

@ -107,10 +107,10 @@ class Searcher(SearcherBase):
# Hack for older movies that don't contain quality tag # Hack for older movies that don't contain quality tag
year_name = fireEvent('scanner.name_year', name, single = True) year_name = fireEvent('scanner.name_year', name, single = True)
if len(found) == 0 and movie_year < datetime.datetime.now().year - 3 and not year_name.get('year', None): if len(found) == 0 and movie_year < datetime.datetime.now().year - 3 and not year_name.get('year', None):
if size > 3000: # Assume dvdr if size > 3000: # Assume dvdr
log.info('Quality was missing in name, assuming it\'s a DVD-R based on the size: %s', size) log.info('Quality was missing in name, assuming it\'s a DVD-R based on the size: %s', size)
found['dvdr'] = True found['dvdr'] = True
else: # Assume dvdrip else: # Assume dvdrip
log.info('Quality was missing in name, assuming it\'s a DVD-Rip based on the size: %s', size) log.info('Quality was missing in name, assuming it\'s a DVD-Rip based on the size: %s', size)
found['dvdrip'] = True found['dvdrip'] = True

1
couchpotato/core/media/movie/_base/__init__.py

@ -1,5 +1,6 @@
from .main import MovieBase from .main import MovieBase
def start(): def start():
return MovieBase() return MovieBase()

1
couchpotato/core/media/movie/_base/main.py

@ -61,7 +61,6 @@ class MovieBase(MovieTypeBase):
except: except:
pass pass
library = fireEvent('library.add.movie', single = True, attrs = params, update_after = update_library) library = fireEvent('library.add.movie', single = True, attrs = params, update_after = update_library)
# Status # Status

1
couchpotato/core/media/movie/library/movie/__init__.py

@ -1,5 +1,6 @@
from .main import MovieLibraryPlugin from .main import MovieLibraryPlugin
def start(): def start():
return MovieLibraryPlugin() return MovieLibraryPlugin()

2
couchpotato/core/media/movie/library/movie/main.py

@ -13,7 +13,7 @@ log = CPLog(__name__)
class MovieLibraryPlugin(LibraryBase): class MovieLibraryPlugin(LibraryBase):
default_dict = {'titles': {}, 'files':{}} default_dict = {'titles': {}, 'files': {}}
def __init__(self): def __init__(self):
addEvent('library.add.movie', self.add) addEvent('library.add.movie', self.add)

1
couchpotato/core/media/movie/searcher/__init__.py

@ -1,6 +1,7 @@
from .main import MovieSearcher from .main import MovieSearcher
import random import random
def start(): def start():
return MovieSearcher() return MovieSearcher()

4
couchpotato/core/media/movie/searcher/main.py

@ -91,7 +91,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
'category': {}, 'category': {},
'profile': {'types': {'quality': {}}}, 'profile': {'types': {'quality': {}}},
'releases': {'status': {}, 'quality': {}}, 'releases': {'status': {}, 'quality': {}},
'library': {'titles': {}, 'files':{}}, 'library': {'titles': {}, 'files': {}},
'files': {}, 'files': {},
}) })
@ -117,7 +117,7 @@ class MovieSearcher(SearcherBase, MovieTypeBase):
def single(self, movie, search_protocols = None, manual = False): def single(self, movie, search_protocols = None, manual = False):
# movies don't contain 'type' yet, so just set to default here # movies don't contain 'type' yet, so just set to default here
if not movie.has_key('type'): if 'type' not in movie:
movie['type'] = 'movie' movie['type'] = 'movie'
# Find out search type # Find out search type

1
couchpotato/core/media/movie/suggestion/__init__.py

@ -1,5 +1,6 @@
from .main import Suggestion from .main import Suggestion
def start(): def start():
return Suggestion() return Suggestion()

2
couchpotato/core/media/movie/suggestion/main.py

@ -40,7 +40,7 @@ class Suggestion(Plugin):
movies.extend(splitString(Env.prop('suggest_seen', default = ''))) movies.extend(splitString(Env.prop('suggest_seen', default = '')))
suggestions = fireEvent('movie.suggest', movies = movies, ignore = ignored, single = True) suggestions = fireEvent('movie.suggest', movies = movies, ignore = ignored, single = True)
self.setCache('suggestion_cached', suggestions, timeout = 6048000) # Cache for 10 weeks self.setCache('suggestion_cached', suggestions, timeout = 6048000) # Cache for 10 weeks
return { return {
'success': True, 'success': True,

1
couchpotato/core/migration/versions/002_Movie_category.py

@ -13,5 +13,6 @@ def upgrade(migrate_engine):
create_column(category_column, movie) create_column(category_column, movie)
Index('ix_movie_category_id', movie.c.category_id).create() Index('ix_movie_category_id', movie.c.category_id).create()
def downgrade(migrate_engine): def downgrade(migrate_engine):
pass pass

1
couchpotato/core/notifications/boxcar/__init__.py

@ -1,5 +1,6 @@
from .main import Boxcar from .main import Boxcar
def start(): def start():
return Boxcar() return Boxcar()

1
couchpotato/core/notifications/core/__init__.py

@ -1,5 +1,6 @@
from .main import CoreNotifier from .main import CoreNotifier
def start(): def start():
return CoreNotifier() return CoreNotifier()

1
couchpotato/core/notifications/core/main.py

@ -71,7 +71,6 @@ class CoreNotifier(Notification):
db.query(Notif).filter(Notif.added <= (int(time.time()) - 2419200)).delete() db.query(Notif).filter(Notif.added <= (int(time.time()) - 2419200)).delete()
db.commit() db.commit()
def markAsRead(self, ids = None, **kwargs): def markAsRead(self, ids = None, **kwargs):
ids = splitString(ids) if ids else None ids = splitString(ids) if ids else None

1
couchpotato/core/notifications/email/__init__.py

@ -1,5 +1,6 @@
from .main import Email from .main import Email
def start(): def start():
return Email() return Email()

2
couchpotato/core/notifications/email/main.py

@ -40,7 +40,7 @@ class Email(Notification):
log.debug("SMTP over SSL %s", ("enabled" if ssl == 1 else "disabled")) log.debug("SMTP over SSL %s", ("enabled" if ssl == 1 else "disabled"))
mailserver = smtplib.SMTP_SSL(smtp_server) if ssl == 1 else smtplib.SMTP(smtp_server) mailserver = smtplib.SMTP_SSL(smtp_server) if ssl == 1 else smtplib.SMTP(smtp_server)
if (starttls): if starttls:
log.debug("Using StartTLS to initiate the connection with the SMTP server") log.debug("Using StartTLS to initiate the connection with the SMTP server")
mailserver.starttls() mailserver.starttls()

1
couchpotato/core/notifications/growl/__init__.py

@ -1,5 +1,6 @@
from .main import Growl from .main import Growl
def start(): def start():
return Growl() return Growl()

2
couchpotato/core/notifications/growl/main.py

@ -37,7 +37,7 @@ class Growl(Notification):
) )
self.growl.register() self.growl.register()
self.registered = True self.registered = True
except Exception, e: except Exception as e:
if 'timed out' in str(e): if 'timed out' in str(e):
self.registered = True self.registered = True
else: else:

1
couchpotato/core/notifications/nmj/__init__.py

@ -1,5 +1,6 @@
from .main import NMJ from .main import NMJ
def start(): def start():
return NMJ() return NMJ()

7
couchpotato/core/notifications/nmj/main.py

@ -86,18 +86,17 @@ class NMJ(Notification):
'arg3': '', 'arg3': '',
} }
params = tryUrlencode(params) params = tryUrlencode(params)
UPDATE_URL = 'http://%(host)s:8008/metadata_database?%(params)s' update_url = 'http://%(host)s:8008/metadata_database?%(params)s' % {'host': host, 'params': params}
updateUrl = UPDATE_URL % {'host': host, 'params': params}
try: try:
response = self.urlopen(updateUrl) response = self.urlopen(update_url)
except: except:
return False return False
try: try:
et = etree.fromstring(response) et = etree.fromstring(response)
result = et.findtext('returnValue') result = et.findtext('returnValue')
except SyntaxError, e: except SyntaxError as e:
log.error('Unable to parse XML returned from the Popcorn Hour: %s', e) log.error('Unable to parse XML returned from the Popcorn Hour: %s', e)
return False return False

1
couchpotato/core/notifications/notifymyandroid/__init__.py

@ -1,5 +1,6 @@
from .main import NotifyMyAndroid from .main import NotifyMyAndroid
def start(): def start():
return NotifyMyAndroid() return NotifyMyAndroid()

1
couchpotato/core/notifications/notifymywp/__init__.py

@ -1,5 +1,6 @@
from .main import NotifyMyWP from .main import NotifyMyWP
def start(): def start():
return NotifyMyWP() return NotifyMyWP()

3
couchpotato/core/notifications/notifymywp/main.py

@ -8,7 +8,8 @@ log = CPLog(__name__)
class NotifyMyWP(Notification): class NotifyMyWP(Notification):
def notify(self, message = '', data = {}, listener = None): def notify(self, message = '', data = None, listener = None):
if not data: data = {}
keys = splitString(self.conf('api_key')) keys = splitString(self.conf('api_key'))
p = PyNMWP(keys, self.conf('dev_key')) p = PyNMWP(keys, self.conf('dev_key'))

1
couchpotato/core/notifications/plex/__init__.py

@ -1,5 +1,6 @@
from .main import Plex from .main import Plex
def start(): def start():
return Plex() return Plex()

7
couchpotato/core/notifications/plex/main.py

@ -23,9 +23,9 @@ class Plex(Notification):
addEvent('renamer.after', self.addToLibrary) addEvent('renamer.after', self.addToLibrary)
def addToLibrary(self, message = None, group = None):
def addToLibrary(self, message = None, group = {}):
if self.isDisabled(): return if self.isDisabled(): return
if not group: group = {}
return self.server.refresh() return self.server.refresh()
@ -57,7 +57,8 @@ class Plex(Notification):
return success return success
def notify(self, message = '', data = {}, listener = None): def notify(self, message = '', data = None, listener = None):
if not data: data = {}
return self.notifyClients(message, self.getClientNames()) return self.notifyClients(message, self.getClientNames())
def test(self, **kwargs): def test(self, **kwargs):

1
couchpotato/core/notifications/prowl/__init__.py

@ -1,5 +1,6 @@
from .main import Prowl from .main import Prowl
def start(): def start():
return Prowl() return Prowl()

2
couchpotato/core/notifications/prowl/main.py

@ -22,7 +22,7 @@ class Prowl(Notification):
'priority': self.conf('priority'), 'priority': self.conf('priority'),
} }
headers = { headers = {
'Content-type': 'application/x-www-form-urlencoded' 'Content-type': 'application/x-www-form-urlencoded'
} }
try: try:

1
couchpotato/core/notifications/pushalot/__init__.py

@ -1,5 +1,6 @@
from .main import Pushalot from .main import Pushalot
def start(): def start():
return Pushalot() return Pushalot()

1
couchpotato/core/notifications/pushalot/main.py

@ -5,6 +5,7 @@ import traceback
log = CPLog(__name__) log = CPLog(__name__)
class Pushalot(Notification): class Pushalot(Notification):
urls = { urls = {

1
couchpotato/core/notifications/pushbullet/__init__.py

@ -1,5 +1,6 @@
from .main import Pushbullet from .main import Pushbullet
def start(): def start():
return Pushbullet() return Pushbullet()

1
couchpotato/core/notifications/pushover/__init__.py

@ -1,5 +1,6 @@
from .main import Pushover from .main import Pushover
def start(): def start():
return Pushover() return Pushover()

6
couchpotato/core/notifications/pushover/main.py

@ -30,9 +30,9 @@ class Pushover(Notification):
}) })
http_handler.request('POST', http_handler.request('POST',
"/1/messages.json", "/1/messages.json",
headers = {'Content-type': 'application/x-www-form-urlencoded'}, headers = {'Content-type': 'application/x-www-form-urlencoded'},
body = tryUrlencode(api_data) body = tryUrlencode(api_data)
) )
response = http_handler.getresponse() response = http_handler.getresponse()

1
couchpotato/core/notifications/synoindex/__init__.py

@ -1,5 +1,6 @@
from .main import Synoindex from .main import Synoindex
def start(): def start():
return Synoindex() return Synoindex()

2
couchpotato/core/notifications/synoindex/main.py

@ -26,7 +26,7 @@ class Synoindex(Notification):
out = p.communicate() out = p.communicate()
log.info('Result from synoindex: %s', str(out)) log.info('Result from synoindex: %s', str(out))
return True return True
except OSError, e: except OSError as e:
log.error('Unable to run synoindex: %s', e) log.error('Unable to run synoindex: %s', e)
return False return False

1
couchpotato/core/notifications/toasty/__init__.py

@ -1,5 +1,6 @@
from .main import Toasty from .main import Toasty
def start(): def start():
return Toasty() return Toasty()

1
couchpotato/core/notifications/toasty/main.py

@ -5,6 +5,7 @@ import traceback
log = CPLog(__name__) log = CPLog(__name__)
class Toasty(Notification): class Toasty(Notification):
urls = { urls = {

1
couchpotato/core/notifications/trakt/__init__.py

@ -1,5 +1,6 @@
from .main import Trakt from .main import Trakt
def start(): def start():
return Trakt() return Trakt()

1
couchpotato/core/notifications/trakt/main.py

@ -3,6 +3,7 @@ from couchpotato.core.notifications.base import Notification
log = CPLog(__name__) log = CPLog(__name__)
class Trakt(Notification): class Trakt(Notification):
urls = { urls = {

1
couchpotato/core/notifications/twitter/__init__.py

@ -1,5 +1,6 @@
from .main import Twitter from .main import Twitter
def start(): def start():
return Twitter() return Twitter()

2
couchpotato/core/notifications/twitter/main.py

@ -64,7 +64,7 @@ class Twitter(Notification):
api.PostUpdate(update_message[135:] + ' 2/2') api.PostUpdate(update_message[135:] + ' 2/2')
else: else:
api.PostUpdate(update_message) api.PostUpdate(update_message)
except Exception, e: except Exception as e:
log.error('Error sending tweet: %s', e) log.error('Error sending tweet: %s', e)
return False return False

1
couchpotato/core/notifications/xbmc/__init__.py

@ -1,5 +1,6 @@
from .main import XBMC from .main import XBMC
def start(): def start():
return XBMC() return XBMC()

3
couchpotato/core/notifications/xbmc/main.py

@ -1,7 +1,6 @@
from couchpotato.core.helpers.variable import splitString from couchpotato.core.helpers.variable import splitString
from couchpotato.core.logger import CPLog from couchpotato.core.logger import CPLog
from couchpotato.core.notifications.base import Notification from couchpotato.core.notifications.base import Notification
from urllib2 import URLError
import base64 import base64
import json import json
import socket import socket
@ -46,7 +45,7 @@ class XBMC(Notification):
max_successful += len(calls) max_successful += len(calls)
response = self.request(host, calls) response = self.request(host, calls)
else: else:
response = self.notifyXBMCnoJSON(host, {'title':self.default_title, 'message':message}) response = self.notifyXBMCnoJSON(host, {'title': self.default_title, 'message': message})
if data and data.get('destination_dir') and (not self.conf('only_first') or hosts.index(host) == 0): if data and data.get('destination_dir') and (not self.conf('only_first') or hosts.index(host) == 0):
response += self.request(host, [('VideoLibrary.Scan', {})]) response += self.request(host, [('VideoLibrary.Scan', {})])

1
couchpotato/core/notifications/xmpp/__init__.py

@ -1,5 +1,6 @@
from .main import Xmpp from .main import Xmpp
def start(): def start():
return Xmpp() return Xmpp()

1
couchpotato/core/plugins/automation/__init__.py

@ -1,5 +1,6 @@
from .main import Automation from .main import Automation
def start(): def start():
return Automation() return Automation()

9
couchpotato/core/plugins/base.py

@ -85,7 +85,7 @@ class Plugin(object):
class_name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower() class_name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
# View path # View path
path = 'static/plugin/%s/' % (class_name) path = 'static/plugin/%s/' % class_name
# Add handler to Tornado # Add handler to Tornado
Env.get('app').add_handlers(".*$", [(Env.get('web_base') + path + '(.*)', StaticFileHandler, {'path': static_folder})]) Env.get('app').add_handlers(".*$", [(Env.get('web_base') + path + '(.*)', StaticFileHandler, {'path': static_folder})])
@ -110,7 +110,7 @@ class Plugin(object):
f.write(content) f.write(content)
f.close() f.close()
os.chmod(path, Env.getPermission('file')) os.chmod(path, Env.getPermission('file'))
except Exception, e: except Exception as e:
log.error('Unable writing to file "%s": %s', (path, traceback.format_exc())) log.error('Unable writing to file "%s": %s', (path, traceback.format_exc()))
if os.path.isfile(path): if os.path.isfile(path):
os.remove(path) os.remove(path)
@ -121,7 +121,7 @@ class Plugin(object):
if not os.path.isdir(path): if not os.path.isdir(path):
os.makedirs(path, Env.getPermission('folder')) os.makedirs(path, Env.getPermission('folder'))
return True return True
except Exception, e: except Exception as e:
log.error('Unable to create folder "%s": %s', (path, e)) log.error('Unable to create folder "%s": %s', (path, e))
return False return False
@ -243,7 +243,6 @@ class Plugin(object):
except: except:
log.error("Something went wrong when finishing the plugin function. Could not find the 'is_running' key") log.error("Something went wrong when finishing the plugin function. Could not find the 'is_running' key")
def getCache(self, cache_key, url = None, **kwargs): def getCache(self, cache_key, url = None, **kwargs):
cache_key_md5 = md5(cache_key) cache_key_md5 = md5(cache_key)
cache = Env.get('cache').get(cache_key_md5) cache = Env.get('cache').get(cache_key_md5)
@ -255,7 +254,7 @@ class Plugin(object):
try: try:
cache_timeout = 300 cache_timeout = 300
if kwargs.has_key('cache_timeout'): if 'cache_timeout' in kwargs:
cache_timeout = kwargs.get('cache_timeout') cache_timeout = kwargs.get('cache_timeout')
del kwargs['cache_timeout'] del kwargs['cache_timeout']

1
couchpotato/core/plugins/browser/__init__.py

@ -1,5 +1,6 @@
from .main import FileBrowser from .main import FileBrowser
def start(): def start():
return FileBrowser() return FileBrowser()

2
couchpotato/core/plugins/browser/main.py

@ -14,7 +14,7 @@ if os.name == 'nt':
raise ImportError("Missing the win32file module, which is a part of the prerequisite \ raise ImportError("Missing the win32file module, which is a part of the prerequisite \
pywin32 package. You can get it from http://sourceforge.net/projects/pywin32/files/pywin32/") pywin32 package. You can get it from http://sourceforge.net/projects/pywin32/files/pywin32/")
else: else:
import win32file #@UnresolvedImport import win32file #@UnresolvedImport
class FileBrowser(Plugin): class FileBrowser(Plugin):

1
couchpotato/core/plugins/category/__init__.py

@ -1,5 +1,6 @@
from .main import CategoryPlugin from .main import CategoryPlugin
def start(): def start():
return CategoryPlugin() return CategoryPlugin()

2
couchpotato/core/plugins/category/main.py

@ -101,7 +101,7 @@ class CategoryPlugin(Plugin):
self.removeFromMovie(id) self.removeFromMovie(id)
success = True success = True
except Exception, e: except Exception as e:
message = log.error('Failed deleting category: %s', e) message = log.error('Failed deleting category: %s', e)
db.expire_all() db.expire_all()

1
couchpotato/core/plugins/custom/__init__.py

@ -1,5 +1,6 @@
from .main import Custom from .main import Custom
def start(): def start():
return Custom() return Custom()

1
couchpotato/core/plugins/dashboard/__init__.py

@ -1,5 +1,6 @@
from .main import Dashboard from .main import Dashboard
def start(): def start():
return Dashboard() return Dashboard()

2
couchpotato/core/plugins/dashboard/main.py

@ -115,7 +115,7 @@ class Dashboard(Plugin):
for movie_id in movie_ids: for movie_id in movie_ids:
movies.append(movie_dict[movie_id].to_dict({ movies.append(movie_dict[movie_id].to_dict({
'library': {'titles': {}, 'files':{}}, 'library': {'titles': {}, 'files': {}},
'files': {}, 'files': {},
})) }))

1
couchpotato/core/plugins/file/__init__.py

@ -1,5 +1,6 @@
from .main import FileManager from .main import FileManager
def start(): def start():
return FileManager() return FileManager()

1
couchpotato/core/plugins/file/main.py

@ -82,7 +82,6 @@ class FileManager(Plugin):
def showCacheFile(self, route, **kwargs): def showCacheFile(self, route, **kwargs):
Env.get('app').add_handlers(".*$", [('%s%s' % (Env.get('api_base'), route), StaticFileHandler, {'path': Env.get('cache_dir')})]) Env.get('app').add_handlers(".*$", [('%s%s' % (Env.get('api_base'), route), StaticFileHandler, {'path': Env.get('cache_dir')})])
def download(self, url = '', dest = None, overwrite = False, urlopen_kwargs = None): def download(self, url = '', dest = None, overwrite = False, urlopen_kwargs = None):
if not urlopen_kwargs: urlopen_kwargs = {} if not urlopen_kwargs: urlopen_kwargs = {}

1
couchpotato/core/plugins/log/__init__.py

@ -1,5 +1,6 @@
from .main import Logging from .main import Logging
def start(): def start():
return Logging() return Logging()

2
couchpotato/core/plugins/log/main.py

@ -42,7 +42,7 @@ class Logging(Plugin):
'desc': 'Log errors', 'desc': 'Log errors',
'params': { 'params': {
'type': {'desc': 'Type of logging, default "error"'}, 'type': {'desc': 'Type of logging, default "error"'},
'**kwargs': {'type':'object', 'desc': 'All other params will be printed in the log string.'}, '**kwargs': {'type': 'object', 'desc': 'All other params will be printed in the log string.'},
} }
}) })

1
couchpotato/core/plugins/manage/__init__.py

@ -1,5 +1,6 @@
from .main import Manage from .main import Manage
def start(): def start():
return Manage() return Manage()

1
couchpotato/core/plugins/manage/main.py

@ -14,6 +14,7 @@ import traceback
log = CPLog(__name__) log = CPLog(__name__)
class Manage(Plugin): class Manage(Plugin):
in_progress = False in_progress = False

1
couchpotato/core/plugins/profile/__init__.py

@ -1,5 +1,6 @@
from .main import ProfilePlugin from .main import ProfilePlugin
def start(): def start():
return ProfilePlugin() return ProfilePlugin()

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save