Skip to content

Commit

Permalink
v0.5.8
Browse files Browse the repository at this point in the history
  • Loading branch information
rembo10 committed Jul 13, 2015
2 parents 84a6c19 + 71da960 commit 24165fb
Show file tree
Hide file tree
Showing 18 changed files with 602 additions and 439 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,23 @@
# Changelog

## v0.5.8
Released 13 July 2015

Highlights:
* Added: Option to only include official extras
* Added: Option to wait until album release date before searching
* Fixed: NotifyMyAndroid notifications
* Fixed: Plex Notifications
* Fixed: Metacritic parsing
* Fixed: Pushbullet notifications
* Fixed: What.cd not honoring custom search term (#2279)
* Improved: XSS Search bug
* Improved: Config page layout
* Improved: Set localhost as default
* Improved: Better single artist scanning

The full list of commits can be found [here](https://github.com/rembo10/headphones/compare/v0.5.6...v0.5.7).

## v0.5.7
Released 01 July 2015

Expand Down
3 changes: 2 additions & 1 deletion data/interfaces/default/album.html
Expand Up @@ -35,14 +35,15 @@ <h2><a id="refresh_artist" onclick="doAjaxCall('refreshArtist?ArtistID=${album['
%for alternate_album in alternate_albums:
<%
track_count = len(myDB.select("SELECT * from alltracks WHERE ReleaseID=?", [alternate_album['ReleaseID']]))
mb_link = "http://musicbrainz.org/release/" + alternate_album['ReleaseID']
have_track_count = len(myDB.select("SELECT * from alltracks WHERE ReleaseID=? AND Location IS NOT NULL", [alternate_album['ReleaseID']]))
if alternate_album['AlbumID'] == alternate_album['ReleaseID']:
alternate_album_name = "Headphones Default Release (" + str(alternate_album['ReleaseDate']) + ") [" + str(have_track_count) + "/" + str(track_count) + " tracks]"
else:
alternate_album_name = alternate_album['AlbumTitle'] + " (" + alternate_album['ReleaseCountry'] + ", " + str(alternate_album['ReleaseDate']) + ", " + alternate_album['ReleaseFormat'] + ") [" + str(have_track_count) + "/" + str(track_count) + " tracks]"

%>
<a href="#" onclick="doAjaxCall('switchAlbum?AlbumID=${album['AlbumID']}&ReleaseID=${alternate_album['ReleaseID']}', $(this), 'table');" data-success="Switched release to: ${alternate_album_name}">${alternate_album_name}</a><br>
<a href="#" onclick="doAjaxCall('switchAlbum?AlbumID=${album['AlbumID']}&ReleaseID=${alternate_album['ReleaseID']}', $(this), 'table');" data-success="Switched release to: ${alternate_album_name}">${alternate_album_name}</a><a href="${mb_link}" target="_blank">MB</a><br>
%endfor
%endif
</div>
Expand Down
659 changes: 346 additions & 313 deletions data/interfaces/default/config.html

Large diffs are not rendered by default.

21 changes: 20 additions & 1 deletion data/interfaces/default/css/style.css
Expand Up @@ -325,7 +325,7 @@ form fieldset small.heading {
margin-top: -15px;
}
form .row {
font-family: Helvetica, Arial;
font-family: Helvetica, Arial, sans-serif;
margin-bottom: 10px;
}
form .row label {
Expand Down Expand Up @@ -408,6 +408,18 @@ form .checkbox small {
form .indent input {
margin-left: 15px;
}
form .suboptions {
margin-left: 15px;
}
.option{
font-size: 15px;
font-weight: 600;
vertical-align: middle;
}
input.bigcheck[type="checkbox"] {
width: 16px;
height: 16px;
}
ul,
ol {
margin-left: 2em;
Expand Down Expand Up @@ -1420,6 +1432,13 @@ div#artistheader h2 a {
line-height: 10px;
height: 10px;
}
.nopad {
margin-bottom: 0px !important;
margin-top: 0px !important;
padding-top: 0px !important;
padding-bottom: 0px !important;
padding: 0px 0px !important;
}
#album_table th#albumname,
#upcoming_table th#artistname,
#wanted_table th#artistname {
Expand Down
2 changes: 2 additions & 0 deletions data/interfaces/default/history.html
Expand Up @@ -52,6 +52,8 @@ <h1 class="clearfix"><i class="fa fa-calendar"></i> History</h1>
fileid = 'torrent'
if item['URL'].find('rutracker') != -1:
fileid = 'torrent'
if item['URL'].find('codeshy') != -1:
fileid = 'nzb'

folder = 'Folder: ' + item['FolderName']

Expand Down
4 changes: 3 additions & 1 deletion headphones/config.py
Expand Up @@ -99,7 +99,7 @@ def bool_int(value):
'HPUSER': (str, 'General', ''),
'HTTPS_CERT': (str, 'General', ''),
'HTTPS_KEY': (str, 'General', ''),
'HTTP_HOST': (str, 'General', '0.0.0.0'),
'HTTP_HOST': (str, 'General', 'localhost'),
'HTTP_PASSWORD': (str, 'General', ''),
'HTTP_PORT': (int, 'General', 8181),
'HTTP_PROXY': (int, 'General', 0),
Expand Down Expand Up @@ -154,6 +154,7 @@ def bool_int(value):
'NZBSORG_HASH': (str, 'NZBsorg', ''),
'NZBSORG_UID': (str, 'NZBsorg', ''),
'NZB_DOWNLOADER': (int, 'General', 0),
'OFFICIAL_RELEASES_ONLY': (int, 'General', 0),
'OMGWTFNZBS': (int, 'omgwtfnzbs', 0),
'OMGWTFNZBS_APIKEY': (str, 'omgwtfnzbs', ''),
'OMGWTFNZBS_UID': (str, 'omgwtfnzbs', ''),
Expand Down Expand Up @@ -241,6 +242,7 @@ def bool_int(value):
'UTORRENT_PASSWORD': (str, 'uTorrent', ''),
'UTORRENT_USERNAME': (str, 'uTorrent', ''),
'VERIFY_SSL_CERT': (bool_int, 'Advanced', 1),
'WAIT_UNTIL_RELEASE_DATE' : (int, 'General', 0),
'WAFFLES': (int, 'Waffles', 0),
'WAFFLES_PASSKEY': (str, 'Waffles', ''),
'WAFFLES_RATIO': (str, 'Waffles', ''),
Expand Down
2 changes: 1 addition & 1 deletion headphones/helpers.py
Expand Up @@ -149,7 +149,7 @@ def get_age(date):

try:
days_old = int(split_date[0]) * 365 + int(split_date[1]) * 30 + int(split_date[2])
except IndexError:
except (IndexError,ValueError):
days_old = False

return days_old
Expand Down
12 changes: 7 additions & 5 deletions headphones/librarysync.py
Expand Up @@ -23,7 +23,7 @@
# You can scan a single directory and append it to the current library by
# specifying append=True, ArtistID and ArtistName.
def libraryScan(dir=None, append=False, ArtistID=None, ArtistName=None,
cron=False):
cron=False, artistScan=False):

if cron and not headphones.CONFIG.LIBRARYSCAN:
return
Expand All @@ -36,7 +36,7 @@ def libraryScan(dir=None, append=False, ArtistID=None, ArtistName=None,

# If we're appending a dir, it's coming from the post processor which is
# already bytestring
if not append:
if not append or artistScan:
dir = dir.encode(headphones.SYS_ENCODING)

if not os.path.isdir(dir):
Expand Down Expand Up @@ -287,7 +287,7 @@ def libraryScan(dir=None, append=False, ArtistID=None, ArtistName=None,

logger.info('Completed matching tracks from directory: %s' % dir.decode(headphones.SYS_ENCODING, 'replace'))

if not append:
if not append or artistScan:
logger.info('Updating scanned artist track counts')

# Clean up the new artist list
Expand Down Expand Up @@ -334,7 +334,7 @@ def libraryScan(dir=None, append=False, ArtistID=None, ArtistName=None,
for artist in artist_list:
myDB.action('INSERT OR IGNORE INTO newartists VALUES (?)', [artist])

if headphones.CONFIG.DETECT_BITRATE:
if headphones.CONFIG.DETECT_BITRATE and bitrates:
headphones.CONFIG.PREFERRED_BITRATE = sum(bitrates) / len(bitrates) / 1000

else:
Expand All @@ -346,6 +346,8 @@ def libraryScan(dir=None, append=False, ArtistID=None, ArtistName=None,

if not append:
update_album_status()

if not append and not artistScan:
lastfm.getSimilar()

logger.info('Library scan complete')
Expand Down Expand Up @@ -374,7 +376,7 @@ def update_album_status(AlbumID=None):
album_completion = 0
logger.info('Album %s does not have any tracks in database' % album['AlbumTitle'])

if album_completion >= headphones.CONFIG.ALBUM_COMPLETION_PCT and album['Status'] == 'Skipped':
if album_completion >= headphones.CONFIG.ALBUM_COMPLETION_PCT:
new_album_status = "Downloaded"

# I don't think we want to change Downloaded->Skipped.....
Expand Down
10 changes: 6 additions & 4 deletions headphones/mb.py
Expand Up @@ -466,6 +466,11 @@ def get_new_releases(rgid, includeExtras=False, forcefull=False):

myDB = db.DBConnection()
results = []

release_status = "official"
if includeExtras and not headphones.CONFIG.OFFICIAL_RELEASES_ONLY:
release_status = []

try:
limit = 100
newResults = None
Expand All @@ -474,6 +479,7 @@ def get_new_releases(rgid, includeExtras=False, forcefull=False):
newResults = musicbrainzngs.browse_releases(
release_group=rgid,
includes=['artist-credits', 'labels', 'recordings', 'release-groups', 'media'],
release_status = release_status,
limit=limit,
offset=len(results))
if 'release-list' not in newResults:
Expand Down Expand Up @@ -513,10 +519,6 @@ def get_new_releases(rgid, includeExtras=False, forcefull=False):
num_new_releases = 0

for releasedata in results:
#releasedata.get will return None if it doesn't have a status
#all official releases should have the Official status included
if not includeExtras and releasedata.get('status') != 'Official':
continue

release = {}
rel_id_check = releasedata['id']
Expand Down
5 changes: 3 additions & 2 deletions headphones/metacritic.py
Expand Up @@ -37,12 +37,13 @@ def update(artistid, artist_name,release_groups):

url = "http://www.metacritic.com/person/" + mc_artist_name + "?filter-options=music&sort_options=date&num_items=100"

res = request.request_soup(url, headers=headers, parser='html.parser')
res = request.request_soup(url, headers=headers)

rows = None

try:
rows = res.tbody.find_all('tr')
table = res.find("table", class_="credits person_credits")
rows = table.tbody.find_all('tr')
except:
logger.info("Unable to get metacritic scores for: %s" % artist_name)

Expand Down
104 changes: 43 additions & 61 deletions headphones/notifiers.py
Expand Up @@ -320,30 +320,27 @@ def __init__(self):

def _sendhttp(self, host, command):

username = self.username
password = self.password
url = host + '/xbmcCmds/xbmcHttp/?' + command

url_command = urllib.urlencode(command)

url = host + '/xbmcCmds/xbmcHttp/?' + url_command

req = urllib2.Request(url)

if password:
base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '')
req.add_header("Authorization", "Basic %s" % base64string)
if self.password:
response = request.request_response(url, auth=(self.username, self.password))
else:
response = request.request_response(url)

logger.info('Plex url: %s' % url)
return response

try:
handle = urllib2.urlopen(req)
except Exception as e:
logger.warn('Error opening Plex url: %s' % e)
return
def _sendjson(self, host, method, params={}):
data = [{'id': 0, 'jsonrpc': '2.0', 'method': method, 'params': params}]
headers = {'Content-Type': 'application/json'}
url = host + '/jsonrpc'

response = handle.read().decode(headphones.SYS_ENCODING)
if self.password:
response = request.request_json(url, method="post", data=json.dumps(data), headers=headers, auth=(self.username, self.password))
else:
response = request.request_json(url, method="post", data=json.dumps(data), headers=headers)

return response
if response:
return response[0]['result']

def update(self):

Expand Down Expand Up @@ -382,17 +379,24 @@ def notify(self, artist, album, albumartpath):
time = "3000" # in ms

for host in hosts:
logger.info('Sending notification command to Plex Media Server @ ' + host)
logger.info('Sending notification command to Plex client @ ' + host)
try:
notification = header + "," + message + "," + time + "," + albumartpath
notifycommand = {'command': 'ExecBuiltIn', 'parameter': 'Notification(' + notification + ')'}
request = self._sendhttp(host, notifycommand)
version = self._sendjson(host, 'Application.GetProperties', {'properties': ['version']})['version']['major']

if version < 12: #Eden
notification = header + "," + message + "," + time + "," + albumartpath
notifycommand = {'command': 'ExecBuiltIn', 'parameter': 'Notification(' + notification + ')'}
request = self._sendhttp(host, notifycommand)

else: #Frodo
params = {'title': header, 'message': message, 'displaytime': int(time), 'image': albumartpath}
request = self._sendjson(host, 'GUI.ShowNotification', params)

if not request:
raise Exception

except:
logger.warn('Error sending notification request to Plex Media Server')
except Exception:
logger.error('Error sending notification request to Plex client @ ' + host)


class NMA(object):
Expand Down Expand Up @@ -439,52 +443,30 @@ def __init__(self):
self.apikey = headphones.CONFIG.PUSHBULLET_APIKEY
self.deviceid = headphones.CONFIG.PUSHBULLET_DEVICEID

def conf(self, options):
return cherrypy.config['config'].get('PUSHBULLET', options)

def notify(self, message, event):
def notify(self, message):
if not headphones.CONFIG.PUSHBULLET_ENABLED:
return

http_handler = HTTPSConnection("api.pushbullet.com")
url = "https://api.pushbullet.com/v2/pushes"

data = {'type': "note",
'title': "Headphones",
'body': message.encode("utf-8")}

http_handler.request("POST",
"/v2/pushes",
headers={'Content-type': "application/json",
'Authorization': 'Basic %s' % base64.b64encode(headphones.CONFIG.PUSHBULLET_APIKEY + ":")},
body=json.dumps(data))
response = http_handler.getresponse()
request_status = response.status
logger.debug(u"PushBullet response status: %r" % request_status)
logger.debug(u"PushBullet response headers: %r" % response.getheaders())
logger.debug(u"PushBullet response body: %r" % response.read())

if request_status == 200:
logger.info(u"PushBullet notifications sent.")
return True
elif request_status >= 400 and request_status < 500:
logger.info(u"PushBullet request failed: %s" % response.reason)
return False
else:
logger.info(u"PushBullet notification failed serverside.")
return False

def updateLibrary(self):
#For uniformity reasons not removed
return
'body': message}

def test(self, apikey, deviceid):
if self.deviceid:
data['device_iden'] = self.deviceid

self.enabled = True
self.apikey = apikey
self.deviceid = deviceid
headers={'Content-type': "application/json",
'Authorization': 'Bearer ' + headphones.CONFIG.PUSHBULLET_APIKEY}

self.notify('Main Screen Activate', 'Test Message')
response = request.request_json(url, method="post", headers=headers, data=json.dumps(data))

if response:
logger.info(u"PushBullet notifications sent.")
return True
else:
logger.info(u"PushBullet notification failed.")
return False

class PUSHALOT(object):

Expand Down
2 changes: 1 addition & 1 deletion headphones/postprocessor.py
Expand Up @@ -1156,7 +1156,7 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None, keep_orig
verify(release['AlbumID'], folder, forced=True, keep_original_folder=keep_original_folder)
continue
else:
logger.info('Found a (possibly) valid Musicbrainz realse group id in album folder name.')
logger.info('Found a (possibly) valid Musicbrainz release group id in album folder name.')
verify(rgid, folder, forced=True)
continue

Expand Down
2 changes: 1 addition & 1 deletion headphones/request.py
Expand Up @@ -206,7 +206,7 @@ def server_message(response):
message = None

# First attempt is to 'read' the response as HTML
if "text/html" in response.headers.get("content-type"):
if response.headers.get("content-type") and "text/html" in response.headers.get("content-type"):
try:
soup = BeautifulSoup(response.content, "html5lib")
except Exception:
Expand Down

0 comments on commit 24165fb

Please sign in to comment.