<?php
/*
Plugin Name: Audioscrobbler album list builder
Version: 0.1
Plugin URI: http://www.qwghlm.co.uk/
Description: Uses Audioscrobbler & the Amazon API to work out what albums you have been listening to, and updates the Amazon Media Manager plugin for WP as a result.
Author: Chris Applegate
Author URI: http://www.qwghlm.co.uk/

Copyright (c) 2005
Released under the GPL
http://www.gnu.org/licenses/gpl.txt

Installation instructions:

* First you will need:
 - The Magpie RSS reader installed somewhere (default /plugins/magpierss/)
 - Amazon API for PHP installed too (default /plugins/amazonAPI/). This will also require NuSoap.

 - For it to work in WordPress, you will also need the Amazon Media Manager installed

* Then - configure the first lines of this file for the paths to Magpie and the Amazon API, and your developer tag
* If you want to use amazon media manager then configure the variable $amazonTable
* Put this in your plugins folder and activate

* To use, call the following lines of code:

    fetch_recent_albums("qwghlm");           // To get the albums for username qwghlm
    get_media(2,5,0,'<li>','</li>','');      // To display with Media Manager

*/

$scrobblerURL "http://ws.audioscrobbler.com/rdf/history/";

// Path of the Amazon PHP-SOAP API
$amazonAPIPath ABSPATH."wp-admin/";

// Path of the Magpie RSS reader
$magpiePath ABSPATH."wp-content/plugins/magpierss/";
// Path of Magpie`s cache
$magpieCachePath "/usr/local/psa/home/vhosts/qwghlm.co.uk/httpdocs/tmp";

// How often to check, in seconds
$updateTime 1800;

// Set Amazon associates tag
$Tag   '';

// Set Amazon developer token
$Token '';

// Set Amazon locale
$Locale 'uk';

// Name of the amazon table
$amazonTable "ae_data";

function 
fetch_recent_albums($username) {

    global 
$magpiePath$magpieCachePath$updateTime;
    global 
$amazonAPIPath$Tag$Token$Locale;
    global 
$scrobblerURL;

    echo 
"<!--  ";

    
// If the media manager needs to be updated...
    // If you don`t want to use media manager, you can still use the codeblock inside
    // this if statement to fetch & process the data, for another application

    
if ($_GET[force] || mm_needs_updating()) {

        echo 
"Time to re-check the feed...\n";

        
define('MAGPIE_CACHE_DIR'$magpieCachePath);
        
define('MAGPIE_CACHE_AGE', ($updateTime 60).'s');
            
// A minute shorter than the regularity of checking database, so we always get a new one
        
define('MAGPIE_FETCH_TIME_OUT'15);
            
// Timeout is normally 5s, but it`s been a bit slow of late

        
require_once($magpiePath 'rss_fetch.inc');

        
$rss fetch_rss($scrobblerURL.$username);

        if (
$rss and !$rss->ERROR) {
            
$items $rss->items;

            
$artistAlbums = array();
            
$trackDates = array();

            
$artists = array();
            
$albums = array();
            
$albumDates = array();

            
// echo "Fetching array:"; print_r($items);

            // First get the artist and album for each track in the RSS feed
            // We want to get unique album/artist combinations
            // So we glue artist and album them together in an array, then serialise it

            
foreach ($items as $item) {
                
$thisEntry serialize(array ("artist" => $item[dc][artist_creator_title],
                                    
"album" => $item[dc][albumlist_album_title]));
                
$artistAlbums[] = $thisEntry;

                
// Get date this particular track was played by splitting off the date portion from the timestamp
                
$trackDates[$thisEntry] = array_shift(split("T"$item[dc][date]));
            }
            
// echo "Artist/album combos:"; print_r ($artistAlbums); print_r ($trackDates);

            // Create a count of each element in $artistsAlbum, also reverse (to get earliest song first)
            
$artistAlbumCounts array_reverse(array_count_values($artistAlbums));

            
// Go through the count and only extract the ones with more than two tracks
            // (You can reduce this to one it you want it to be less strict, I suppose)

            
foreach ($artistAlbumCounts as $artistAlbum => $count) {
                if (
$count 2) {
                    
$a unserialize($artistAlbum);

                    
// Only process if an album title is actually given!
                    
if (!empty($a['album'])) {

                        
// We remove accents from names of album and artists, as the Amazon search API doesn't like them
                        // It mistakes them for string terminators or something (not sure)
                        // This equires the WordPress remove_accents() function; if you're using outside of WP then
                        // you can declare a quick 'n dirty version thus:
                        // function remove_accents() { return preg_replace("/&([a-z])[a-z]+;/i","$1",htmlentities($string)); }

                        
$artists[] = remove_accents($a['artist']);
                        
$albums[] = remove_accents($a['album']);

                        
// Work out what date this album was played
                        
$albumDates[] = $trackDates[$artistAlbum];
                    }
                }
            }

            
// echo "Individual albums/artists:"; print_r($artists); print_r($albums); print_r($albumDates);

            // Get the amazon search API
            
require_once ($amazonAPIPath.'AmazonSearch2.php');

            
$AS = new AmazonSearch($Token$Tag$Localetrue);

            for (
$i=0$i<count($artists); $i++) {

                
$Results $AS->DoKeywordSearch($artists[$i].' '.$albums[$i], 'lite''music'10);

                
// print_r($Results);

                
$thisAlbum null;

                
// Self-titled albums may not return the correct result first (as we sent a query in the form of
                // e.g. "Blur Blur", so we search thought all the results and pick one that contains the self-title

                // We don't do this check for non-self-titled albums in case there is a minor difference
                // (e.g. '&' vs. 'and') between Amazon and Audioscrobbler's versions of the title, Amazon
                // has probably returned the right result in any case.

                
if ($artists[$i] == $albums[$i])  {

                    
// First to see if there is an identically-named album given
                    
for ($j=0$j<count($Results); $j++) {
                        if (
$Results[$j]['ProductName'] == $albums[$i]) {
                            
$thisAlbum $Results[$j];
                            break;
                        }
                    }

                    
// If we haven`t found it, then this will find a partial match e.g. "The Band EP" (warning: may return dodgy results!)
                    
if ($thisAlbum == null) {
                        for (
$j=0$j<count($Results); $j++) {
                            if (
stristr($Results[$j]['ProductName'],$albums[$i]) !== false) {
                                
$thisAlbum $Results[$j];
                                break;
                            }
                        }
                    }

                    
// There is no guarantee we`ll get a match, btw
                
}
                else {
                    
$thisAlbum $Results[0];
                }

                
// print_r($thisAlbum);

                // Update the media manager with this album (if we have one)
                // (If you don`t want to use media manager then comment/delete this line and do what you like with the code)
                // You will probably want to store the results in a database or cache...

                
if ($thisAlbum != null)
                    
update_mediamanager($thisAlbum$albumDates[$i], $artists[$i], $albums[$i]);

                else echo 
"Can't find album/artist combo for:".$artists[$i].' '.$albums[$i];
            }
        }
        else {
            echo 
"Error: " $rss->ERROR;
        }
    }
    else {
        echo 
"No need to update, skipping...";
    }

    echo 
" -->";
}

