From eaa420583e3298c78f57663a198d8e8d0ae38c3d Mon Sep 17 00:00:00 2001 From: Remy Date: Tue, 9 Aug 2011 01:22:51 -0700 Subject: [PATCH 1/5] Fixed album title exception in post processor --- headphones/postprocessor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/headphones/postprocessor.py b/headphones/postprocessor.py index 313f30af..e28033c3 100644 --- a/headphones/postprocessor.py +++ b/headphones/postprocessor.py @@ -306,7 +306,7 @@ def moveFiles(albumpath, release, tracks): os.chmod(temp_f, 0755) except Exception, e: - logger.error('Could not create folder for %s. Not moving' % release['AlbumName']) + logger.error('Could not create folder for %s. Not moving: %s' % (release['AlbumTitle'], e)) return albumpath for r,d,f in os.walk(albumpath): From 76529ea85180583dfe01e836c2c10ffc1a30903c Mon Sep 17 00:00:00 2001 From: Remy Date: Tue, 9 Aug 2011 12:10:43 -0700 Subject: [PATCH 2/5] Fixed exception being referenced before assignment in searcher/getresultNZB --- headphones/searcher.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/headphones/searcher.py b/headphones/searcher.py index 333b12eb..ded3ee5d 100644 --- a/headphones/searcher.py +++ b/headphones/searcher.py @@ -453,7 +453,7 @@ def getresultNZB(result): else: try: nzb = urllib2.urlopen(result[2], timeout=20).read() - except: + except Exception, e: logger.warn('Error fetching nzb from url: ' + result[2] + ' %s' % e) return nzb From c24178db956f26eaf1af5a57e78e0a519c972175 Mon Sep 17 00:00:00 2001 From: Remy Date: Tue, 9 Aug 2011 14:49:25 -0700 Subject: [PATCH 3/5] Fixed bug with log page not displaying if non-utf8 characters --- data/css/style.css | 2 +- data/interfaces/default/logs.html | 23 +++++++++-------------- headphones/__init__.py | 2 ++ headphones/helpers.py | 9 +++++++-- headphones/logger.py | 24 ++++++++++++++---------- headphones/webserve.py | 8 +------- 6 files changed, 34 insertions(+), 34 deletions(-) diff --git a/data/css/style.css b/data/css/style.css index e3d9a282..a072fe06 100755 --- a/data/css/style.css +++ b/data/css/style.css @@ -190,7 +190,7 @@ table#log_table { background-color: white; } table#log_table th#timestamp { text-align: left; min-width: 165px; } table#log_table th#level { text-align: left; min-width: 75px; } -table#log_table th#message { text-align: left; min-width: 200px; } +table#log_table th#message { text-align: left; min-width: 500px; } table#upcoming_table th#albumart { text-align: center; min-width: 50px; } table#upcoming_table th#albumname { text-align: center; min-width: 200px; } diff --git a/data/interfaces/default/logs.html b/data/interfaces/default/logs.html index cc6436f3..98004034 100644 --- a/data/interfaces/default/logs.html +++ b/data/interfaces/default/logs.html @@ -15,23 +15,18 @@ %for line in lineList: <% - out_tuple = helpers.extract_logline(line) + timestamp, message, level, threadname = line + + if level == 'WARNING' or level == 'ERROR': + grade = 'X' + else: + grade = 'Z' %> - %if out_tuple: - <% - if out_tuple[1] == 'DEBUG': - continue - elif out_tuple[1] == 'WARNING' or out_tuple[1] == 'ERROR': - grade = 'X' - else: - grade = 'Z' - %> - ${out_tuple[0]} - ${out_tuple[1]} - ${out_tuple[3].decode('utf-8')} + ${timestamp} + ${level} + ${message} - %endif %endfor diff --git a/headphones/__init__.py b/headphones/__init__.py index 6939f8b8..57d7cb43 100644 --- a/headphones/__init__.py +++ b/headphones/__init__.py @@ -37,6 +37,8 @@ CFG = None DB_FILE = None LOG_DIR = None +LOG_LIST = [] + CACHE_DIR = None HTTP_PORT = None diff --git a/headphones/helpers.py b/headphones/helpers.py index 9dc3aa10..4ecc6941 100644 --- a/headphones/helpers.py +++ b/headphones/helpers.py @@ -5,8 +5,6 @@ import re import headphones -from headphones import logger - def multikeysort(items, columns): comparers = [ ((itemgetter(col[1:].strip()), -1) if col.startswith('-') else (itemgetter(col.strip()), 1)) for col in columns] @@ -91,6 +89,10 @@ def today(): yyyymmdd = datetime.date.isoformat(today) return yyyymmdd +def now(): + now = datetime.datetime.now() + return now.strftime("%Y-%m-%d %H:%M:%S") + def bytes_to_mb(bytes): mb = int(bytes)/1048576 @@ -103,6 +105,9 @@ def replace_all(text, dic): return text def extract_data(s): + + from headphones import logger + #headphones default format pattern = re.compile(r'(?P.*?)\s\-\s(?P.*?)\s\[(?P.*?)\]', re.VERBOSE) match = pattern.match(s) diff --git a/headphones/logger.py b/headphones/logger.py index f861a4c3..93c77c57 100644 --- a/headphones/logger.py +++ b/headphones/logger.py @@ -4,6 +4,7 @@ import logging from logging import handlers import headphones +from headphones import helpers MAX_SIZE = 1000000 # 1mb MAX_FILES = 5 @@ -45,33 +46,36 @@ class RotatingLogger(object): l.addHandler(consolehandler) def log(self, message, level): - + logger = logging.getLogger('headphones') threadname = threading.currentThread().getName() - message = threadname + ' : ' + message - if level == 'debug': + if level != 'DEBUG': + headphones.LOG_LIST.insert(0, (helpers.now(), message, level, threadname)) + + message = threadname + ' : ' + message + + if level == 'DEBUG': logger.debug(message) - elif level == 'info': + elif level == 'INFO': logger.info(message) - elif level == 'warn': + elif level == 'WARN': logger.warn(message) else: logger.error(message) - headphones_log = RotatingLogger('headphones.log', MAX_SIZE, MAX_FILES) def debug(message): - headphones_log.log(message, level='debug') + headphones_log.log(message, level='DEBUG') def info(message): - headphones_log.log(message, level='info') + headphones_log.log(message, level='INFO') def warn(message): - headphones_log.log(message, level='warn') + headphones_log.log(message, level='WARN') def error(message): - headphones_log.log(message, level='error') + headphones_log.log(message, level='ERROR') diff --git a/headphones/webserve.py b/headphones/webserve.py index fd406306..779f6da0 100644 --- a/headphones/webserve.py +++ b/headphones/webserve.py @@ -231,13 +231,7 @@ class WebInterface(object): history.exposed = True def logs(self): - log_file = os.path.join(headphones.LOG_DIR, 'headphones.log') - if os.path.isfile(log_file): - fileHandle = open(log_file) - lineList = fileHandle.readlines() - fileHandle.close() - lineList.reverse() - return serve_template(templatename="logs.html", title="Log", lineList=lineList[0:500]) + return serve_template(templatename="logs.html", title="Log", lineList=headphones.LOG_LIST) logs.exposed = True def clearhistory(self, type=None): From 58e1728c0ec97f4492bff74fb5179cdc77240262 Mon Sep 17 00:00:00 2001 From: Remy Date: Tue, 9 Aug 2011 14:58:56 -0700 Subject: [PATCH 4/5] Added download directory scan interval as a config option in config.ini --- headphones/__init__.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/headphones/__init__.py b/headphones/__init__.py index 57d7cb43..453266cc 100644 --- a/headphones/__init__.py +++ b/headphones/__init__.py @@ -76,6 +76,7 @@ INCLUDE_EXTRAS = False NZB_SEARCH_INTERVAL = 360 LIBRARYSCAN_INTERVAL = 60 +DOWNLOAD_SCAN_INTERVAL = 5 SAB_HOST = None SAB_USERNAME = None @@ -158,7 +159,7 @@ def initialize(): CURRENT_VERSION, LATEST_VERSION, MUSIC_DIR, DESTINATION_DIR, PREFERRED_QUALITY, PREFERRED_BITRATE, DETECT_BITRATE, \ CORRECT_METADATA, MOVE_FILES, RENAME_FILES, FOLDER_FORMAT, FILE_FORMAT, CLEANUP_FILES, INCLUDE_EXTRAS, \ ADD_ALBUM_ART, EMBED_ALBUM_ART, DOWNLOAD_DIR, BLACKHOLE, BLACKHOLE_DIR, USENET_RETENTION, NZB_SEARCH_INTERVAL, \ - LIBRARYSCAN_INTERVAL, SAB_HOST, SAB_USERNAME, SAB_PASSWORD, SAB_APIKEY, SAB_CATEGORY, \ + LIBRARYSCAN_INTERVAL, DOWNLOAD_SCAN_INTERVAL, SAB_HOST, SAB_USERNAME, SAB_PASSWORD, SAB_APIKEY, SAB_CATEGORY, \ NZBMATRIX, NZBMATRIX_USERNAME, NZBMATRIX_APIKEY, NEWZNAB, NEWZNAB_HOST, NEWZNAB_APIKEY, \ NZBSORG, NZBSORG_UID, NZBSORG_HASH, NEWZBIN, NEWZBIN_UID, NEWZBIN_PASSWORD, LASTFM_USERNAME @@ -211,6 +212,7 @@ def initialize(): NZB_SEARCH_INTERVAL = check_setting_int(CFG, 'General', 'nzb_search_interval', 360) LIBRARYSCAN_INTERVAL = check_setting_int(CFG, 'General', 'libraryscan_interval', 180) + DOWNLOAD_SCAN_INTERVAL = check_setting_int(CFG, 'General', 'download_scan_interval', 5) SAB_HOST = check_setting_str(CFG, 'SABnzbd', 'sab_host', '') SAB_USERNAME = check_setting_str(CFG, 'SABnzbd', 'sab_username', '') @@ -371,6 +373,7 @@ def config_write(): new_config['General']['nzb_search_interval'] = NZB_SEARCH_INTERVAL new_config['General']['libraryscan_interval'] = LIBRARYSCAN_INTERVAL + new_config['General']['download_scan_interval'] = DOWNLOAD_SCAN_INTERVAL new_config['SABnzbd'] = {} new_config['SABnzbd']['sab_host'] = SAB_HOST @@ -416,7 +419,7 @@ def start(): SCHED.add_interval_job(searcher.searchNZB, minutes=NZB_SEARCH_INTERVAL) SCHED.add_interval_job(importer.scanMusic, minutes=LIBRARYSCAN_INTERVAL) SCHED.add_interval_job(versioncheck.checkGithub, minutes=300) - SCHED.add_interval_job(postprocessor.checkFolder, minutes=5) + SCHED.add_interval_job(postprocessor.checkFolder, minutes=DOWNLOAD_SCAN_INTERVAL) SCHED.start() From 36a29673541bfdc2354cb7fc814fea51f6b82266 Mon Sep 17 00:00:00 2001 From: Remy Date: Tue, 9 Aug 2011 16:34:43 -0700 Subject: [PATCH 5/5] Fixed css on log page, added better error catching for lastfm and searcher --- data/css/style.css | 4 ++-- headphones/importer.py | 7 +++++-- headphones/searcher.py | 5 +++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/data/css/style.css b/data/css/style.css index a072fe06..8b7803e7 100755 --- a/data/css/style.css +++ b/data/css/style.css @@ -188,8 +188,8 @@ table#history_table { background-color: white; width: 100%; } table#log_table { background-color: white; } -table#log_table th#timestamp { text-align: left; min-width: 165px; } -table#log_table th#level { text-align: left; min-width: 75px; } +table#log_table th#timestamp { text-align: left; min-width: 150px; } +table#log_table th#level { text-align: left; min-width: 60px; } table#log_table th#message { text-align: left; min-width: 500px; } table#upcoming_table th#albumart { text-align: center; min-width: 50px; } diff --git a/headphones/importer.py b/headphones/importer.py index 2efc2a27..aa22b690 100644 --- a/headphones/importer.py +++ b/headphones/importer.py @@ -215,8 +215,11 @@ def addArtisttoDB(artistid, extrasonly=False): myDB.upsert("albums", newValueDict, controlValueDict) - lastfm.getAlbumDescription(rg['id'], artist['artist_name'], rg['title']) - + try: + lastfm.getAlbumDescription(rg['id'], artist['artist_name'], rg['title']) + except Exception, e: + logger.error('Attempt to retrieve album description from Last.fm failed: %s' % e) + # I changed the albumid from releaseid -> rgid, so might need to delete albums that have a releaseid for release in release_dict['releaselist']: myDB.action('DELETE from albums WHERE AlbumID=?', [release['releaseid']]) diff --git a/headphones/searcher.py b/headphones/searcher.py index ded3ee5d..c472ac17 100644 --- a/headphones/searcher.py +++ b/headphones/searcher.py @@ -418,6 +418,7 @@ def searchNZB(albumid=None, new=False): f = open(download_path, 'w') f.write(data) f.close() + logger.info('File saved to: %s' % nzb_name) except Exception, e: logger.error('Couldn\'t write NZB file: %s' % e) break @@ -449,12 +450,12 @@ def getresultNZB(result): try: nzb = urllib.urlopen(url, data=params).read() except urllib2.URLError, e: - logger.warn('Error fetching nzb from url: ' + url + ' %s' % e) + logger.warn('Error fetching nzb from url: %s. Error: %s' % (url, e)) else: try: nzb = urllib2.urlopen(result[2], timeout=20).read() except Exception, e: - logger.warn('Error fetching nzb from url: ' + result[2] + ' %s' % e) + logger.warn('Error fetching nzb from url: %s. Error: %s' % (result[2], e)) return nzb def preprocess(resultlist):