mirror of
https://github.com/rembo10/headphones.git
synced 2026-03-31 10:09:28 +01:00
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:
@@ -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
84
headphones/db.py
Normal 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())
|
||||
@@ -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
155
headphones/importer.py
Normal 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)
|
||||
@@ -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'), 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()
|
||||
@@ -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')
|
||||
|
||||
|
||||
217
headphones/mb.py
217
headphones/mb.py
@@ -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)
|
||||
|
||||
|
||||
@@ -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"])
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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>'''
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user