// Checks to see if Media Manager needs updating
function mm_needs_updating() {

    global 
$wpdb$amazonTable$updateTime;

    
// Get last time the table was updated
    
$tableStatus $wpdb->get_row("SHOW TABLE STATUS LIKE '$amazonTable'");

    if (
$tableStatus->Name != $amazonTable) {
        die (
"Wrong table ".$tableStatus->Name." - terminating");
    }
    
$lastUpdated strtotime($tableStatus->Update_time);
    
// echo "Table ".$tableStatus->Name." last updated: ".date('r', $lastUpdated)."\n";

    // Randomising code idea comes from LinuxBrit's del.icio.us plugin: http://linuxbrit.co.uk/
    // randomise a bit, between 30 and 60s "off the mark" to avoid a bunch of
    // requests all simultaneously deciding to refresh the file

    
srand((double)microtime()*1000000);
    
$lastUpdated += 30 rand(060);

    if (
time() > $lastUpdated $updateTime) {
        
$wpdb->query("ALTER TABLE $amazonTable COMMENT = 'Last updated by Audioscrobbler on ".date('r')."'");
        return 
true;
    }
    else {
        return 
false;
//        return true;
    
}
}


// Updates media manager
function update_mediamanager($amazonSearchItem$rdfDate$rdfArtist$rdfAlbum) {

    global 
$wpdb$amazonTable;

    
// Gets data about the item
    
$fv_type $amazonSearchItem['Catalog'];
    
$fv_code $amazonSearchItem['Asin'];
    
$fv_itemtitle htmlspecialchars($amazonSearchItem['ProductName'], ENT_QUOTES);
    
$fv_authors htmlspecialchars($amazonSearchItem['Artists'][0], ENT_QUOTES);
    
$fv_url $amazonSearchItem['Url'];
    
$fv_image $amazonSearchItem['ImageUrlSmall'];
    
$fv_comment "Added/updated automatically from Audioscrobbler on ".date('r')." for $rdfAlbum by $rdfArtist";

    
$dateadded $rdfDate;

    
// Checks to see if there are existing entry
    
$existing $wpdb->get_var("SELECT COUNT(*) FROM $amazonTable WHERE itemtitle='$fv_itemtitle' && authors='$fv_authors'");

    
$sqlQuery "";
    if (
$existing 0) {
        echo 
"Existing entry for $fv_itemtitle by $fv_authors! Updating time/date only\n";

        
$sqlQuery "UPDATE $amazonTable
                    SET dateadded='$dateadded',
                    comment='$fv_comment'
                    WHERE itemtitle='$fv_itemtitle' && authors='$fv_authors' LIMIT 1"
;
    }
    else {


        
// Check size of the image supplied, if less than 1kB then probably blank so we should ignore
        
$ch curl_init($fv_image);
        
curl_setopt($chCURLOPT_RETURNTRANSFER1);
        
curl_exec($ch);
        
$imgInfo curl_getinfo($ch);
        
$byteCount $imgInfo['size_download'];
        echo 
"File is $byteCount bytes\n";

        if (
$byteCount 1024) {
            echo 
"Not adding (image supplied too small!)\n";
        }
        else {

            echo 
"New entry! Inserting $fv_itemtitle by $fv_authors into table...\n";
            
$sqlQuery "INSERT INTO $amazonTable
                        SET type='$fv_type',
                        code='$fv_code',
                        itemtitle='$fv_itemtitle',
                        authors='$fv_authors',
                        url='$fv_url',
                        image='$fv_image',
                        comment='$fv_comment',
                        dateadded='$dateadded'"
;
        }
    }

    if (!empty(
$sqlQuery))
        
$wpdb->query($sqlQuery);

}

?>