mirror of
https://github.com/rembo10/headphones.git
synced 2026-04-04 12:09:27 +01:00
Merge branch 'cache' into develop
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,6 +10,7 @@
|
||||
*.db-journal
|
||||
*.ini
|
||||
logs/*
|
||||
cache/*
|
||||
|
||||
# OS generated files #
|
||||
######################
|
||||
|
||||
@@ -12,9 +12,11 @@ $commands¶meters[&optionalparameters]:
|
||||
|
||||
getIndex (fetch data from index page. Returns: ArtistName, ArtistSortName, ArtistID, Status, DateAdded,
|
||||
[LatestAlbum, ReleaseDate, AlbumID], HaveTracks, TotalTracks,
|
||||
IncludeExtras)
|
||||
IncludeExtras, LastUpdated, [ArtworkURL, ThumbURL]: a remote url to the artwork/thumbnail. To get the cached image path, see getArtistArt command.
|
||||
ThumbURL is added/updated when an artist is added/updated. If your using the database method to get the artwork,
|
||||
it's more reliable to use the ThumbURL than the ArtworkURL)
|
||||
|
||||
getArtist&id=$artistid (fetch artist data. returns the artist object (see above) and album info: Status, AlbumASIN, DateAdded, AlbumTitle, ArtistName, ReleaseDate, AlbumID, ArtistID, Type)
|
||||
getArtist&id=$artistid (fetch artist data. returns the artist object (see above) and album info: Status, AlbumASIN, DateAdded, AlbumTitle, ArtistName, ReleaseDate, AlbumID, ArtistID, Type, ArtworkURL: hosted image path. For cached image, see getAlbumArt command)
|
||||
|
||||
getAlbum&id=$albumid (fetch data from album page. Returns the album object, a description object and a tracks object. Tracks contain: AlbumASIN, AlbumTitle, TrackID, Format, TrackDuration (ms), ArtistName, TrackTitle, AlbumID, ArtistID, Location, TrackNumber, CleanName (stripped of punctuation /styling), BitRate)
|
||||
|
||||
@@ -52,4 +54,13 @@ checkGithub (updates the version information above and returns getVersion data)
|
||||
|
||||
shutdown (shut down headphones)
|
||||
restart (restart headphones)
|
||||
update (update headphones - you may want to check the install type in get version and not allow this if type==exe)
|
||||
update (update headphones - you may want to check the install type in get version and not allow this if type==exe)
|
||||
|
||||
getArtistArt&id=$artistid (Returns either a relative path to the cached image, or a remote url if the image can't be saved to the cache dir)
|
||||
getAlbumArt&id=$albumid (see above)
|
||||
|
||||
getArtistInfo&id=$artistid (Returns Summary and Content, both formatted in html)
|
||||
getAlbumInfo&id=$albumid (See above, returns Summary and Content)
|
||||
|
||||
getArtistThumb&id=$artistid (Returns either a relative path to the cached thumbnail artist image, or an http:// address if the cache dir can't be written to)
|
||||
getAlbumThumb&id=$albumid (see above)
|
||||
@@ -26,7 +26,7 @@
|
||||
<div class="table_wrapper">
|
||||
<div id="albumheader" class="clearfix">
|
||||
<div id="albumImg">
|
||||
<img src="http://ec1.images-amazon.com/images/P/${album['AlbumASIN']}.01.LZZZZZZZ.jpg" height="200" width="200" alt="albumart" class="albumArt" rel="dialog">
|
||||
<img id="albumImg" height="200" width="200" alt="albumart" class="albumArt" rel="dialog">
|
||||
</div>
|
||||
|
||||
<h1><a href="http://musicbrainz.org/release-group/${album['AlbumID']}">${album['AlbumTitle']}</a></h1>
|
||||
@@ -41,9 +41,7 @@
|
||||
|
||||
%>
|
||||
<div class="albuminfo">
|
||||
%if description:
|
||||
<p>${description['Summary']}</p>
|
||||
%endif
|
||||
<div id="albumInfo"></div>
|
||||
<ul>
|
||||
<li>Tracks: <span>${totaltracks}</span></li>
|
||||
<li>Duration: <span>${albumduration}</span></li>
|
||||
@@ -128,8 +126,25 @@
|
||||
<%def name="javascriptIncludes()">
|
||||
<script src="js/libs/jquery.dataTables.min.js"></script>
|
||||
<script>
|
||||
|
||||
function getAlbumArt() {
|
||||
var id = "${album['AlbumID']}";
|
||||
var image = $("div#albumImg img#albumImg");
|
||||
if ( !image.hasClass('done') ) {
|
||||
image.addClass('done');
|
||||
getArtwork(image,id,'album');
|
||||
}
|
||||
}
|
||||
|
||||
function getAlbumInfo() {
|
||||
var id = "${album['AlbumID']}";
|
||||
var elem = $("#albumInfo");
|
||||
getInfo(elem,id,'album');
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
getAlbumInfo("${album['ArtistName']}","${album['AlbumTitle']}","#albumheader .albumArt",3);
|
||||
getAlbumInfo();
|
||||
getAlbumArt();
|
||||
initActions();
|
||||
|
||||
$('#track_table').dataTable({
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<%def name="body()">
|
||||
<div id="artistheader" class="clearfix">
|
||||
<div id="artistImg">
|
||||
<img class="albumArt" src="http://ec1.images-amazon.com/images/P/None.01.MZZZZZZZ.jpg" width="200" height="200" alt="${artist['ArtistName']}"/>
|
||||
<img id="artistImg" class="albumArt" alt="${artist['ArtistName']}"/>
|
||||
</div>
|
||||
<h1>
|
||||
%if artist['Status'] == 'Loading':
|
||||
@@ -109,7 +109,7 @@
|
||||
%>
|
||||
<tr class="grade${grade}">
|
||||
<td id="select"><input type="checkbox" name="${album['AlbumID']}" class="checkbox" /></td>
|
||||
<td id="albumart"><img src="http://ec1.images-amazon.com/images/P/${album['AlbumASIN']}.01.MZZZZZZZ.jpg" height="50" width="50"></td>
|
||||
<td id="albumart"><img title="${album['AlbumID']}" height="64" width="64"></td>
|
||||
<td id="albumname"><a href="albumPage?AlbumID=${album['AlbumID']}">${album['AlbumTitle']}</a></td>
|
||||
<td id="reldate">${album['ReleaseDate']}</td>
|
||||
<td id="type">${album['Type']}</td>
|
||||
@@ -148,11 +148,41 @@
|
||||
<script src="js/libs/jquery.dataTables.min.js"></script>
|
||||
|
||||
<script>
|
||||
|
||||
function getArtistArt() {
|
||||
var id = "${artist['ArtistID']}";
|
||||
var image = $("div#artistImg img#artistImg");
|
||||
if ( !image.hasClass('done') ) {
|
||||
image.addClass('done');
|
||||
getArtwork(image,id,'artist');
|
||||
}
|
||||
}
|
||||
|
||||
function getAlbumArt() {
|
||||
$("table#album_table tr td#albumart").each(function(){
|
||||
var id = $(this).children('img').attr('title');
|
||||
var image = $(this).children('img');
|
||||
if ( !image.hasClass('done') ) {
|
||||
image.addClass('done');
|
||||
getThumb(image,id,'album');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getArtistBio() {
|
||||
var id = "${artist['ArtistID']}";
|
||||
var elem = $("#artistBio");
|
||||
getInfo(elem,id,'artist');
|
||||
}
|
||||
|
||||
|
||||
function initThisPage() {
|
||||
%if artist['Status'] == 'Loading':
|
||||
showMsg("Getting artist information",true);
|
||||
%endif
|
||||
|
||||
getArtistArt();
|
||||
getArtistBio();
|
||||
getAlbumArt();
|
||||
$('#album_table').dataTable({
|
||||
"bDestroy": true,
|
||||
"aoColumns": [
|
||||
@@ -181,19 +211,16 @@
|
||||
|
||||
});
|
||||
resetFilters("albums");
|
||||
replaceEmptyAlbum("table#album_table td#albumart img","${artist['ArtistName']}");
|
||||
setTimeout(function(){
|
||||
initFancybox();
|
||||
},1000);
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
getArtistInfo("${artist['ArtistName']}","#artistImg img",3,"${artist['ArtistID']}");
|
||||
initActions();
|
||||
initThisPage();
|
||||
});
|
||||
$(window).load(function(){
|
||||
replaceEmptyAlbum("table#album_table td#albumart img","${artist['ArtistName']}");
|
||||
setTimeout(function(){
|
||||
initFancybox();
|
||||
},1000)
|
||||
|
||||
@@ -96,10 +96,9 @@
|
||||
<a href="#main" id="toTop"><span>Back to top</span></a>
|
||||
</div>
|
||||
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
|
||||
<script>!window.jQuery && document.write(unescape('%3Cscript src="js/libs/jquery-1.7.2.min.js"%3E%3C/script%3E'))</script>
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.19/jquery-ui.min.js"></script>
|
||||
<script>!window.jQuery && document.write(unescape('%3Cscript src="js/libs/jquery-ui.min.js"%3E%3C/script%3E'))</script>
|
||||
<script src="js/libs/jquery-1.7.2.min.js"></script>
|
||||
<script src="js/libs/jquery-ui.min.js"></script>
|
||||
|
||||
${next.javascriptIncludes()}
|
||||
|
||||
<script src="js/plugins.js"></script>
|
||||
|
||||
@@ -74,11 +74,10 @@
|
||||
function getArtistArt() {
|
||||
$("table#artist_table tr td#name").each(function(){
|
||||
var id = $(this).children('a').attr('title');
|
||||
var artist = $(this).children('a').text();
|
||||
var image = $(this).parent().find("td#albumart img");
|
||||
if ( !image.hasClass('done') ) {
|
||||
image.addClass('done');
|
||||
getArtistInfo(artist,image,1,id);
|
||||
getThumb(image,id,'artist');
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -114,4 +113,4 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
</%def>
|
||||
</%def>
|
||||
|
||||
@@ -1,110 +1,85 @@
|
||||
function getArtistInfo(name,imgElem,size,artistID) {
|
||||
var apikey = "690e1ed3bc00bc91804cd8f7fe5ed6d4";
|
||||
function getThumb(imgElem,id,type) {
|
||||
|
||||
// Get Data by Artist ID
|
||||
$.ajax({
|
||||
url: "http://ws.audioscrobbler.com/2.0/?method=artist.getInfo&mbid="+ artistID +"&api_key="+ apikey+"&format=json",
|
||||
dataType: "jsonp",
|
||||
cache: true,
|
||||
success: function(data){
|
||||
if ( data.artist !== undefined ) {
|
||||
var imageUrl = data.artist.image[size]['#text'];
|
||||
}
|
||||
if (data.error) {
|
||||
getArtistName();
|
||||
} else {
|
||||
if ( data.artist === undefined || imageUrl == "" || imageUrl == undefined ) {
|
||||
var imageLarge = "#";
|
||||
var imageUrl = "interfaces/default/images/no-cover-artist.png";
|
||||
} else {
|
||||
var artist = data.artist.mbid;
|
||||
var artistBio = data.artist.bio.summary;
|
||||
var imageLarge = data.artist.image[4]['#text'];
|
||||
var imageUrl = data.artist.image[size]['#text'];
|
||||
}
|
||||
var artistBio = artistBio;
|
||||
var image = imgElem;
|
||||
var bio = $('#artistBio');
|
||||
$(image).attr("src",imageUrl).removeAttr("width").removeAttr("height").hide().fadeIn();
|
||||
if ( bio.length > 0 ) $(bio).append(artistBio);
|
||||
$(image).wrap('<a href="'+ imageLarge +'" rel="dialog" title="' + name + '"></a>');
|
||||
}
|
||||
}
|
||||
});
|
||||
// If not found get by Name
|
||||
function getArtistName() {
|
||||
$.ajax({
|
||||
url: "http://ws.audioscrobbler.com/2.0/?method=artist.getInfo&artist="+ name +"&api_key="+ apikey+"&format=json",
|
||||
dataType: "jsonp",
|
||||
success: function(data){
|
||||
if ( data.artist !== undefined ) {
|
||||
var imageUrl = data.artist.image[size]['#text'];
|
||||
}
|
||||
if ( data.artist === undefined || imageUrl == "" ) {
|
||||
var imageLarge = "#";
|
||||
var imageUrl = "interfaces/default/images/no-cover-artist.png";
|
||||
} else {
|
||||
var artist = data.artist.name;
|
||||
var artistBio = data.artist.bio.summary;
|
||||
var imageLarge = data.artist.image[4]['#text'];
|
||||
var imageUrl = data.artist.image[size]['#text'];
|
||||
}
|
||||
var artistBio = artistBio;
|
||||
var image = imgElem;
|
||||
var bio = $('#artistBio');
|
||||
$(image).attr("src",imageUrl).removeAttr("width").removeAttr("height").hide().fadeIn();
|
||||
if ( bio.length > 0 ) $(bio).append(artistBio);
|
||||
$(image).wrap('<a href="'+ imageLarge +'" rel="dialog" title="' + artist + '"></a>');
|
||||
}
|
||||
});
|
||||
if ( type == 'artist' ) {
|
||||
var thumbURL = "getThumb?ArtistID=" + id;
|
||||
} else {
|
||||
var thumbURL = "getThumb?AlbumID=" + id;
|
||||
}
|
||||
// Get Data from the cache by Artist ID
|
||||
$.ajax({
|
||||
url: thumbURL,
|
||||
success: function(data){
|
||||
if ( data == "" ) {
|
||||
var imageUrl = "interfaces/default/images/no-cover-artist.png";
|
||||
}
|
||||
else {
|
||||
var imageUrl = data;
|
||||
}
|
||||
$(imgElem).attr("src",imageUrl).hide().fadeIn();
|
||||
$(imgElem).wrap('<a href="'+ imageLarge +'" rel="dialog" title="' + name + '"></a>');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getAlbumInfo(name, album, elem,size) {
|
||||
var apikey = "690e1ed3bc00bc91804cd8f7fe5ed6d4";
|
||||
var dimensions = getOriginalWidthOfImg(this);
|
||||
var cover = $(elem);
|
||||
function getArtwork(imgElem,id,type) {
|
||||
|
||||
if ( dimensions <= 1) {
|
||||
// Get Data
|
||||
$.ajax({
|
||||
url: "http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key=" + apikey + "&artist="+ name +"&album="+ album +"&format=json&callback=?",
|
||||
dataType: "jsonp",
|
||||
success: function(data){
|
||||
if ( data.artist !== undefined ) {
|
||||
var imageUrl = data.artist.image[size]['#text'];
|
||||
}
|
||||
if (data.album === undefined || imageUrl == "") {
|
||||
if ( elem.width() == 50 ) {
|
||||
var imageUrl = "interfaces/default/images/no-cover-artist.png";
|
||||
} else {
|
||||
var imageUrl = "interfaces/default/images/no-cover-art.png";
|
||||
}
|
||||
} else {
|
||||
var imageUrl = data.album.image[size]['#text'];
|
||||
var imageLarge = data.album.image[3]['#text'];
|
||||
}
|
||||
$(cover).error(function(){
|
||||
if ( elem.width() == 50 ) {
|
||||
var imageUrl = "interfaces/default/images/no-cover-artist.png";
|
||||
} else {
|
||||
var imageUrl = "interfaces/default/images/no-cover-art.png";
|
||||
}
|
||||
$(elem).css("background", "url("+ imageUrl+") center top no-repeat");
|
||||
});
|
||||
if ( imageUrl == "") {
|
||||
if ( elem.width() == 50 ) {
|
||||
var imageUrl = "interfaces/default/images/no-cover-artist.png";
|
||||
} else {
|
||||
var imageUrl = "interfaces/default/images/no-cover-art.png";
|
||||
}
|
||||
$(elem).css("background", "url("+ imageUrl+") center top no-repeat");
|
||||
}
|
||||
$(elem).css("background", "url("+ imageUrl+") center top no-repeat");
|
||||
$(elem).wrap('<a href="'+ imageLarge +'" rel="dialog" title="' + name + '"></a>');
|
||||
}
|
||||
});
|
||||
if ( type == 'artist' ) {
|
||||
var artworkURL = "getArtwork?ArtistID=" + id;
|
||||
} else {
|
||||
var artworkURL = "getArtwork?AlbumID=" + id;
|
||||
}
|
||||
// Get Data from the cache by Artist ID
|
||||
$.ajax({
|
||||
url: artworkURL,
|
||||
success: function(data){
|
||||
if ( data == "" ) {
|
||||
var imageUrl = "interfaces/default/images/no-cover-artist.png";
|
||||
}
|
||||
else {
|
||||
var imageUrl = data;
|
||||
}
|
||||
$(imgElem).attr("src",imageUrl).removeAttr("width").removeAttr("height").hide().fadeIn();
|
||||
$(imgElem).wrap('<a href="'+ imageLarge +'" rel="dialog" title="' + name + '"></a>');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getInfo(elem,id,type) {
|
||||
|
||||
if ( type == 'artist' ) {
|
||||
var infoURL = "getInfo?ArtistID=" + id;
|
||||
} else {
|
||||
var infoURL = "getInfo?AlbumID=" + id;
|
||||
}
|
||||
// Get Data from the cache by ID
|
||||
$.ajax({
|
||||
url: infoURL,
|
||||
dataType: "json",
|
||||
success: function(data){
|
||||
var summary = data.Summary;
|
||||
$(elem).append(summary);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getImageLinks(elem,id,type) {
|
||||
|
||||
if ( type == 'artist' ) {
|
||||
var infoURL = "getImageLinks?ArtistID=" + id;
|
||||
} else {
|
||||
var infoURL = "getImageLinks?AlbumID=" + id;
|
||||
}
|
||||
// Get Data from the cache by ID
|
||||
$.ajax({
|
||||
url: infoURL,
|
||||
dataType: "json",
|
||||
success: function(data){
|
||||
var thumbnail = data.thumbnail;
|
||||
var artwork = data.artwork;
|
||||
|
||||
$(elem).attr("src", thumbnail);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getOriginalWidthOfImg(img_element) {
|
||||
|
||||
@@ -59,8 +59,8 @@
|
||||
%>
|
||||
<tr class="grade${grade}">
|
||||
<td id="select"><input type="checkbox" name="${artist['ArtistID']}" class="checkbox" /></td>
|
||||
<td id="albumart"><div id="artistImg"><img class="albumArt" src="http://ec1.images-amazon.com/images/P/${artist['AlbumID']}.01.MZZZZZZZ.jpg" height="50" width="50"></div></td>
|
||||
<td id="name"><span title="${artist['ArtistSortName']}"></span><a href="artistPage?ArtistID=${artist['ArtistID']}">${artist['ArtistName']}</a></td>
|
||||
<td id="albumart"><div id="artistImg"><img class="albumArt" height="50" width="50"></div></td>
|
||||
<td id="name"><span title="${artist['ArtistSortName']}"></span><a href="artistPage?ArtistID=${artist['ArtistID']}" title="${artist['ArtistID']}">${artist['ArtistName']}</a></td>
|
||||
<td id="status">${artist['Status']}</td>
|
||||
<td id="album"><span title="${releasedate}"></span><a href="albumPage?AlbumID=${artist['AlbumID']}">${albumdisplay}</a></td>
|
||||
</tr>
|
||||
@@ -78,13 +78,19 @@
|
||||
<%def name="javascriptIncludes()">
|
||||
<script src="js/libs/jquery.dataTables.min.js"></script>
|
||||
<script>
|
||||
function getArtistArt() {
|
||||
$("table#artist_table tr td#name").each(function(){
|
||||
var id = $(this).children('a').attr('title');
|
||||
var image = $(this).parent().find("td#albumart img");
|
||||
if ( !image.hasClass('done') ) {
|
||||
image.addClass('done');
|
||||
getThumb(image,id,'artist');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initThisPage() {
|
||||
$("table#artist_table tr td#name").each(function(){
|
||||
var artist = $(this).children('a').text();
|
||||
var image = $(this).parent().find("td#albumart img");
|
||||
getArtistInfo(artist,image,1);
|
||||
});
|
||||
getArtistArt();
|
||||
$('#artist_table').dataTable({
|
||||
"bDestroy":true,
|
||||
"aoColumns": [
|
||||
@@ -108,4 +114,4 @@
|
||||
initFancybox();
|
||||
});
|
||||
</script>
|
||||
</%def>
|
||||
</%def>
|
||||
|
||||
@@ -26,8 +26,12 @@
|
||||
else:
|
||||
grade = 'Z'
|
||||
%>
|
||||
<tr class="grade${grade}">
|
||||
<td id="albumart"><div id="artistImg"><img class="albumArt" src="http://ec1.images-amazon.com/images/P/${result['uniquename']}.01.MZZZZZZZ.jpg" height="50" width="50"></div></td>
|
||||
<tr class="grade${grade}">
|
||||
%if type == 'album':
|
||||
<td id="albumart"><div id="artistImg"><img title="${result['albumid']}" class="albumArt" height="50" width="50"></div></td>
|
||||
%else:
|
||||
<td id="albumart"><div id="artistImg"><img title="${result['id']}" class="albumArt" height="50" width="50"></div></td>
|
||||
%endif
|
||||
%if type == 'album':
|
||||
<td id="albumname"><a href="${result['albumurl']}">${result['title']}</a></td>
|
||||
%endif
|
||||
@@ -55,20 +59,18 @@
|
||||
<script src="js/libs/jquery.dataTables.min.js"></script>
|
||||
|
||||
<script>
|
||||
function initThisPage() {
|
||||
$("table#searchresults_table tr td#artistname").each(function(){
|
||||
var artist = $(this).children('a').attr('title');
|
||||
var image = $(this).parent().find("td#albumart img");
|
||||
var album = $(this).prev().text();
|
||||
var getId = $(this).children('a').attr('href');
|
||||
var id = getId.substr(30);
|
||||
%if type == 'artist':
|
||||
getArtistInfo(artist,image,1,id);
|
||||
%endif
|
||||
%if type == 'album':
|
||||
getAlbumInfo(artist,album,image,1);
|
||||
%endif
|
||||
function getArt() {
|
||||
$("table#searchresults_table tr td#albumart img").each(function(){
|
||||
var id = $(this).attr('title');
|
||||
var image = $(this);
|
||||
if ( !image.hasClass('done') ) {
|
||||
image.addClass('done');
|
||||
getImageLinks(image,id,"${type}");
|
||||
}
|
||||
});
|
||||
}
|
||||
function initThisPage() {
|
||||
getArt();
|
||||
$('#searchresults_table').dataTable(
|
||||
{
|
||||
"bDestroy": true,
|
||||
@@ -95,4 +97,4 @@
|
||||
initFancybox();
|
||||
});
|
||||
</script>
|
||||
</%def>
|
||||
</%def>
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
%for album in wanted:
|
||||
<tr class="gradeZ">
|
||||
<td id="select"><input type="checkbox" name="${album['AlbumID']}" class="checkbox" /></th>
|
||||
<td id="albumart"><img src="http://ec1.images-amazon.com/images/P/${album['AlbumASIN']}.01.MZZZZZZZ.jpg" height="50" width="50"></td>
|
||||
<td id="albumart"><img title="${album['AlbumID']}" height="50" width="50"></td>
|
||||
<td id="artistname">${album['ArtistName']}</td>
|
||||
<td id="albumname"><a href="albumPage?AlbumID=${album['AlbumID']}">${album['AlbumTitle']}</a></td>
|
||||
<td id="reldate">${album['ReleaseDate']}</td>
|
||||
@@ -70,7 +70,7 @@
|
||||
<tbody>
|
||||
%for album in upcoming:
|
||||
<tr class="gradeZ">
|
||||
<td id="albumart"><img src="http://ec1.images-amazon.com/images/P/${album['AlbumASIN']}.01.MZZZZZZZ.jpg" height="50" width="50"></td>
|
||||
<td id="albumart"><img title="${album['AlbumID']}" height="50" width="50"></td>
|
||||
<td id="artistname">${album['ArtistName']}</td>
|
||||
<td id="albumname"><a href="albumPage?AlbumID=${album['AlbumID']}">${album['AlbumTitle']}</a></td>
|
||||
<td id="reldate">${album['ReleaseDate']}</td>
|
||||
@@ -90,7 +90,19 @@
|
||||
<%def name="javascriptIncludes()">
|
||||
<script src="js/libs/jquery.dataTables.min.js"></script>
|
||||
<script>
|
||||
|
||||
function getAlbumArt() {
|
||||
$("td#albumart img").each(function(){
|
||||
var id = $(this).attr('title');
|
||||
var image = $(this);
|
||||
if ( !image.hasClass('done') ) {
|
||||
image.addClass('done');
|
||||
getThumb(image,id,'album');
|
||||
}
|
||||
});
|
||||
}
|
||||
function initThisPage() {
|
||||
getAlbumArt();
|
||||
$('#wanted_table').dataTable({
|
||||
"bDestroy":true,
|
||||
"bFilter": false,
|
||||
@@ -103,8 +115,5 @@
|
||||
$(document).ready(function() {
|
||||
initThisPage();
|
||||
});
|
||||
$(window).load(function(){
|
||||
replaceEmptyAlbum("table#wanted_table td#albumart img","interfaces/default/images/no-cover-art.png");
|
||||
});
|
||||
</script>
|
||||
</%def>
|
||||
</%def>
|
||||
|
||||
4
data/js/libs/jquery-1.7.2.min.js
vendored
Normal file
4
data/js/libs/jquery-1.7.2.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
121
data/js/libs/jquery-ui.min.js
vendored
Normal file
121
data/js/libs/jquery-ui.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -672,13 +672,13 @@ def dbcheck():
|
||||
|
||||
conn=sqlite3.connect(DB_FILE)
|
||||
c=conn.cursor()
|
||||
c.execute('CREATE TABLE IF NOT EXISTS artists (ArtistID TEXT UNIQUE, ArtistName TEXT, ArtistSortName TEXT, DateAdded TEXT, Status TEXT, IncludeExtras INTEGER, LatestAlbum TEXT, ReleaseDate TEXT, AlbumID TEXT, HaveTracks INTEGER, TotalTracks INTEGER, LastUpdated TEXT)')
|
||||
c.execute('CREATE TABLE IF NOT EXISTS albums (ArtistID TEXT, ArtistName TEXT, AlbumTitle TEXT, AlbumASIN TEXT, ReleaseDate TEXT, DateAdded TEXT, AlbumID TEXT UNIQUE, Status TEXT, Type TEXT)')
|
||||
c.execute('CREATE TABLE IF NOT EXISTS artists (ArtistID TEXT UNIQUE, ArtistName TEXT, ArtistSortName TEXT, DateAdded TEXT, Status TEXT, IncludeExtras INTEGER, LatestAlbum TEXT, ReleaseDate TEXT, AlbumID TEXT, HaveTracks INTEGER, TotalTracks INTEGER, LastUpdated TEXT, ArtworkURL TEXT, ThumbURL TEXT)')
|
||||
c.execute('CREATE TABLE IF NOT EXISTS albums (ArtistID TEXT, ArtistName TEXT, AlbumTitle TEXT, AlbumASIN TEXT, ReleaseDate TEXT, DateAdded TEXT, AlbumID TEXT UNIQUE, Status TEXT, Type TEXT, ArtworkURL TEXT, ThumbURL TEXT)')
|
||||
c.execute('CREATE TABLE IF NOT EXISTS tracks (ArtistID TEXT, ArtistName TEXT, AlbumTitle TEXT, AlbumASIN TEXT, AlbumID TEXT, TrackTitle TEXT, TrackDuration, TrackID TEXT, TrackNumber INTEGER, Location TEXT, BitRate INTEGER, CleanName TEXT, Format TEXT)')
|
||||
c.execute('CREATE TABLE IF NOT EXISTS snatched (AlbumID TEXT, Title TEXT, Size INTEGER, URL TEXT, DateAdded TEXT, Status TEXT, FolderName TEXT)')
|
||||
c.execute('CREATE TABLE IF NOT EXISTS have (ArtistName TEXT, AlbumTitle TEXT, TrackNumber TEXT, TrackTitle TEXT, TrackLength TEXT, BitRate TEXT, Genre TEXT, Date TEXT, TrackID TEXT, Location TEXT, CleanName TEXT, Format TEXT)')
|
||||
c.execute('CREATE TABLE IF NOT EXISTS lastfmcloud (ArtistName TEXT, ArtistID TEXT, Count INTEGER)')
|
||||
c.execute('CREATE TABLE IF NOT EXISTS descriptions (ReleaseGroupID TEXT, ReleaseID TEXT, Summary TEXT, Content TEXT)')
|
||||
c.execute('CREATE TABLE IF NOT EXISTS descriptions (ArtistID TEXT, ReleaseGroupID TEXT, ReleaseID TEXT, Summary TEXT, Content TEXT, LastUpdated TEXT)')
|
||||
c.execute('CREATE TABLE IF NOT EXISTS releases (ReleaseID TEXT, ReleaseGroupID TEXT, UNIQUE(ReleaseID, ReleaseGroupID))')
|
||||
c.execute('CREATE INDEX IF NOT EXISTS tracks_albumid ON tracks(AlbumID ASC)')
|
||||
c.execute('CREATE INDEX IF NOT EXISTS album_artistid_reldate ON albums(ArtistID ASC, ReleaseDate DESC)')
|
||||
@@ -767,7 +767,37 @@ def dbcheck():
|
||||
try:
|
||||
c.execute('SELECT LastUpdated from artists')
|
||||
except sqlite3.OperationalError:
|
||||
c.execute('ALTER TABLE artists ADD COLUMN LastUpdated TEXT DEFAULT NULL')
|
||||
c.execute('ALTER TABLE artists ADD COLUMN LastUpdated TEXT DEFAULT NULL')
|
||||
|
||||
try:
|
||||
c.execute('SELECT ArtworkURL from artists')
|
||||
except sqlite3.OperationalError:
|
||||
c.execute('ALTER TABLE artists ADD COLUMN ArtworkURL TEXT DEFAULT NULL')
|
||||
|
||||
try:
|
||||
c.execute('SELECT ArtworkURL from albums')
|
||||
except sqlite3.OperationalError:
|
||||
c.execute('ALTER TABLE albums ADD COLUMN ArtworkURL TEXT DEFAULT NULL')
|
||||
|
||||
try:
|
||||
c.execute('SELECT ThumbURL from artists')
|
||||
except sqlite3.OperationalError:
|
||||
c.execute('ALTER TABLE artists ADD COLUMN ThumbURL TEXT DEFAULT NULL')
|
||||
|
||||
try:
|
||||
c.execute('SELECT ThumbURL from albums')
|
||||
except sqlite3.OperationalError:
|
||||
c.execute('ALTER TABLE albums ADD COLUMN ThumbURL TEXT DEFAULT NULL')
|
||||
|
||||
try:
|
||||
c.execute('SELECT ArtistID from descriptions')
|
||||
except sqlite3.OperationalError:
|
||||
c.execute('ALTER TABLE descriptions ADD COLUMN ArtistID TEXT DEFAULT NULL')
|
||||
|
||||
try:
|
||||
c.execute('SELECT LastUpdated from descriptions')
|
||||
except sqlite3.OperationalError:
|
||||
c.execute('ALTER TABLE descriptions ADD COLUMN LastUpdated TEXT DEFAULT NULL')
|
||||
|
||||
conn.commit()
|
||||
c.close()
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
import headphones
|
||||
|
||||
from headphones import db, mb, importer, searcher, postprocessor, versioncheck, logger
|
||||
from headphones import db, mb, importer, searcher, cache, postprocessor, versioncheck, logger
|
||||
|
||||
import lib.simplejson as simplejson
|
||||
from xml.dom.minidom import Document
|
||||
@@ -24,7 +24,7 @@ import copy
|
||||
cmd_list = [ 'getIndex', 'getArtist', 'getAlbum', 'getUpcoming', 'getWanted', 'getSimilar', 'getHistory', 'getLogs',
|
||||
'findArtist', 'findAlbum', 'addArtist', 'delArtist', 'pauseArtist', 'resumeArtist', 'refreshArtist',
|
||||
'queueAlbum', 'unqueueAlbum', 'forceSearch', 'forceProcess', 'getVersion', 'checkGithub',
|
||||
'shutdown', 'restart', 'update', ]
|
||||
'shutdown', 'restart', 'update', 'getArtistArt', 'getAlbumArt', 'getArtistInfo', 'getAlbumInfo', 'getArtistThumb', 'getAlbumThumb']
|
||||
|
||||
class Api(object):
|
||||
|
||||
@@ -314,3 +314,63 @@ class Api(object):
|
||||
|
||||
def _update(self, **kwargs):
|
||||
headphones.SIGNAL = 'update'
|
||||
|
||||
def _getArtistArt(self, **kwargs):
|
||||
|
||||
if 'id' not in kwargs:
|
||||
self.data = 'Missing parameter: id'
|
||||
return
|
||||
else:
|
||||
self.id = kwargs['id']
|
||||
|
||||
self.data = cache.getArtwork(ArtistID=self.id)
|
||||
|
||||
def _getAlbumArt(self, **kwargs):
|
||||
|
||||
if 'id' not in kwargs:
|
||||
self.data = 'Missing parameter: id'
|
||||
return
|
||||
else:
|
||||
self.id = kwargs['id']
|
||||
|
||||
self.data = cache.getArtwork(AlbumID=self.id)
|
||||
|
||||
def _getArtistInfo(self, **kwargs):
|
||||
|
||||
if 'id' not in kwargs:
|
||||
self.data = 'Missing parameter: id'
|
||||
return
|
||||
else:
|
||||
self.id = kwargs['id']
|
||||
|
||||
self.data = cache.getInfo(ArtistID=self.id)
|
||||
|
||||
def _getAlbumInfo(self, **kwargs):
|
||||
|
||||
if 'id' not in kwargs:
|
||||
self.data = 'Missing parameter: id'
|
||||
return
|
||||
else:
|
||||
self.id = kwargs['id']
|
||||
|
||||
self.data = cache.getInfo(AlbumID=self.id)
|
||||
|
||||
def _getArtistThumb(self, **kwargs):
|
||||
|
||||
if 'id' not in kwargs:
|
||||
self.data = 'Missing parameter: id'
|
||||
return
|
||||
else:
|
||||
self.id = kwargs['id']
|
||||
|
||||
self.data = cache.getThumb(ArtistID=self.id)
|
||||
|
||||
def _getAlbumThumb(self, **kwargs):
|
||||
|
||||
if 'id' not in kwargs:
|
||||
self.data = 'Missing parameter: id'
|
||||
return
|
||||
else:
|
||||
self.id = kwargs['id']
|
||||
|
||||
self.data = cache.getThumb(AlbumID=self.id)
|
||||
|
||||
520
headphones/cache.py
Normal file
520
headphones/cache.py
Normal file
@@ -0,0 +1,520 @@
|
||||
# This file is part of Headphones.
|
||||
#
|
||||
# Headphones is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Headphones is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Headphones. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import glob, urllib, urllib2
|
||||
|
||||
import lib.simplejson as simplejson
|
||||
|
||||
import headphones
|
||||
from headphones import db, helpers, logger
|
||||
|
||||
lastfm_apikey = "690e1ed3bc00bc91804cd8f7fe5ed6d4"
|
||||
|
||||
class Cache(object):
|
||||
"""
|
||||
This class deals with getting, storing and serving up artwork (album
|
||||
art, artist images, etc) and info/descriptions (album info, artist descrptions)
|
||||
to and from the cache folder. This can be called from within a web interface,
|
||||
for example, using the helper functions getInfo(id) and getArtwork(id), to utilize the cached
|
||||
images rather than having to retrieve them every time the page is reloaded.
|
||||
|
||||
So you can call cache.getArtwork(id) which will return an absolute path
|
||||
to the image file on the local machine, or if the cache directory
|
||||
doesn't exist, or can not be written to, it will return a url to the image.
|
||||
|
||||
Call cache.getInfo(id) to grab the artist/album info; will return the text description
|
||||
|
||||
The basic format for art in the cache is <musicbrainzid>.<date>.<ext>
|
||||
and for info it is <musicbrainzid>.<date>.txt
|
||||
"""
|
||||
|
||||
path_to_art_cache = os.path.join(headphones.CACHE_DIR, 'artwork')
|
||||
|
||||
id = None
|
||||
id_type = None # 'artist' or 'album' - set automatically depending on whether ArtistID or AlbumID is passed
|
||||
query_type = None # 'artwork','thumb' or 'info' - set automatically
|
||||
|
||||
artwork_files = []
|
||||
thumb_files = []
|
||||
|
||||
artwork_errors = False
|
||||
artwork_url = None
|
||||
|
||||
thumb_errors = False
|
||||
thumb_url = None
|
||||
|
||||
info_summary = None
|
||||
info_content = None
|
||||
|
||||
def __init__(self):
|
||||
|
||||
pass
|
||||
|
||||
def _exists(self, type):
|
||||
|
||||
self.artwork_files = glob.glob(os.path.join(self.path_to_art_cache, self.id + '*'))
|
||||
self.thumb_files = glob.glob(os.path.join(self.path_to_art_cache, 'T_' + self.id + '*'))
|
||||
|
||||
if type == 'artwork':
|
||||
|
||||
if self.artwork_files:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
elif type == 'thumb':
|
||||
|
||||
if self.thumb_files:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def _get_age(self, date):
|
||||
# There's probably a better way to do this
|
||||
split_date = date.split('-')
|
||||
days_old = int(split_date[0])*365 + int(split_date[1])*30 + int(split_date[2])
|
||||
|
||||
return days_old
|
||||
|
||||
|
||||
def _is_current(self, filename=None, date=None):
|
||||
|
||||
if filename:
|
||||
base_filename = os.path.basename(filename)
|
||||
date = base_filename.split('.')[1]
|
||||
|
||||
# Calculate how old the cached file is based on todays date & file date stamp
|
||||
# helpers.today() returns todays date in yyyy-mm-dd format
|
||||
if self._get_age(helpers.today()) - self._get_age(date) < 30:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def _get_thumb_url(self, data):
|
||||
|
||||
thumb_url = None
|
||||
|
||||
try:
|
||||
images = data[self.id_type]['image']
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
for image in images:
|
||||
if image['size'] == 'medium':
|
||||
thumb_url = image['#text']
|
||||
break
|
||||
|
||||
return thumb_url
|
||||
|
||||
def get_artwork_from_cache(self, ArtistID=None, AlbumID=None):
|
||||
'''
|
||||
Pass a musicbrainz id to this function (either ArtistID or AlbumID)
|
||||
'''
|
||||
|
||||
self.query_type = 'artwork'
|
||||
|
||||
if ArtistID:
|
||||
self.id = ArtistID
|
||||
self.id_type = 'artist'
|
||||
else:
|
||||
self.id = AlbumID
|
||||
self.id_type = 'album'
|
||||
|
||||
if self._exists('artwork') and self._is_current(filename=self.artwork_files[0]):
|
||||
return self.artwork_files[0]
|
||||
else:
|
||||
self._update_cache()
|
||||
# If we failed to get artwork, either return the url or the older file
|
||||
if self.artwork_errors and self.artwork_url:
|
||||
return self.artwork_url
|
||||
elif self._exists('artwork'):
|
||||
return self.artwork_files[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_thumb_from_cache(self, ArtistID=None, AlbumID=None):
|
||||
'''
|
||||
Pass a musicbrainz id to this function (either ArtistID or AlbumID)
|
||||
'''
|
||||
|
||||
self.query_type = 'thumb'
|
||||
|
||||
if ArtistID:
|
||||
self.id = ArtistID
|
||||
self.id_type = 'artist'
|
||||
else:
|
||||
self.id = AlbumID
|
||||
self.id_type = 'album'
|
||||
|
||||
if self._exists('thumb') and self._is_current(filename=self.thumb_files[0]):
|
||||
return self.thumb_files[0]
|
||||
else:
|
||||
self._update_cache()
|
||||
# If we failed to get artwork, either return the url or the older file
|
||||
if self.thumb_errors and self.thumb_url:
|
||||
return self.thumb_url
|
||||
elif self._exists('thumb'):
|
||||
return self.thumb_files[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_info_from_cache(self, ArtistID=None, AlbumID=None):
|
||||
|
||||
self.query_type = 'info'
|
||||
myDB = db.DBConnection()
|
||||
|
||||
if ArtistID:
|
||||
self.id = ArtistID
|
||||
self.id_type = 'artist'
|
||||
db_info = myDB.action('SELECT Summary, Content, LastUpdated FROM descriptions WHERE ArtistID=?', [self.id]).fetchone()
|
||||
else:
|
||||
self.id = AlbumID
|
||||
self.id_type = 'album'
|
||||
db_info = myDB.action('SELECT Summary, Content, LastUpdated FROM descriptions WHERE ReleaseGroupID=?', [self.id]).fetchone()
|
||||
|
||||
if not db_info or not db_info['LastUpdated'] or not self._is_current(date=db_info['LastUpdated']):
|
||||
|
||||
self._update_cache()
|
||||
info_dict = { 'Summary' : self.info_summary, 'Content' : self.info_content }
|
||||
return info_dict
|
||||
|
||||
else:
|
||||
info_dict = { 'Summary' : db_info['Summary'], 'Content' : db_info['Content'] }
|
||||
return info_dict
|
||||
|
||||
def get_image_links(self, ArtistID=None, AlbumID=None):
|
||||
'''
|
||||
Here we're just going to open up the last.fm url, grab the image links and return them
|
||||
Won't save any image urls, or save the artwork in the cache. Useful for search results, etc.
|
||||
'''
|
||||
if ArtistID:
|
||||
|
||||
self.id_type = 'artist'
|
||||
|
||||
params = { "method": "artist.getInfo",
|
||||
"api_key": lastfm_apikey,
|
||||
"mbid": ArtistID,
|
||||
"format": "json"
|
||||
}
|
||||
|
||||
url = "http://ws.audioscrobbler.com/2.0/?" + urllib.urlencode(params)
|
||||
logger.debug('Retrieving artist information from: ' + url)
|
||||
|
||||
try:
|
||||
result = urllib2.urlopen(url, timeout=20).read()
|
||||
except:
|
||||
logger.warn('Could not open url: ' + url)
|
||||
return
|
||||
|
||||
if result:
|
||||
|
||||
try:
|
||||
data = simplejson.JSONDecoder().decode(result)
|
||||
except:
|
||||
logger.warn('Could not parse data from url: ' + url)
|
||||
return
|
||||
|
||||
try:
|
||||
image_url = data['artist']['image'][-1]['#text']
|
||||
except KeyError:
|
||||
logger.debug('No artist image found on url: ' + url)
|
||||
image_url = None
|
||||
|
||||
thumb_url = self._get_thumb_url(data)
|
||||
if not thumb_url:
|
||||
logger.debug('No artist thumbnail image found on url: ' + url)
|
||||
|
||||
else:
|
||||
|
||||
self.id_type = 'album'
|
||||
|
||||
params = { "method": "album.getInfo",
|
||||
"api_key": lastfm_apikey,
|
||||
"mbid": AlbumID,
|
||||
"format": "json"
|
||||
}
|
||||
|
||||
url = "http://ws.audioscrobbler.com/2.0/?" + urllib.urlencode(params)
|
||||
logger.debug('Retrieving album information from: ' + url)
|
||||
|
||||
try:
|
||||
result = urllib2.urlopen(url, timeout=20).read()
|
||||
except:
|
||||
logger.warn('Could not open url: ' + url)
|
||||
return
|
||||
|
||||
if result:
|
||||
|
||||
try:
|
||||
data = simplejson.JSONDecoder().decode(result)
|
||||
except:
|
||||
logger.warn('Could not parse data from url: ' + url)
|
||||
return
|
||||
|
||||
try:
|
||||
image_url = data['artist']['image'][-1]['#text']
|
||||
except KeyError:
|
||||
logger.debug('No artist image found on url: ' + url)
|
||||
image_url = None
|
||||
|
||||
thumb_url = self._get_thumb_url(data)
|
||||
if not thumb_url:
|
||||
logger.debug('No artist thumbnail image found on url: ' + url)
|
||||
|
||||
image_dict = {'artwork' : image_url, 'thumbnail' : thumb_url }
|
||||
return image_dict
|
||||
|
||||
def _update_cache(self):
|
||||
'''
|
||||
Since we call the same url for both info and artwork, we'll update both at the same time
|
||||
'''
|
||||
myDB = db.DBConnection()
|
||||
|
||||
# Since lastfm uses release ids rather than release group ids for albums, we have to do a artist + album search for albums
|
||||
if self.id_type == 'artist':
|
||||
|
||||
params = { "method": "artist.getInfo",
|
||||
"api_key": lastfm_apikey,
|
||||
"mbid": self.id,
|
||||
"format": "json"
|
||||
}
|
||||
|
||||
url = "http://ws.audioscrobbler.com/2.0/?" + urllib.urlencode(params)
|
||||
logger.debug('Retrieving artist information from: ' + url)
|
||||
|
||||
try:
|
||||
result = urllib2.urlopen(url, timeout=20).read()
|
||||
except:
|
||||
logger.warn('Could not open url: ' + url)
|
||||
return
|
||||
|
||||
if result:
|
||||
|
||||
try:
|
||||
data = simplejson.JSONDecoder().decode(result)
|
||||
except:
|
||||
logger.warn('Could not parse data from url: ' + url)
|
||||
return
|
||||
try:
|
||||
self.info_summary = data['artist']['bio']['summary']
|
||||
except KeyError:
|
||||
logger.debug('No artist bio summary found on url: ' + url)
|
||||
self.info_summary = None
|
||||
try:
|
||||
self.info_content = data['artist']['bio']['content']
|
||||
except KeyError:
|
||||
logger.debug('No artist bio found on url: ' + url)
|
||||
self.info_content = None
|
||||
try:
|
||||
image_url = data['artist']['image'][-1]['#text']
|
||||
except KeyError:
|
||||
logger.debug('No artist image found on url: ' + url)
|
||||
image_url = None
|
||||
|
||||
thumb_url = self._get_thumb_url(data)
|
||||
if not thumb_url:
|
||||
logger.debug('No artist thumbnail image found on url: ' + url)
|
||||
|
||||
else:
|
||||
|
||||
dbartist = myDB.action('SELECT ArtistName, AlbumTitle FROM albums WHERE AlbumID=?', [self.id]).fetchone()
|
||||
|
||||
params = { "method": "album.getInfo",
|
||||
"api_key": lastfm_apikey,
|
||||
"artist": dbartist['ArtistName'].encode('utf-8'),
|
||||
"album": dbartist['AlbumTitle'].encode('utf-8'),
|
||||
"format": "json"
|
||||
}
|
||||
|
||||
url = "http://ws.audioscrobbler.com/2.0/?" + urllib.urlencode(params)
|
||||
|
||||
logger.debug('Retrieving artist information from: ' + url)
|
||||
try:
|
||||
result = urllib2.urlopen(url, timeout=20).read()
|
||||
except:
|
||||
logger.warn('Could not open url: ' + url)
|
||||
return
|
||||
|
||||
if result:
|
||||
try:
|
||||
data = simplejson.JSONDecoder().decode(result)
|
||||
except:
|
||||
logger.warn('Could not parse data from url: ' + url)
|
||||
return
|
||||
try:
|
||||
self.info_summary = data['album']['wiki']['summary']
|
||||
except KeyError:
|
||||
logger.debug('No album summary found from: ' + url)
|
||||
self.info_summary = None
|
||||
try:
|
||||
self.info_content = data['album']['wiki']['content']
|
||||
except KeyError:
|
||||
logger.debug('No album infomation found from: ' + url)
|
||||
self.info_content = None
|
||||
try:
|
||||
image_url = data['album']['image'][-1]['#text']
|
||||
except KeyError:
|
||||
logger.debug('No album image link found on url: ' + url)
|
||||
image_url = None
|
||||
|
||||
thumb_url = self._get_thumb_url(data)
|
||||
if not thumb_url:
|
||||
logger.debug('No album thumbnail image found on url: ' + url)
|
||||
|
||||
#Save the content & summary to the database no matter what if we've opened up the url
|
||||
if self.id_type == 'artist':
|
||||
controlValueDict = {"ArtistID": self.id}
|
||||
else:
|
||||
controlValueDict = {"ReleaseGroupID": self.id}
|
||||
|
||||
newValueDict = {"Summary": self.info_summary,
|
||||
"Content": self.info_content,
|
||||
"LastUpdated": helpers.today()}
|
||||
|
||||
myDB.upsert("descriptions", newValueDict, controlValueDict)
|
||||
|
||||
# Save the image URL to the database
|
||||
if image_url:
|
||||
if self.id_type == 'artist':
|
||||
myDB.action('UPDATE artists SET ArtworkURL=? WHERE ArtistID=?', [image_url, self.id])
|
||||
else:
|
||||
myDB.action('UPDATE albums SET ArtworkURL=? WHERE AlbumID=?', [image_url, self.id])
|
||||
|
||||
# Save the thumb URL to the database
|
||||
if thumb_url:
|
||||
if self.id_type == 'artist':
|
||||
myDB.action('UPDATE artists SET ThumbURL=? WHERE ArtistID=?', [thumb_url, self.id])
|
||||
else:
|
||||
myDB.action('UPDATE albums SET ThumbURL=? WHERE AlbumID=?', [thumb_url, self.id])
|
||||
|
||||
# Should we grab the artwork here if we're just grabbing thumbs or info?? Probably not since the files can be quite big
|
||||
if image_url and self.query_type == 'artwork':
|
||||
|
||||
try:
|
||||
artwork = urllib2.urlopen(image_url, timeout=20).read()
|
||||
except Exception, e:
|
||||
logger.error('Unable to open url "' + image_url + '". Error: ' + str(e))
|
||||
artwork = None
|
||||
|
||||
if artwork:
|
||||
|
||||
# Make sure the artwork dir exists:
|
||||
if not os.path.isdir(self.path_to_art_cache):
|
||||
try:
|
||||
os.makedirs(self.path_to_art_cache)
|
||||
except Exception, e:
|
||||
logger.error('Unable to create artwork cache dir. Error: ' + str(e))
|
||||
self.artwork_errors = True
|
||||
self.artwork_url = image_url
|
||||
|
||||
#Delete the old stuff
|
||||
for artwork_file in self.artwork_files:
|
||||
try:
|
||||
os.remove(artwork_file)
|
||||
except:
|
||||
logger.error('Error deleting file from the cache: ' + artwork_file)
|
||||
|
||||
ext = os.path.splitext(image_url)[1]
|
||||
|
||||
artwork_path = os.path.join(self.path_to_art_cache, self.id + '.' + helpers.today() + ext)
|
||||
try:
|
||||
f = open(artwork_path, 'wb')
|
||||
f.write(artwork)
|
||||
f.close()
|
||||
except Exception, e:
|
||||
logger.error('Unable to write to the cache dir: ' + str(e))
|
||||
self.artwork_errors = True
|
||||
self.artwork_url = image_url
|
||||
|
||||
# Grab the thumbnail as well if we're getting the full artwork (as long as it's missing/outdated
|
||||
if thumb_url and self.query_type in ['thumb','artwork'] and not (self.thumb_files and self._is_current(self.thumb_files[0])):
|
||||
|
||||
try:
|
||||
artwork = urllib2.urlopen(thumb_url, timeout=20).read()
|
||||
except Exception, e:
|
||||
logger.error('Unable to open url "' + thumb_url + '". Error: ' + str(e))
|
||||
artwork = None
|
||||
|
||||
if artwork:
|
||||
|
||||
# Make sure the artwork dir exists:
|
||||
if not os.path.isdir(self.path_to_art_cache):
|
||||
try:
|
||||
os.makedirs(self.path_to_art_cache)
|
||||
except Exception, e:
|
||||
logger.error('Unable to create artwork cache dir. Error: ' + str(e))
|
||||
self.thumb_errors = True
|
||||
self.thumb_url = thumb_url
|
||||
|
||||
#Delete the old stuff
|
||||
for thumb_file in self.thumb_files:
|
||||
try:
|
||||
os.remove(thumb_file)
|
||||
except:
|
||||
logger.error('Error deleting file from the cache: ' + thumb_file)
|
||||
|
||||
ext = os.path.splitext(image_url)[1]
|
||||
|
||||
thumb_path = os.path.join(self.path_to_art_cache, 'T_' + self.id + '.' + helpers.today() + ext)
|
||||
try:
|
||||
f = open(thumb_path, 'wb')
|
||||
f.write(artwork)
|
||||
f.close()
|
||||
except Exception, e:
|
||||
logger.error('Unable to write to the cache dir: ' + str(e))
|
||||
self.thumb_errors = True
|
||||
self.thumb_url = image_url
|
||||
|
||||
def getArtwork(ArtistID=None, AlbumID=None):
|
||||
|
||||
c = Cache()
|
||||
artwork_path = c.get_artwork_from_cache(ArtistID, AlbumID)
|
||||
|
||||
if not artwork_path:
|
||||
return None
|
||||
|
||||
if artwork_path.startswith('http://'):
|
||||
return artwork_path
|
||||
else:
|
||||
return "cache" + artwork_path[len(headphones.CACHE_DIR):]
|
||||
|
||||
def getThumb(ArtistID=None, AlbumID=None):
|
||||
|
||||
c = Cache()
|
||||
artwork_path = c.get_thumb_from_cache(ArtistID, AlbumID)
|
||||
|
||||
if not artwork_path:
|
||||
return None
|
||||
|
||||
if artwork_path.startswith('http://'):
|
||||
return artwork_path
|
||||
else:
|
||||
return "cache" + artwork_path[len(headphones.CACHE_DIR):]
|
||||
|
||||
def getInfo(ArtistID=None, AlbumID=None):
|
||||
|
||||
c = Cache()
|
||||
|
||||
info_dict = c.get_info_from_cache(ArtistID, AlbumID)
|
||||
|
||||
return info_dict
|
||||
|
||||
def getImageLinks(ArtistID=None, AlbumID=None):
|
||||
|
||||
c = Cache()
|
||||
image_links = c.get_image_links(ArtistID, AlbumID)
|
||||
|
||||
return image_links
|
||||
@@ -82,6 +82,9 @@ def addArtistIDListToDB(artistidlist):
|
||||
|
||||
def addArtisttoDB(artistid, extrasonly=False):
|
||||
|
||||
# Putting this here to get around the circular import
|
||||
from headphones import cache
|
||||
|
||||
# Can't add various artists - throws an error from MB
|
||||
if artistid == various_artists_mbid:
|
||||
logger.warn('Cannot import Various Artists.')
|
||||
@@ -179,11 +182,6 @@ def addArtisttoDB(artistid, extrasonly=False):
|
||||
newValueDict['Status'] = "Skipped"
|
||||
|
||||
myDB.upsert("albums", newValueDict, controlValueDict)
|
||||
|
||||
try:
|
||||
lastfm.getAlbumDescription(rg['id'], artist['artist_name'], rg['title'])
|
||||
except Exception, e:
|
||||
logger.error('Attempt to retrieve album description from Last.fm failed: %s' % e)
|
||||
|
||||
# I changed the albumid from releaseid -> rgid, so might need to delete albums that have a releaseid
|
||||
for release in release_dict['releaselist']:
|
||||
@@ -220,6 +218,9 @@ def addArtisttoDB(artistid, extrasonly=False):
|
||||
|
||||
myDB.upsert("tracks", newValueDict, controlValueDict)
|
||||
|
||||
logger.info(u"Updating album cache for " + rg['title'])
|
||||
cache.getThumb(AlbumID=rg['id'])
|
||||
|
||||
latestalbum = myDB.action('SELECT AlbumTitle, ReleaseDate, AlbumID from albums WHERE ArtistID=? order by ReleaseDate DESC', [artistid]).fetchone()
|
||||
totaltracks = len(myDB.select('SELECT TrackTitle from tracks WHERE ArtistID=?', [artistid]))
|
||||
havetracks = len(myDB.select('SELECT TrackTitle from tracks WHERE ArtistID=? AND Location IS NOT NULL', [artistid])) + len(myDB.select('SELECT TrackTitle from have WHERE ArtistName like ?', [artist['artist_name']]))
|
||||
@@ -241,6 +242,10 @@ def addArtisttoDB(artistid, extrasonly=False):
|
||||
newValueDict['LastUpdated'] = helpers.now()
|
||||
|
||||
myDB.upsert("artists", newValueDict, controlValueDict)
|
||||
|
||||
logger.info(u"Updating cache for: " + artist['artist_name'])
|
||||
cache.getThumb(ArtistID=artistid)
|
||||
|
||||
logger.info(u"Updating complete for: " + artist['artist_name'])
|
||||
|
||||
def addReleaseById(rid):
|
||||
|
||||
@@ -28,6 +28,8 @@ import headphones
|
||||
from headphones import logger, searcher, db, importer, mb, lastfm, librarysync
|
||||
from headphones.helpers import checked, radio
|
||||
|
||||
import lib.simplejson as simplejson
|
||||
|
||||
|
||||
|
||||
def serve_template(templatename, **kwargs):
|
||||
@@ -591,3 +593,36 @@ class WebInterface(object):
|
||||
return data
|
||||
|
||||
api.exposed = True
|
||||
|
||||
def getInfo(self, ArtistID=None, AlbumID=None):
|
||||
|
||||
from headphones import cache
|
||||
info_dict = cache.getInfo(ArtistID, AlbumID)
|
||||
|
||||
return simplejson.dumps(info_dict)
|
||||
|
||||
getInfo.exposed = True
|
||||
|
||||
def getArtwork(self, ArtistID=None, AlbumID=None):
|
||||
|
||||
from headphones import cache
|
||||
return cache.getArtwork(ArtistID, AlbumID)
|
||||
|
||||
getArtwork.exposed = True
|
||||
|
||||
def getThumb(self, ArtistID=None, AlbumID=None):
|
||||
|
||||
from headphones import cache
|
||||
return cache.getThumb(ArtistID, AlbumID)
|
||||
|
||||
getThumb.exposed = True
|
||||
|
||||
# If you just want to get the last.fm image links for an album, make sure to pass a releaseid and not a releasegroupid
|
||||
def getImageLinks(self, ArtistID=None, AlbumID=None):
|
||||
|
||||
from headphones import cache
|
||||
image_dict = cache.getImageLinks(ArtistID, AlbumID)
|
||||
|
||||
return simplejson.dumps(image_dict)
|
||||
|
||||
getImageLinks.exposed = True
|
||||
|
||||
@@ -56,6 +56,10 @@ def initialize(options={}):
|
||||
'/favicon.ico':{
|
||||
'tools.staticfile.on': True,
|
||||
'tools.staticfile.filename': "images/favicon.ico"
|
||||
},
|
||||
'/cache':{
|
||||
'tools.staticdir.on': True,
|
||||
'tools.staticdir.dir': headphones.CACHE_DIR
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user