Some more big changes: no more 503 errors, add as many artists as you want at the same time, no more DB is locked errors, no more chinese/japanese results in the searches, version number displayed at the bottom, add artists while importing, some other stuff

This commit is contained in:
Remy
2011-07-16 02:25:57 -07:00
parent 4c1ff07b85
commit 75ba22ebdd
14 changed files with 576 additions and 394 deletions

View File

@@ -96,6 +96,9 @@ h1{
.updatebar{
text-align: center;
}
.version{
font-size: 12px;
}
a:link {
color: #5E2612;
text-decoration: none;

84
headphones/db.py Normal file
View File

@@ -0,0 +1,84 @@
# Stolen from sick beards db.py.
from __future__ import with_statement
import os
import sqlite3
import threading
import time
import headphones
from headphones import logger
db_lock = threading.Lock()
def dbFilename(filename="headphones.db"):
return os.path.join(headphones.DATA_DIR, filename)
class DBConnection:
def __init__(self, filename="headphones.db"):
self.filename = filename
self.connection = sqlite3.connect(dbFilename(filename), 20)
self.connection.row_factory = sqlite3.Row
def action(self, query, args=None):
with db_lock:
if query == None:
return
sqlResult = None
attempt = 0
while attempt < 5:
try:
if args == None:
#logger.debug(self.filename+": "+query)
sqlResult = self.connection.execute(query)
else:
#logger.debug(self.filename+": "+query+" with args "+str(args))
sqlResult = self.connection.execute(query, args)
self.connection.commit()
break
except sqlite3.OperationalError, e:
if "unable to open database file" in e.message or "database is locked" in e.message:
logger.warn('Database Error: %s' % e)
attempt += 1
time.sleep(1)
else:
logger.error('Database error: %s' % e)
raise
except sqlite3.DatabaseError, e:
logger.error('Fatal Error executing %s :: %s' % (command, e))
raise
return sqlResult
def select(self, query, args=None):
sqlResults = self.action(query, args).fetchall()
if sqlResults == None:
return []
return sqlResults
def upsert(self, tableName, valueDict, keyDict):
changesBefore = self.connection.total_changes
genParams = lambda myDict : [x + " = ?" for x in myDict.keys()]
query = "UPDATE "+tableName+" SET " + ", ".join(genParams(valueDict)) + " WHERE " + " AND ".join(genParams(keyDict))
self.action(query, valueDict.values() + keyDict.values())
if self.connection.total_changes == changesBefore:
query = "INSERT INTO "+tableName+" (" + ", ".join(valueDict.keys() + keyDict.keys()) + ")" + \
" VALUES (" + ", ".join(["?"] * len(valueDict.keys() + keyDict.keys())) + ")"
self.action(query, valueDict.values() + keyDict.values())

View File

@@ -1,6 +1,11 @@
import time
from operator import itemgetter
import datetime
def multikeysort(items, columns):
from operator import itemgetter
comparers = [ ((itemgetter(col[1:].strip()), -1) if col.startswith('-') else (itemgetter(col.strip()), 1)) for col in columns]
def comparer(left, right):
for fn, mult in comparers:
result = cmp(fn(left), fn(right))
@@ -8,6 +13,7 @@ def multikeysort(items, columns):
return mult * result
else:
return 0
return sorted(items, cmp=comparer)
def checked(variable):
@@ -55,4 +61,18 @@ def latinToAscii(unicrap):
pass
else:
r += str(i)
return r
return r
def convert_milliseconds(ms):
seconds = ms/1000
gmtime = time.gmtime(seconds)
minutes = time.strftime("%M:%S", gmtime)
return minutes
def today():
today = datetime.date.today()
yyyymmdd = datetime.date.isoformat(today)
return yyyymmdd

155
headphones/importer.py Normal file
View File

@@ -0,0 +1,155 @@
from lib.pyItunes import *
from lib.configobj import ConfigObj
import time
import os
from lib.beets.mediafile import MediaFile
import headphones
from headphones import logger, helpers, db, mb
various_artists_mbid = '89ad4ac3-39f7-470e-963a-56509c546377'
def scanMusic(dir=None):
if not dir:
dir = headphones.MUSIC_DIR
results = []
for r,d,f in os.walk(unicode(dir)):
for files in f:
if any(files.endswith(x) for x in (".mp3", ".flac", ".aac", ".ogg", ".ape")):
results.append(os.path.join(r,files))
logger.info(u'%i music files found' % len(results))
if results:
lst = []
myDB = db.DBConnection()
myDB.action('''DELETE from have''')
for song in results:
try:
f = MediaFile(song)
except:
logger.info("Could not read file: '" + song + "'")
else:
if f.albumartist:
artist = f.albumartist
elif f.artist:
artist = f.artist
else:
continue
myDB.action('INSERT INTO have VALUES( ?, ?, ?, ?, ?, ?, ?, ?, ?)', [artist, f.album, f.track, f.title, f.length, f.bitrate, f.genre, f.date, f.mb_trackid])
lst.append(artist)
artistlist = {}.fromkeys(lst).keys()
logger.info(u"Preparing to import %i artists" % len(artistlist))
artistlist_to_mbids(artistlist)
def itunesImport(pathtoxml):
if os.path.splitext(pathtoxml)[1] == '.xml':
logger.info(u"Loading xml file from"+ pathtoxml)
pl = XMLLibraryParser(pathtoxml)
l = Library(pl.dictionary)
lst = []
for song in l.songs:
lst.append(song.artist)
rawlist = {}.fromkeys(lst).keys()
artistlist = [f for f in rawlist if f != None]
else:
rawlist = os.listdir(pathtoxml)
logger.info(u"Loading artists from directory:" +pathtoxml)
exclude = ['.ds_store', 'various artists', 'untitled folder', 'va']
artistlist = [f for f in rawlist if f.lower() not in exclude]
artistlist_to_mbids(artistlist)
def artistlist_to_mbids(artistlist):
for artist in artistlist:
results = mb.findArtist(artist, limit=1)
artistid = results[0]['id']
if artistid != various_artists_mbid:
addArtisttoDB(artistid)
def addArtisttoDB(artistid):
if artistid == various_artists_mbid:
logger.warn('Cannot import Various Artists.')
return
myDB = db.DBConnection()
artistlist = myDB.select('SELECT ArtistID, ArtistName from artists WHERE ArtistID=?', [artistid])
if any(artistid in x for x in artistlist):
logger.info(artistlist[0][1] + u" is already in the database, skipping")
return
artist = mb.getArtist(artistid)
if artist['artist_name'].startswith('The '):
sortname = artist['artist_name'][4:]
else:
sortname = artist['artist_name']
controlValueDict = {"ArtistID": artistid}
newValueDict = {"ArtistName": artist['artist_name'],
"ArtistSortName": sortname,
"DateAdded": helpers.today(),
"Status": "Loading"}
myDB.upsert("artists", newValueDict, controlValueDict)
for rg in artist['releasegroups']:
rgid = rg['id']
try:
releaseid = mb.getReleaseGroup(rgid)
except Exception, e:
logger.info('Unable to get release information for %s - it may not be a valid release group' % rg['title'])
continue
release = mb.getRelease(releaseid)
logger.info(u"Now adding album: " + release['title']+ " to the database")
controlValueDict = {"AlbumID": release['id']}
newValueDict = {"ArtistID": artistid,
"ArtistName": artist['artist_name'],
"AlbumTitle": rg['title'],
"AlbumASIN": release['asin'],
"ReleaseDate": release['date'],
"DateAdded": helpers.today(),
"Status": "Skipped"
}
myDB.upsert("albums", newValueDict, controlValueDict)
latestrelease = myDB.select("SELECT ReleaseDate, DateAdded from albums WHERE AlbumID=?", [release['id']])
if latestrelease[0][0] > latestrelease[0][1]:
logger.info(release['title'] + u" is an upcoming album. Setting its status to 'Wanted'...")
controlValueDict = {"AlbumID": release['id']}
newValueDict = {"Status": "Wanted"}
myDB.upsert("albums", newValueDict, controlValueDict)
for track in release['tracks']:
myDB.action('INSERT INTO tracks VALUES( ?, ?, ?, ?, ?, ?, ?, ?)', [artistid, artist['artist_name'], rg['title'], release['asin'], release['id'], track['title'], track['duration'], track['id']])
controlValueDict = {"ArtistID": artistid}
newValueDict = {"Status": "Active"}
myDB.upsert("artists", newValueDict, controlValueDict)

View File

@@ -1,133 +0,0 @@
from lib.pyItunes import *
from lib.configobj import ConfigObj
import lib.musicbrainz2.webservice as ws
import lib.musicbrainz2.model as m
import lib.musicbrainz2.utils as u
from headphones.mb import getReleaseGroup
import string
import time
import os
import sqlite3
from lib.beets.mediafile import MediaFile
import headphones
from headphones import logger, helpers
def scanMusic(dir=None):
if not dir:
dir = headphones.MUSIC_DIR
results = []
for r,d,f in os.walk(unicode(dir)):
for files in f:
if any(files.endswith(x) for x in (".mp3", ".flac", ".aac", ".ogg", ".ape")):
results.append(os.path.join(r,files))
logger.info(u'%i music files found' % len(results))
if results:
lst = []
# open db connection to write songs you have
conn=sqlite3.connect(headphones.DB_FILE)
c=conn.cursor()
c.execute('''DELETE from have''')
for song in results:
try:
f = MediaFile(song)
except:
logger.info("Could not read file: '" + song + "'")
else:
if not f.artist:
pass
else:
c.execute('INSERT INTO have VALUES( ?, ?, ?, ?, ?, ?, ?, ?, ?)', (f.artist, f.album, f.track, f.title, f.length, f.bitrate, f.genre, f.date, f.mb_trackid))
lst.append(f.artist)
conn.commit()
c.close()
artistlist = {}.fromkeys(lst).keys()
logger.info(u"Preparing to import %i artists" % len(artistlist))
importartist(artistlist)
def itunesImport(pathtoxml):
if os.path.splitext(pathtoxml)[1] == '.xml':
logger.info(u"Loading xml file from"+ pathtoxml)
pl = XMLLibraryParser(pathtoxml)
l = Library(pl.dictionary)
lst = []
for song in l.songs:
lst.append(song.artist)
rawlist = {}.fromkeys(lst).keys()
artistlist = [f for f in rawlist if f != None]
importartist(artistlist)
else:
rawlist = os.listdir(pathtoxml)
logger.info(u"Loading artists from directory:" +pathtoxml)
exclude = ['.ds_store', 'various artists', 'untitled folder', 'va']
artistlist = [f for f in rawlist if f.lower() not in exclude]
importartist(artistlist)
def importartist(artistlist):
for name in artistlist:
logger.info(u"Querying MusicBrainz for: "+name)
artistResults = ws.Query().getArtists(ws.ArtistFilter(string.replace(name, '&#38;', '%38'), limit=1))
time.sleep(1)
for result in artistResults:
if result.artist.name == 'Various Artists':
logger.info(u"Top result is Various Artists. Skipping.")
else:
logger.info(u"Found best match: "+result.artist.name+". Gathering album information...")
artistid = u.extractUuid(result.artist.id)
inc = ws.ArtistIncludes(releases=(m.Release.TYPE_OFFICIAL, m.Release.TYPE_ALBUM), releaseGroups=True)
artist = ws.Query().getArtistById(artistid, inc)
time.sleep(1)
conn=sqlite3.connect(headphones.DB_FILE)
c=conn.cursor()
c.execute('SELECT ArtistID from artists')
artistlist = c.fetchall()
if any(artistid in x for x in artistlist):
logger.info(result.artist.name + u" is already in the database, skipping")
else:
if artist.name.startswith('The '):
sortname = artist.name[4:]
else:
sortname = artist.name
c.execute('INSERT INTO artists VALUES( ?, ?, ?, CURRENT_DATE, ?)', (artistid, artist.name, sortname, 'Active'))
for rg in artist.getReleaseGroups():
rgid = u.extractUuid(rg.id)
releaseid = getReleaseGroup(rgid)
time.sleep(1)
inc = ws.ReleaseIncludes(artist=True, releaseEvents= True, tracks= True, releaseGroup=True)
results = ws.Query().getReleaseById(releaseid, inc)
time.sleep(1)
logger.info(u"Now adding album: " + results.title+ " to the database")
c.execute('INSERT INTO albums VALUES( ?, ?, ?, ?, ?, CURRENT_DATE, ?, ?)', (artistid, results.artist.name, results.title, results.asin, results.getEarliestReleaseDate(), u.extractUuid(results.id), 'Skipped'))
conn.commit()
c.execute('SELECT ReleaseDate, DateAdded from albums WHERE AlbumID="%s"' % u.extractUuid(results.id))
latestrelease = c.fetchall()
if latestrelease[0][0] > latestrelease[0][1]:
logger.info(results.title + u" is an upcoming album. Setting its status to 'Wanted'...")
c.execute('UPDATE albums SET Status = "Wanted" WHERE AlbumID="%s"' % u.extractUuid(results.id))
else:
pass
for track in results.tracks:
c.execute('INSERT INTO tracks VALUES( ?, ?, ?, ?, ?, ?, ?, ?)', (artistid, results.artist.name, results.title, results.asin, u.extractUuid(results.id), track.title, track.duration, u.extractUuid(track.id)))
conn.commit()
c.close()

View File

@@ -37,7 +37,7 @@ class RotatingLogger(object):
if not quiet:
consolehandler = logging.StreamHandler()
consolehandler.setLevel(logging.DEBUG)
consolehandler.setLevel(logging.INFO)
consoleformatter = logging.Formatter('%(asctime)s - %(levelname)s :: %(message)s', '%d-%b-%Y %H:%M:%S')

View File

@@ -1,4 +1,7 @@
from __future__ import with_statement
import time
import threading
import lib.musicbrainz2.webservice as ws
import lib.musicbrainz2.model as m
@@ -6,70 +9,194 @@ import lib.musicbrainz2.utils as u
from lib.musicbrainz2.webservice import WebServiceError
from headphones import logger
from headphones.helpers import multikeysort
q = ws.Query()
mb_lock = threading.Lock()
def findArtist(name, limit=1):
artistlist = []
artistResults = q.getArtists(ws.ArtistFilter(name=name, limit=limit))
for result in artistResults:
artistid = u.extractUuid(result.artist.id)
artistlist.append([result.artist.name, artistid])
with mb_lock:
artistlist = []
attempt = 0
return artistlist
while attempt < 5:
try:
artistResults = q.getArtists(ws.ArtistFilter(query=name, limit=limit))
break
except WebServiceError, e:
logger.warn('Attempt to retrieve information from MusicBrainz failed: %s' % e)
attempt += 1
time.sleep(1)
time.sleep(1)
for result in artistResults:
artistlist.append({
'name': result.artist.name,
'uniquename': result.artist.getUniqueName(),
'id': u.extractUuid(result.artist.id),
'url': result.artist.id,
'score': result.score
})
return artistlist
def getArtist(artistid):
rglist = []
#Get all official release groups
inc = ws.ArtistIncludes(releases=(m.Release.TYPE_OFFICIAL, m.Release.TYPE_ALBUM), ratings=False, releaseGroups=True)
artist = q.getArtistById(artistid, inc)
with mb_lock:
for rg in artist.getReleaseGroups():
artist_dict = {}
#Get all official release groups
inc = ws.ArtistIncludes(releases=(m.Release.TYPE_OFFICIAL, m.Release.TYPE_ALBUM), releaseGroups=True)
rgid = u.extractUuid(rg.id)
rglist.append([rg.title, rgid])
return rglist
attempt = 0
while attempt < 5:
try:
artist = q.getArtistById(artistid, inc)
break
except WebServiceError, e:
logger.warn('Attempt to retrieve information from MusicBrainz failed: %s' % e)
attempt += 1
time.sleep(1)
time.sleep(1)
artist_dict['artist_name'] = artist.name
artist_dict['artist_sortname'] = artist.sortName
artist_dict['artist_uniquename'] = artist.getUniqueName()
artist_dict['artist_type'] = u.extractFragment(artist.type)
artist_dict['artist_begindate'] = artist.beginDate
artist_dict['artist_endDate'] = artist.endDate
releasegroups = []
for rg in artist.getReleaseGroups():
releasegroups.append({
'title': rg.title,
'id': u.extractUuid(rg.id),
'url': rg.id,
'type': u.getReleaseTypeName(rg.type)
})
artist_dict['releasegroups'] = releasegroups
return artist_dict
def getReleaseGroup(rgid):
releaselist = []
"""
Returns the best release out of any given release group
"""
with mb_lock:
inc = ws.ReleaseGroupIncludes(releases=True)
releaseGroup = q.getReleaseGroupById(rgid, inc)
time.sleep(1)
# I think for now we have to make separate queries for each release, in order
# to get more detailed release info (ASIN, track count, etc.)
for release in releaseGroup.releases:
releaseid = u.extractUuid(release.id)
inc = ws.ReleaseIncludes(tracks=True)
releaselist = []
inc = ws.ReleaseGroupIncludes(releases=True)
attempt = 0
while attempt < 5:
try:
releaseGroup = q.getReleaseGroupById(rgid, inc)
break
except WebServiceError, e:
logger.warn('Attempt to retrieve information from MusicBrainz failed: %s' % e)
attempt += 1
time.sleep(1)
time.sleep(1)
# I think for now we have to make separate queries for each release, in order
# to get more detailed release info (ASIN, track count, etc.)
for release in releaseGroup.releases:
inc = ws.ReleaseIncludes(tracks=True)
attempt = 0
while attempt < 5:
try:
releaseResult = q.getReleaseById(release.id, inc)
break
except WebServiceError, e:
logger.warn('Attempt to retrieve information for %s from MusicBrainz failed: %s' % (releaseResult.title, e))
attempt += 1
time.sleep(1)
if not releaseResult:
continue
time.sleep(1)
release_dict = {
'asin': bool(releaseResult.asin),
'tracks': len(releaseResult.getTracks()),
'releaseid': u.extractUuid(releaseResult.id)
}
releaselist.append(release_dict)
a = multikeysort(releaselist, ['-asin', '-tracks'])
releaseid = a[0]['releaseid']
return releaseid
def getRelease(releaseid):
"""
Deep release search to get track info
"""
with mb_lock:
release = {}
inc = ws.ReleaseIncludes(tracks=True, releaseEvents=True)
attempt = 0
while attempt < 5:
try:
results = q.getReleaseById(releaseid, inc)
break
except WebServiceError, e:
logger.warn('Attempt to retrieve information from MusicBrainz failed: %s' % e)
attempt += 1
time.sleep(1)
releaseResult = q.getReleaseById(releaseid, inc)
time.sleep(1)
release_dict = {
'asin': bool(releaseResult.asin),
'tracks': len(releaseResult.getTracks()),
'releaseid': u.extractUuid(releaseResult.id)
}
release['title'] = results.title
release['id'] = u.extractUuid(results.id)
release['asin'] = results.asin
release['date'] = results.getEarliestReleaseDate()
releaselist.append(release_dict)
a = multikeysort(releaselist, ['-asin', '-tracks'])
releaseid = a[0]['releaseid']
tracks = []
i = 1
for track in results.tracks:
tracks.append({
'number': i,
'title': track.title,
'id': u.extractUuid(track.id),
'url': track.id,
'duration': track.duration
})
i += 1
release['tracks'] = tracks
return release
return releaseid
def getExtras(artistid):
@@ -91,4 +218,4 @@ def getExtras(artistid):
print results.title
print u.getReleaseTypeName(results.releaseGroup.type)

View File

@@ -1,23 +1,19 @@
import urllib
import string
import lib.feedparser as feedparser
import sqlite3
import os, re
import headphones
from headphones import logger
from headphones import logger, db
def searchNZB(albumid=None):
conn=sqlite3.connect(headphones.DB_FILE)
c=conn.cursor()
myDB = db.DBConnection()
if albumid:
c.execute('SELECT ArtistName, AlbumTitle, AlbumID, ReleaseDate from albums WHERE Status="Wanted" AND AlbumID="%s"' % albumid)
results = myDB.select('SELECT ArtistName, AlbumTitle, AlbumID, ReleaseDate from albums WHERE Status="Wanted" AND AlbumID=?', [albumid])
else:
c.execute('SELECT ArtistName, AlbumTitle, AlbumID, ReleaseDate from albums WHERE Status="Wanted"')
results = c.fetchall()
results = myDB.select('SELECT ArtistName, AlbumTitle, AlbumID, ReleaseDate from albums WHERE Status="Wanted"')
for albums in results:
@@ -176,10 +172,9 @@ def searchNZB(albumid=None):
logger.error(u"Unable to send link. Are you sure the host address is correct?")
break
c.execute('UPDATE albums SET status = "Snatched" WHERE AlbumID="%s"' % albums[2])
c.execute('INSERT INTO snatched VALUES( ?, ?, ?, ?, CURRENT_DATE, ?)', (albums[2], bestqual[0], bestqual[1], bestqual[2], "Snatched"))
conn.commit()
c.close()
myDB.action('UPDATE albums SET status = "Snatched" WHERE AlbumID=?', [albums[2]])
myDB.action('INSERT INTO snatched VALUES( ?, ?, ?, ?, CURRENT_DATE, ?)', [albums[2], bestqual[0], bestqual[1], bestqual[2], "Snatched"])
elif headphones.BLACKHOLE:
@@ -192,10 +187,9 @@ def searchNZB(albumid=None):
logger.error('Couldn\'t retrieve NZB: %s' % e)
break
c.execute('UPDATE albums SET status = "Snatched" WHERE AlbumID="%s"' % albums[2])
c.execute('INSERT INTO snatched VALUES( ?, ?, ?, ?, CURRENT_DATE, ?)', (albums[2], bestqual[0], bestqual[1], bestqual[2], "Snatched"))
conn.commit()
c.close()
myDB.action('UPDATE albums SET status = "Snatched" WHERE AlbumID=?', [albums[2]])
myDB.action('INSERT INTO snatched VALUES( ?, ?, ?, ?, CURRENT_DATE, ?)', [albums[2], bestqual[0], bestqual[1], bestqual[2], "Snatched"])

View File

@@ -47,7 +47,7 @@ _footer = '''
<input type="hidden" name="hosted_button_id" value="93FFC6WDV97QS">
<input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
<img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1">
</form>
</form><br /><div class="version">Version: %s</div>
</div></div>
</body>
</html>'''

View File

@@ -2,20 +2,17 @@ import lib.musicbrainz2.webservice as ws
import lib.musicbrainz2.model as m
import lib.musicbrainz2.utils as u
from headphones.mb import getReleaseGroup
import sqlite3
import time
import os
import headphones
from headphones import logger
from headphones import logger, db, mb
def dbUpdate():
conn=sqlite3.connect(headphones.DB_FILE)
c=conn.cursor()
c.execute('SELECT ArtistID, ArtistName from artists WHERE Status="Active"')
activeartists = c.fetchall()
myDB = db.DBConnection()
activeartists = myDB.select('SELECT ArtistID, ArtistName from artists WHERE Status="Active"')
i = 0
@@ -25,53 +22,46 @@ def dbUpdate():
artistname = activeartists[i][1]
logger.info(u"Updating album information for artist: " + artistname)
c.execute('SELECT AlbumID from albums WHERE ArtistID="%s"' % artistid)
albumlist = c.fetchall()
artist = mb.getArtist(artistid)
inc = ws.ArtistIncludes(releases=(m.Release.TYPE_OFFICIAL, m.Release.TYPE_ALBUM), releaseGroups=True)
artist = ws.Query().getArtistById(artistid, inc)
time.sleep(1)
for rg in artist.getReleaseGroups():
for rg in artist['releasegroups']:
rgid = rg['id']
releaseid = mb.getReleaseGroup(rgid)
results = mb.getRelease(releaseid)
albumlist = myDB.select('SELECT AlbumID from albums WHERE ArtistID=?', [artistid])
rgid = u.extractUuid(rg.id)
releaseid = getReleaseGroup(rgid)
inc = ws.ReleaseIncludes(artist=True, releaseEvents= True, tracks= True, releaseGroup=True)
results = ws.Query().getReleaseById(releaseid, inc)
time.sleep(1)
if any(releaseid in x for x in albumlist):
logger.info(results.title + " already exists in the database. Updating ASIN, Release Date, Tracks")
logger.info(results['title'] + " already exists in the database. Updating ASIN, Release Date, Tracks")
c.execute('UPDATE albums SET AlbumASIN="%s", ReleaseDate="%s" WHERE AlbumID="%s"' % (results.asin, results.getEarliestReleaseDate(), u.extractUuid(results.id)))
myDB.action('UPDATE albums SET AlbumASIN=?, ReleaseDate=? WHERE AlbumID=?', [results['asin'], results['date'], results['id']])
for track in results.tracks:
c.execute('UPDATE tracks SET TrackDuration="%s" WHERE AlbumID="%s" AND TrackID="%s"' % (track.duration, u.extractUuid(results.id), u.extractUuid(track.id)))
conn.commit()
for track in results['tracks']:
myDB.action('UPDATE tracks SET TrackDuration=? WHERE AlbumID=? AND TrackID=?', [track['duration'], results['id'], track['id']])
else:
logger.info(u"New album found! Adding "+results.title+"to the database...")
c.execute('INSERT INTO albums VALUES( ?, ?, ?, ?, ?, CURRENT_DATE, ?, ?)', (artistid, results.artist.name, results.title, results.asin, results.getEarliestReleaseDate(), u.extractUuid(results.id), 'Skipped'))
conn.commit()
c.execute('SELECT ReleaseDate, DateAdded from albums WHERE AlbumID="%s"' % u.extractUuid(results.id))
latestrelease = c.fetchall()
logger.info(u"New album found! Adding "+results['title']+"to the database...")
myDB.action('INSERT INTO albums VALUES( ?, ?, ?, ?, ?, CURRENT_DATE, ?, ?)', [artistid, artist['artist_name'], rg['title'], results['asin'], results['date'], results['id'], 'Skipped'])
latestrelease = myDB.select('SELECT ReleaseDate, DateAdded from albums WHERE AlbumID=?', [results['id']])
if latestrelease[0][0] > latestrelease[0][1]:
c.execute('UPDATE albums SET Status = "Wanted" WHERE AlbumID="%s"' % u.extractUuid(results.id))
myDB.action('UPDATE albums SET Status = "Wanted" WHERE AlbumID=?', results['id'])
else:
pass
for track in results.tracks:
for track in results['tracks']:
c.execute('INSERT INTO tracks VALUES( ?, ?, ?, ?, ?, ?, ?, ?)', (artistid, results.artist.name, results.title, results.asin, u.extractUuid(results.id), track.title, track.duration, u.extractUuid(track.id)))
conn.commit()
myDB.action('INSERT INTO tracks VALUES( ?, ?, ?, ?, ?, ?, ?, ?)', [artistid, artist['artist_name'], rg['title'], results['asin'], results['id'], track['title'], track['duration'], track['id']])
i += 1
conn.commit()
c.close()
conn.close()

View File

@@ -6,15 +6,13 @@ import lib.musicbrainz2.webservice as ws
import lib.musicbrainz2.model as m
import lib.musicbrainz2.utils as u
import string
import time
import datetime
import sqlite3
import threading
import headphones
from headphones.mb import getReleaseGroup
from headphones import templates, logger, searcher
from headphones import templates, logger, searcher, db, importer, helpers, mb
from headphones.helpers import checked
@@ -34,11 +32,8 @@ class WebInterface(object):
''' % (headphones.CURRENT_VERSION, headphones.LATEST_VERSION, headphones.COMMITS_BEHIND))
page.append(templates._logobar)
page.append(templates._nav)
conn=sqlite3.connect(headphones.DB_FILE)
c=conn.cursor()
c.execute('SELECT ArtistName, ArtistID, Status from artists order by ArtistSortName collate nocase')
results = c.fetchall()
myDB = db.DBConnection()
results = myDB.select('SELECT ArtistName, ArtistID, Status from artists order by ArtistSortName collate nocase')
if len(results):
i = 0
page.append('''<div class="table"><table border="0" cellpadding="3">
@@ -49,14 +44,11 @@ class WebInterface(object):
<th align="center">Have</th>
</tr>''')
while i < len(results):
c.execute('''SELECT AlbumTitle, ReleaseDate, DateAdded, AlbumID from albums WHERE ArtistID='%s' order by ReleaseDate DESC''' % results[i][1])
latestalbum = c.fetchall()
c.execute('''SELECT TrackTitle from tracks WHERE ArtistID="%s"''' % results[i][1])
totaltracks = len(c.fetchall())
c.execute('''SELECT TrackTitle from have WHERE ArtistName like "%s"''' % results[i][0])
havetracks = len(c.fetchall())
latestalbum = myDB.select('SELECT AlbumTitle, ReleaseDate, DateAdded, AlbumID from albums WHERE ArtistID=? order by ReleaseDate DESC', [results[i][1]])
totaltracks = len(myDB.select('SELECT TrackTitle from tracks WHERE ArtistID=?', [results[i][1]]))
havetracks = len(myDB.select('SELECT TrackTitle from have WHERE ArtistName like ?', [results[i][0]]))
try:
percent = (havetracks*100)/totaltracks
percent = (havetracks*100.0)/totaltracks
if percent > 100:
percent = 100
except ZeroDivisionError:
@@ -74,6 +66,8 @@ class WebInterface(object):
releaseDate = ""
if results[i][2] == 'Paused':
newStatus = '''<font color="red"><b>%s</b></font>(<A class="external" href="resumeArtist?ArtistID=%s">resume</a>)''' % (results[i][2], results[i][1])
elif results[i][2] == 'Loading':
newStatus = '''<a class="gray">Loading...</a>'''
else:
newStatus = '''%s(<A class="external" href="pauseArtist?ArtistID=%s">pause</a>)''' % (results[i][2], results[i][1])
page.append('''<tr><td align="left" width="300"><a href="artistPage?ArtistID=%s">%s</a>
@@ -83,9 +77,9 @@ class WebInterface(object):
<td><div class="progress-container"><div style="width: %s%%"></div></div></td></tr>
''' % (results[i][1], results[i][0], results[i][1], results[i][1], newStatus, newalbumName, releaseDate, percent))
i = i+1
c.close()
page.append('''</table></div>''')
page.append(templates._footer)
page.append(templates._footer % headphones.CURRENT_VERSION)
else:
page.append("""<div class="datanil">Add some artists to the database!</div>""")
@@ -97,12 +91,10 @@ class WebInterface(object):
page = [templates._header]
page.append(templates._logobar)
page.append(templates._nav)
conn=sqlite3.connect(headphones.DB_FILE)
c=conn.cursor()
c.execute('''SELECT ArtistName from artists WHERE ArtistID="%s"''' % ArtistID)
artistname = c.fetchall()
c.execute('''SELECT AlbumTitle, ReleaseDate, AlbumID, Status, ArtistName, AlbumASIN from albums WHERE ArtistID="%s" order by ReleaseDate DESC''' % ArtistID)
results = c.fetchall()
myDB = db.DBConnection()
results = myDB.select('SELECT AlbumTitle, ReleaseDate, AlbumID, Status, ArtistName, AlbumASIN from albums WHERE ArtistID=? order by ReleaseDate DESC', [ArtistID])
i = 0
page.append('''<div class="table"><table border="0" cellpadding="3">
<tr><p align="center">%s <br /></p></tr>
@@ -112,12 +104,10 @@ class WebInterface(object):
<th align="center" width="100">Release Date</th>
<th align="center" width="180">Status</th>
<th align="center">Have</th>
</tr>''' % (artistname[0]))
</tr>''' % (results[0][4]))
while i < len(results):
c.execute('''SELECT TrackTitle from tracks WHERE AlbumID="%s"''' % results[i][2])
totaltracks = len(c.fetchall())
c.execute('''SELECT TrackTitle from have WHERE ArtistName like ? AND AlbumTitle like ?''', (results[i][4], results[i][0]))
havetracks = len(c.fetchall())
totaltracks = len(myDB.select('SELECT TrackTitle from tracks WHERE AlbumID=?', [results[i][2]]))
havetracks = len(myDB.select('SELECT TrackTitle from have WHERE ArtistName like ? AND AlbumTitle like ?', [results[i][4], results[i][0]]))
try:
percent = (havetracks*100)/totaltracks
if percent > 100:
@@ -141,9 +131,9 @@ class WebInterface(object):
<td align="center">%s</td>
<td><div class="progress-container"><div style="width: %s%%"></div></div></td></tr>''' % (results[i][5], results[i][2], results[i][0], results[i][2], results[i][1], newStatus, percent))
i = i+1
c.close()
page.append('''</table></div>''')
page.append(templates._footer)
page.append(templates._footer % headphones.CURRENT_VERSION)
return page
artistPage.exposed = True
@@ -152,10 +142,8 @@ class WebInterface(object):
page = [templates._header]
page.append(templates._logobar)
page.append(templates._nav)
conn=sqlite3.connect(headphones.DB_FILE)
c=conn.cursor()
c.execute('''SELECT ArtistID, ArtistName, AlbumTitle, TrackTitle, TrackDuration, TrackID, AlbumASIN from tracks WHERE AlbumID="%s"''' % AlbumID)
results = c.fetchall()
myDB = db.DBConnection()
results = myDB.select('SELECT ArtistID, ArtistName, AlbumTitle, TrackTitle, TrackDuration, TrackID, AlbumASIN from tracks WHERE AlbumID=?', [AlbumID])
if results[0][6]:
albumart = '''<br /><img src="http://ec1.images-amazon.com/images/P/%s.01.LZZZZZZZ.jpg" height="200" width="200"><br /><br />''' % results[0][6]
@@ -172,14 +160,14 @@ class WebInterface(object):
<th> </th>
</tr>''' % (results[0][0], results[0][1], results[0][2], AlbumID, results[0][0], albumart))
while i < len(results):
c.execute('''SELECT TrackTitle from have WHERE ArtistName like ? AND AlbumTitle like ? AND TrackTitle like ?''', (results[i][1], results[i][2], results[i][3]))
trackmatches = c.fetchall()
trackmatches = myDB.select('SELECT TrackTitle from have WHERE ArtistName like ? AND AlbumTitle like ? AND TrackTitle like ?', [results[i][1], results[i][2], results[i][3]])
if len(trackmatches):
have = '<img src="images/checkmark.png" width="20px">'
else:
have = ''
if results[i][4]:
duration = time.strftime("%M:%S", time.gmtime(int(results[i][4])/1000))
duration = helpers.convert_milliseconds(results[i][4])
else:
duration = 'n/a'
page.append('''<tr><td align="left" width="120">%s</td>
@@ -187,9 +175,9 @@ class WebInterface(object):
<td align="center">%s</td>
<td>%s</td></tr>''' % (i+1, results[i][3], results[i][5], duration, have))
i = i+1
c.close()
page.append('''</table></div>''')
page.append(templates._footer)
page.append(templates._footer % headphones.CURRENT_VERSION)
return page
albumPage.exposed = True
@@ -203,7 +191,7 @@ class WebInterface(object):
if len(name) == 0 or name == 'Add an artist':
raise cherrypy.HTTPRedirect("home")
else:
artistResults = ws.Query().getArtists(ws.ArtistFilter(string.replace(name, '&', '%38'), limit=8))
artistResults = mb.findArtist(name, limit=10)
if len(artistResults) == 0:
logger.info(u"No results found for " + name)
page.append('''<div class="table"><p class="center">No results! <a class="blue" href="home">Go back</a></p></div>''')
@@ -211,20 +199,13 @@ class WebInterface(object):
elif len(artistResults) > 1:
page.append('''<div class="table"><p class="center">Search returned multiple artists. Click the artist you want to add:</p>''')
for result in artistResults:
artist = result.artist
detail = artist.getDisambiguation()
if detail:
disambiguation = '(%s)' % detail
else:
disambiguation = ''
page.append('''<p class="mediumtext"><a href="addArtist?artistid=%s">%s %s</a> (<a class="externalred" href="artistInfo?artistid=%s">more info</a>)</p>''' % (u.extractUuid(artist.id), artist.name, disambiguation, u.extractUuid(artist.id)))
page.append('''<p class="mediumtext"><a href="addArtist?artistid=%s">%s</a> (<a class="externalred" href="artistInfo?artistid=%s">more info</a>)</p>''' % (result['id'], result['uniquename'], result['id']))
page.append('''</div>''')
return page
else:
for result in artistResults:
artist = result.artist
logger.info(u"Found one artist matching your search term: " + artist.name +" ("+ artist.id+")")
raise cherrypy.HTTPRedirect("addArtist?artistid=%s" % u.extractUuid(artist.id))
logger.info(u"Found one artist matching your search term: " + result['name'] +" ("+ result['id']+")")
raise cherrypy.HTTPRedirect("addArtist?artistid=%s" % result['id'])
findArtist.exposed = True
@@ -232,123 +213,83 @@ class WebInterface(object):
page = [templates._header]
page.append(templates._logobar)
page.append(templates._nav)
inc = ws.ArtistIncludes(releases=(m.Release.TYPE_OFFICIAL, m.Release.TYPE_ALBUM), releaseGroups=True)
artist = ws.Query().getArtistById(artistid, inc)
page.append('''Artist Name: %s </br> ''' % artist.name)
page.append('''Unique ID: %s </br></br>Albums:<br />''' % u.extractUuid(artist.id))
for rg in artist.getReleaseGroups():
page.append('''%s <br />''' % rg.title)
artist = mb.getArtist(artistid)
page.append('''<div class="table"><p class="center">Artist Information:</p>''')
page.append('''<p class="mediumtext">Artist Name: %s </br> ''' % artist['artist_name'])
page.append('''Unique ID: %s </br></br>Albums:<br />''' % artist['artist_id'])
for rg in artist['releasegroups']:
page.append('''%s <br />''' % rg['title'])
return page
artistInfo.exposed = True
def addArtist(self, artistid):
inc = ws.ArtistIncludes(releases=(m.Release.TYPE_OFFICIAL, m.Release.TYPE_ALBUM), releaseGroups=True)
artist = ws.Query().getArtistById(artistid, inc)
time.sleep(1)
conn=sqlite3.connect(headphones.DB_FILE)
c=conn.cursor()
c.execute('SELECT ArtistID from artists')
artistlist = c.fetchall()
if any(artistid in x for x in artistlist):
page = [templates._header]
page.append
page.append('''%s has already been added. Go <a href="home">back</a>.''' % artist.name)
logger.info(artist.name + u" is already in the database!")
c.close()
return page
else:
logger.info(u"Adding " + artist.name + " to the database.")
if artist.name.startswith('The '):
sortname = artist.name[4:]
else:
sortname = artist.name
c.execute('INSERT INTO artists VALUES( ?, ?, ?, CURRENT_DATE, ?)', (artistid, artist.name, sortname, 'Active'))
for rg in artist.getReleaseGroups():
rgid = u.extractUuid(rg.id)
releaseid = getReleaseGroup(rgid)
inc = ws.ReleaseIncludes(artist=True, releaseEvents= True, tracks= True, releaseGroup=True)
results = ws.Query().getReleaseById(releaseid, inc)
time.sleep(1)
logger.info(u"Now adding album: " + results.title+ " to the database")
c.execute('INSERT INTO albums VALUES( ?, ?, ?, ?, ?, CURRENT_DATE, ?, ?)', (artistid, results.artist.name, results.title, results.asin, results.getEarliestReleaseDate(), u.extractUuid(results.id), 'Skipped'))
c.execute('SELECT ReleaseDate, DateAdded from albums WHERE AlbumID="%s"' % u.extractUuid(results.id))
latestrelease = c.fetchall()
if latestrelease[0][0] > latestrelease[0][1]:
logger.info(results.title + u" is an upcoming album. Setting its status to 'Wanted'...")
c.execute('UPDATE albums SET Status = "Wanted" WHERE AlbumID="%s"' % u.extractUuid(results.id))
else:
pass
for track in results.tracks:
c.execute('INSERT INTO tracks VALUES( ?, ?, ?, ?, ?, ?, ?, ?)', (artistid, results.artist.name, results.title, results.asin, u.extractUuid(results.id), track.title, track.duration, u.extractUuid(track.id)))
conn.commit()
c.close()
raise cherrypy.HTTPRedirect("home")
threading.Thread(target=importer.addArtisttoDB, args=[artistid]).start()
time.sleep(2)
raise cherrypy.HTTPRedirect("home")
addArtist.exposed = True
def pauseArtist(self, ArtistID):
conn=sqlite3.connect(headphones.DB_FILE)
c=conn.cursor()
logger.info(u"Pausing artist: " + ArtistID)
c.execute('UPDATE artists SET status = "Paused" WHERE ArtistId="%s"' % ArtistID)
conn.commit()
c.close()
myDB = db.DBConnection()
controlValueDict = {'ArtistID': ArtistID}
newValueDict = {'Status': 'Paused'}
myDB.upsert("artists", newValueDict, controlValueDict)
raise cherrypy.HTTPRedirect("home")
pauseArtist.exposed = True
def resumeArtist(self, ArtistID):
conn=sqlite3.connect(headphones.DB_FILE)
c=conn.cursor()
logger.info(u"Resuming artist: " + ArtistID)
c.execute('UPDATE artists SET status = "Active" WHERE ArtistId="%s"' % ArtistID)
conn.commit()
c.close()
myDB = db.DBConnection()
controlValueDict = {'ArtistID': ArtistID}
newValueDict = {'Status': 'Active'}
myDB.upsert("artists", newValueDict, controlValueDict)
raise cherrypy.HTTPRedirect("home")
resumeArtist.exposed = True
def deleteArtist(self, ArtistID):
conn=sqlite3.connect(headphones.DB_FILE)
c=conn.cursor()
logger.info(u"Deleting all traces of artist: " + ArtistID)
c.execute('''DELETE from artists WHERE ArtistID="%s"''' % ArtistID)
c.execute('''DELETE from albums WHERE ArtistID="%s"''' % ArtistID)
c.execute('''DELETE from tracks WHERE ArtistID="%s"''' % ArtistID)
conn.commit()
c.close()
myDB = db.DBConnection()
myDB.action('DELETE from artists WHERE ArtistID=?', [ArtistID])
myDB.action('DELETE from albums WHERE ArtistID=?', [ArtistID])
myDB.action('DELETE from tracks WHERE ArtistID=?', [ArtistID])
raise cherrypy.HTTPRedirect("home")
deleteArtist.exposed = True
def queueAlbum(self, AlbumID, ArtistID):
conn=sqlite3.connect(headphones.DB_FILE)
c=conn.cursor()
logger.info(u"Marking album: " + AlbumID + "as wanted...")
c.execute('UPDATE albums SET status = "Wanted" WHERE AlbumID="%s"' % AlbumID)
conn.commit()
c.close()
myDB = db.DBConnection()
controlValueDict = {'AlbumID': AlbumID}
newValueDict = {'Status': 'Wanted'}
myDB.upsert("albums", newValueDict, controlValueDict)
import searcher
searcher.searchNZB(AlbumID)
raise cherrypy.HTTPRedirect("artistPage?ArtistID=%s" % ArtistID)
queueAlbum.exposed = True
def unqueueAlbum(self, AlbumID, ArtistID):
conn=sqlite3.connect(headphones.DB_FILE)
c=conn.cursor()
logger.info(u"Marking album: " + AlbumID + "as skipped...")
c.execute('UPDATE albums SET status = "Skipped" WHERE AlbumID="%s"' % AlbumID)
conn.commit()
c.close()
myDB = db.DBConnection()
controlValueDict = {'AlbumID': AlbumID}
newValueDict = {'Status': 'Skipped'}
myDB.upsert("albums", newValueDict, controlValueDict)
raise cherrypy.HTTPRedirect("artistPage?ArtistID=%s" % ArtistID)
unqueueAlbum.exposed = True
@@ -357,14 +298,11 @@ class WebInterface(object):
page = [templates._header]
page.append(templates._logobar)
page.append(templates._nav)
today = datetime.date.today()
todaysql = datetime.date.isoformat(today)
conn=sqlite3.connect(headphones.DB_FILE)
c=conn.cursor()
c.execute('''SELECT AlbumTitle, ReleaseDate, DateAdded, AlbumASIN, AlbumID, ArtistName, ArtistID from albums WHERE ReleaseDate > date('now') order by ReleaseDate DESC''')
albums = c.fetchall()
c.execute('''SELECT AlbumTitle, ReleaseDate, DateAdded, AlbumASIN, AlbumID, ArtistName, ArtistID from albums WHERE Status="Wanted"''')
wanted = c.fetchall()
myDB = db.DBConnection()
albums = myDB.select("SELECT AlbumTitle, ReleaseDate, DateAdded, AlbumASIN, AlbumID, ArtistName, ArtistID from albums WHERE ReleaseDate > date('now') order by ReleaseDate DESC")
wanted = myDB.select("SELECT AlbumTitle, ReleaseDate, DateAdded, AlbumASIN, AlbumID, ArtistName, ArtistID from albums WHERE Status='Wanted'")
page.append('''<div class="table"><table border="0" cellpadding="3">
<tr>
<th align="center" width="300"></th>
@@ -413,7 +351,7 @@ class WebInterface(object):
i += 1
page.append('''</table></div>''')
if len(albums):
page.append(templates._footer)
page.append(templates._footer % headphones.CURRENT_VERSION)
return page
upcoming.exposed = True
@@ -455,38 +393,40 @@ class WebInterface(object):
<a href="forceSearch">Force Check for Wanted Albums</a><br /><br />
<a href="forceUpdate">Force Update Active Artists</a><br /><br />
<a href="checkGithub">Check for Headphones Updates</a><br /><br /><br /></div></div>''' % (path2, path))
page.append(templates._footer)
page.append(templates._footer % headphones.CURRENT_VERSION)
return page
manage.exposed = True
def importItunes(self, path):
headphones.PATH_TO_XML = path
headphones.config_write()
from headphones import itunesimport
itunesimport.itunesImport(path)
threading.Thread(target=importer.itunesImport, args=[path]).start()
time.sleep(10)
raise cherrypy.HTTPRedirect("home")
importItunes.exposed = True
def musicScan(self, path):
from headphones import itunesimport
headphones.MUSIC_DIR = path
headphones.config_write()
try:
itunesimport.scanMusic(path)
threading.Thread(target=importer.scanMusic, args=[path]).start()
except Exception, e:
logger.error('Unable to complete the scan: %s' % e)
time.sleep(10)
raise cherrypy.HTTPRedirect("home")
musicScan.exposed = True
def forceUpdate(self):
from headphones import updater
updater.dbUpdate()
threading.Thread(target=updater.dbUpdate).start()
time.sleep(5)
raise cherrypy.HTTPRedirect("home")
forceUpdate.exposed = True
def forceSearch(self):
from headphones import searcher
searcher.searchNZB()
threading.Thread(target=searcher.searchNZB).start()
time.sleep(5)
raise cherrypy.HTTPRedirect("home")
forceSearch.exposed = True
@@ -500,10 +440,9 @@ class WebInterface(object):
page = [templates._header]
page.append(templates._logobar)
page.append(templates._nav)
conn=sqlite3.connect(headphones.DB_FILE)
c=conn.cursor()
c.execute('''SELECT AlbumID, Title TEXT, Size INTEGER, URL TEXT, DateAdded TEXT, Status TEXT from snatched order by DateAdded DESC''')
snatched = c.fetchall()
myDB = db.DBConnection()
snatched = myDB.select('''SELECT AlbumID, Title TEXT, Size INTEGER, URL TEXT, DateAdded TEXT, Status TEXT from snatched order by DateAdded DESC''')
page.append('''<div class="table"><table border="0" cellpadding="3">
<tr>
<th align="center" width="300"></th>
@@ -527,17 +466,16 @@ class WebInterface(object):
i += 1
page.append('''</table></div>''')
if len(snatched):
page.append(templates._footer)
page.append(templates._footer % headphones.CURRENT_VERSION)
return page
history.exposed = True
def clearhistory(self):
conn=sqlite3.connect(headphones.DB_FILE)
c=conn.cursor()
logger.info(u"Clearing history")
c.execute('''DELETE from snatched''')
conn.commit()
c.close()
myDB = db.DBConnection()
myDB.action('''DELETE from snatched''')
raise cherrypy.HTTPRedirect("history")
clearhistory.exposed = True
@@ -577,7 +515,7 @@ class WebInterface(object):
checked(headphones.CLEANUP_FILES),
checked(headphones.ADD_ALBUM_ART)
))
#page.append(templates._footer)
page.append(templates._footer % headphones.CURRENT_VERSION)
return page
config.exposed = True

View File

@@ -33,6 +33,10 @@ def initialize(options={}):
'/js':{
'tools.staticdir.on': True,
'tools.staticdir.dir': "js"
},
'/favicon.ico':{
'tools.staticfile.on': True,
'tools.staticfile.filename': "images/favicon.ico"
}
}

View File

@@ -788,7 +788,7 @@ class MediaFile(object):
etc = StorageStyle('compilation')
)
albumartist = MediaField(
mp3 = StorageStyle('TXXX', id3_desc=u'Album Artist'),
mp3 = StorageStyle('TPE2'),
mp4 = StorageStyle(
'----:com.apple.iTunes:Album Artist',
as_type=str),

View File

@@ -141,7 +141,7 @@ def getReleaseTypeName(releaseType):
@see: L{musicbrainz2.model.Release}
"""
from musicbrainz2.data.releasetypenames import releaseTypeNames
from lib.musicbrainz2.data.releasetypenames import releaseTypeNames
return releaseTypeNames.get(releaseType)