summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul 'flowerysong' Arthur <flowerysong00@yahoo.com>2010-08-17 20:59:16 +0000
committerPaul 'flowerysong' Arthur <flowerysong00@yahoo.com>2010-08-17 20:59:16 +0000
commitdf80bd72432011010dc0e91ab564659ca6b2c500 (patch)
treec68f957da32a382bf3a542b7e7f3e54b886483ca
parent34d1449660437c2ea24dd55989efebf4e01d485f (diff)
downloadampache-df80bd72432011010dc0e91ab564659ca6b2c500.tar.gz
ampache-df80bd72432011010dc0e91ab564659ca6b2c500.tar.bz2
ampache-df80bd72432011010dc0e91ab564659ca6b2c500.zip
Refactored Last.FM recommendations; drop new dependency on curl since
Snoopy works just as well for this application.
-rw-r--r--artists.php17
-rw-r--r--config/ampache.cfg.php.dist6
-rw-r--r--lib/class/artist.class.php38
-rw-r--r--lib/class/recommendation.class.php201
-rw-r--r--lib/debug.lib.php15
-rw-r--r--templates/show_artist.inc.php3
-rw-r--r--templates/show_install_check.inc.php11
-rw-r--r--templates/show_now_playing_row.inc.php38
-rw-r--r--templates/show_recommended_artists.inc.php72
9 files changed, 322 insertions, 79 deletions
diff --git a/artists.php b/artists.php
index ea9cb414..d8fb1d91 100644
--- a/artists.php
+++ b/artists.php
@@ -34,6 +34,14 @@ switch($_REQUEST['action']) {
$object_ids = $artist->get_albums();
$object_type = 'album';
require_once Config::get('prefix') . '/templates/show_artist.inc.php';
+ if (Config::get('lastfm_api_key')) {
+ if ($object_ids = Recommendation::get_artists_like($artist->id)) {
+ // Ugly code to grab the relevant entries.
+ // Almost looks like Perl.
+ $object_ids = array_map(create_function('$i', 'return $i[\'id\'];'), $object_ids);
+ require_once Config::get('prefix') . '/templates/show_recommended_artists.inc.php';
+ }
+ }
break;
case 'show_all_songs':
$artist = new Artist($_REQUEST['artist']);
@@ -42,15 +50,6 @@ switch($_REQUEST['action']) {
$object_ids = $artist->get_songs();
require_once Config::get('prefix') . '/templates/show_artist.inc.php';
break;
-
- case 'show_like':
- $artist = new Artist($_REQUEST['artist']);
- $artist->format();
- $object_type = 'artist';
- $object_ids = $artist->get_like();
- require_once Config::get('prefix') . '/templates/show_artist.inc.php';
- break;
-
case 'update_from_tags':
$type = 'artist';
diff --git a/config/ampache.cfg.php.dist b/config/ampache.cfg.php.dist
index 13e31fee..a30988a4 100644
--- a/config/ampache.cfg.php.dist
+++ b/config/ampache.cfg.php.dist
@@ -307,9 +307,9 @@ art_order = "db,tags,folder,musicbrainz,lastfm,google"
;amazon_developer_public_key = ""
;amazon_developer_private_key = ""
-; LastFM API Key
-; Set this to your api key that you can register
-; on last.fm
+; Last.FM API Key
+; Set this to your Last.FM api key to actually use Last.FM for
+; recommendations.
;lastfm_api_key = ""
; Amazon base urls
diff --git a/lib/class/artist.class.php b/lib/class/artist.class.php
index 1009591c..f7638b94 100644
--- a/lib/class/artist.class.php
+++ b/lib/class/artist.class.php
@@ -145,44 +145,6 @@ class Artist extends database_object {
return $results;
} // get_albums
- public function get_like() {
-
- // Are you compiling with cURL?
- if (!check_php_curl()) {
- return false;
- }
-
- $result = array();
- $lastfm_api_key = Config::get('lastfm_api_key');
-
- $artistsql = "SELECT name FROM artist WHERE id = \"" . $this->id . "\"";
- $artist_result = Dba::query($artistsql);
- $r = Dba::fetch_assoc($artist_result);
- $searchArtist = preg_replace('/ /', '%20', $r['name']);
-
- $lastsite = "http://ws.audioscrobbler.com/2.0/?method=artist.getsimilar&artist=" . $searchArtist . "&api_key=" . $lastfm_api_key;
- debug_event('Similar', 'search url : ' . $lastsite, 5);
- $lastch = curl_init();
- curl_setopt($lastch, CURLOPT_URL, $lastsite);
- curl_setopt($lastch, CURLOPT_RETURNTRANSFER, 1);
-
- $lastxml = simplexml_load_string( curl_exec($lastch) );
- $lastcontent = curl_exec($lastch);
- $lastxml = simplexml_load_string( $lastcontent );
-
- foreach( $lastxml->similarartists->children() as $lastchild ) {
- $check_query = 'SELECT * FROM artist WHERE name = \'' . $lastchild->name . '\'';
- $check_result = Dba::query($check_query);
- $row = Dba::fetch_assoc($check_result);
- if( !is_null($row['id']) ) {
- $result[] = $row['id'];
- // debug_event('Similar', 'row return: ' . $row['id'], 5);
- }
- }
-
- return $result;
-
- } // get_like
/**
* get_songs
diff --git a/lib/class/recommendation.class.php b/lib/class/recommendation.class.php
new file mode 100644
index 00000000..0852780d
--- /dev/null
+++ b/lib/class/recommendation.class.php
@@ -0,0 +1,201 @@
+<?php
+/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/*
+
+ Copyright (c) Ampache.org
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License v2
+ as published by the Free Software Foundation.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+/**
+ * Recommendation Class
+ */
+class Recommendation {
+
+ /**
+ * Constructor
+ * Not on my watch, boyo.
+ */
+ private function __construct() {
+ return false;
+ } //constructor
+
+ /**
+ * get_lastfm_results
+ * Runs a last.fm query and returns the parsed results
+ */
+ private static function get_lastfm_results($method, $query) {
+ $api_key = Config::get('lastfm_api_key');
+ $api_base = "http://ws.audioscrobbler.com/2.0/?method=";
+ $url = $api_base . $method . '&api_key=' . $api_key . '&' . $query;
+ debug_event('Recommendation', 'search url : ' . $url, 5);
+
+ $snoopy = new Snoopy();
+ if(Config::get('proxy_host') AND Config::get('proxy_port')) {
+ $snoopy->proxy_user = Config::get('proxy_host');
+ $snoopy->proxy_port = Config::get('proxy_port');
+ $snoopy->proxy_user = Config::get('proxy_user');
+ $snoopy->proxy_pass = Config::get('proxy_pass');
+ }
+ $snoopy->fetch($url);
+ $content = $snoopy->results;
+
+ return simplexml_load_string($content);
+ } // get_lastfm_results
+
+ /**
+ * get_songs_like
+ * Returns a list of similar songs
+ */
+ public static function get_songs_like($song_id, $limit = 5, $local_only = true) {
+ $song = new Song($song_id);
+
+ if (isset($song->mbid)) {
+ $query = 'mbid=' . rawurlencode($song->mbid);
+ }
+ else {
+ $query = 'track=' . rawurlencode($song->title);
+ }
+
+ if ($limit && !$local_only) {
+ $query .= "&limit=$limit";
+ }
+
+ $xml = self::get_lastfm_results('track.getsimilar', $query);
+
+ foreach ($xml->similartracks->children() as $child) {
+ $name = $child->name;
+ $local_id = null;
+
+ $artist_name = $child->artist->name;
+ $s_artist_name = Catalog::trim_prefix($artist_name);
+ $s_artist_name = Dba::escape($s_artist_name['string']);
+
+ $sql = "SELECT `song`.`id` FROM `song` " .
+ "LEFT JOIN `artist` ON " .
+ "`song`.`artist`=`artist`.`id` WHERE " .
+ "`song`.`title`='" . Dba::escape($name) .
+ "' AND `artist`.`name`='$s_artist_name'";
+
+ $db_result = Dba::read($sql);
+
+ if ($result = Dba::fetch_assoc($db_result)) {
+ $local_id = $result['id'];
+ }
+
+ if (is_null($local_id)) {
+ debug_event('Recommendation', "$name did not match any local song", 5);
+ if (! $local_only) {
+ $results[] = array(
+ 'id' => null,
+ 'title' => $name,
+ 'artist' => $artist_name
+ );
+ }
+ }
+ else {
+ debug_event('Recommendation', "$name matched local song $local_id", 5);
+ $results[] = array(
+ 'id' => $local_id,
+ 'title' => $name
+ );
+ }
+
+ if ($limit && count($results) >= $limit) {
+ break;
+ }
+ }
+
+ if (isset($results)) {
+ return $results;
+ }
+
+ return false;
+ }
+
+ /**
+ * get_artists_like
+ * Returns a list of similar artists
+ */
+ public static function get_artists_like($artist_id, $limit = 5, $local_only = true) {
+ $artist = new Artist($artist_id);
+
+ $query = 'artist=' . rawurlencode($artist->name);
+ if ($limit && !$local_only) {
+ $query .= "&limit=$limit";
+ }
+
+ $xml = self::get_lastfm_results('artist.getsimilar', $query);
+
+ foreach ($xml->similarartists->children() as $child) {
+ $name = $child->name;
+ $local_id = null;
+
+ // First we check by MBID
+ if ((string)$child->mbid) {
+ $mbid = Dba::escape($child->mbid);
+ $sql = "SELECT `id` FROM `artist` WHERE `mbid`='$mbid'";
+ $db_result = Dba::read($sql);
+ if ($result = Dba::fetch_assoc($db_result)) {
+ $local_id = $result['id'];
+ }
+ }
+
+ // Then we fall back to the less likely to work exact
+ // name match
+ if (is_null($local_id)) {
+ $searchname = Catalog::trim_prefix($name);
+ $searchname = Dba::escape($searchname['string']);
+ $sql = "SELECT `id` FROM `artist` WHERE `name`='$searchname'";
+ $db_result = Dba::read($sql);
+ if ($result = Dba::fetch_assoc($db_result)) {
+ $local_id = $result['id'];
+ }
+ }
+
+ // Then we give up
+ if (is_null($local_id)) {
+ debug_event('Recommendation', "$name did not match any local artist", 5);
+ if (! $local_only) {
+ $results[] = array(
+ 'id' => null,
+ 'name' => $name
+ );
+ }
+ }
+ else {
+ debug_event('Recommendation', "$name matched local artist " . $local_id, 5);
+ $results[] = array(
+ 'id' => $local_id,
+ 'name' => $name
+ );
+ }
+
+ // Don't do more work than we have to
+ if ($limit && count($results) >= $limit) {
+ break;
+ }
+ }
+
+ if (isset($results)) {
+ return $results;
+ }
+
+ return false;
+ } // get_artists_like
+
+} // end of recommendation class
+?>
diff --git a/lib/debug.lib.php b/lib/debug.lib.php
index e49cb065..4464447e 100644
--- a/lib/debug.lib.php
+++ b/lib/debug.lib.php
@@ -157,21 +157,6 @@ function check_php_pcre() {
} // check_php_pcre
/**
- * check_php_curl
- * This makes sure they have cURL (curl_???) support
- * compiled into PHP this is optional
- */
-function check_php_curl() {
-
- if (!extension_loaded('curl')) {
- return false;
- }
-
- return true;
-
-} // check_php_curl
-
-/**
* check_config_values
* checks to make sure that they have at least set the needed variables
*/
diff --git a/templates/show_artist.inc.php b/templates/show_artist.inc.php
index d14bc665..408e6b5e 100644
--- a/templates/show_artist.inc.php
+++ b/templates/show_artist.inc.php
@@ -54,9 +54,6 @@ if (Config::get('ratings')) {
<?php echo Ajax::button('?action=basket&type=artist_random&id=' . $artist->id,'random',_('Random'),'random_' . $artist->id); ?>
<?php echo Ajax::text('?action=basket&type=artist_random&id=' . $artist->id, sprintf(_('Add Random Songs By %s'), $artist->f_name),'random_text_' . $artist->id); ?>
</li>
-<li>
- <a href="<?php echo $web_path; ?>/artists.php?action=show_like&amp;artist=<?php echo $artist->id; ?>"><?php echo get_user_icon('view'); ?></a> <a href="<?php echo $web_path; ?>/artists.php?action=show_like&amp;artist=<?php echo $artist->id; ?>"><?php printf(_("Show Similar to %s"), $artist->f_name); ?></a>
-</li>
<?php if (Access::check('interface','50')) { ?>
<li>
<a href="<?php echo $web_path; ?>/artists.php?action=update_from_tags&amp;artist=<?php echo $artist->id; ?>"><?php echo get_user_icon('cog', _('Update from tags')); ?></a>
diff --git a/templates/show_install_check.inc.php b/templates/show_install_check.inc.php
index 97bdb64b..08952496 100644
--- a/templates/show_install_check.inc.php
+++ b/templates/show_install_check.inc.php
@@ -174,16 +174,5 @@
}
?>
</td>
-</tr><tr>
-<td><?php echo _('PHP cURL extension Support'); ?>:</td>
-<td>
-<?php
- if (!check_php_curl()) {
- echo debug_result(_('Some functions might not run correctly.'), false);
- }
- else {
- echo debug_result(_(''), true);
- }
-?>
</tr>
</table>
diff --git a/templates/show_now_playing_row.inc.php b/templates/show_now_playing_row.inc.php
index ad33429f..c6f4988f 100644
--- a/templates/show_now_playing_row.inc.php
+++ b/templates/show_now_playing_row.inc.php
@@ -82,3 +82,41 @@ $artist = scrub_out(truncate_with_ellipsis($media->f_artist_full));
</div>
</div>
<?php } // end play album art ?>
+
+<?php if (Config::get('show_similar')) { ?>
+<div class="np_group">
+<?php if ($artists = Recommendation::get_artists_like($media->artist, 3, false)) { ?>
+ <div class="np_cel cel_similar">
+ <label><?php echo _('Similar Artists'); ?></label>
+ <?php foreach ($artists as $a) { ?>
+ <div class="np_cel cel_similar_artist">
+ <?php
+ if (is_null($a['id'])) {
+ echo scrub_out(truncate_with_ellipsis($a['name']), Config::get('ellipse_threshold_artist'));
+ }
+ else {
+ $artist = new Artist($a['id']);
+ $artist->format();
+ echo $artist->f_name_link;
+ }
+ ?>
+ </div>
+ <?php } // end foreach ?>
+ </div>
+<?php } // end show similar artists ?>
+<?php if ($songs = Recommendation::get_songs_like($media->id, 3)) { ?>
+ <div class="np_cel cel_similar">
+ <label><?php echo _('Similar Songs'); ?></label>
+ <?php foreach ($songs as $s) { ?>
+ <div class="np_cel cel_similar_song">
+ <?php
+ $song = new Song($s['id']);
+ $song->format();
+ echo $song->f_link;
+ ?>
+ </div>
+ <?php } // end foreach ?>
+ </div>
+<?php } // end show similar songs ?>
+</div>
+<?php } // end show similar things ?>
diff --git a/templates/show_recommended_artists.inc.php b/templates/show_recommended_artists.inc.php
new file mode 100644
index 00000000..459e2d63
--- /dev/null
+++ b/templates/show_recommended_artists.inc.php
@@ -0,0 +1,72 @@
+<?php
+/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
+/*
+
+ Copyright (c) Ampache.org
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License v2
+ as published by the Free Software Foundation.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+?>
+<?php show_box_top(_('Similar Artists'), 'info-box'); ?>
+<table class="tabledata" cellpadding="0" cellspacing="0">
+<colgroup>
+ <col id="col_add" />
+ <col id="col_artist" />
+ <col id="col_songs" />
+ <col id="col_albums" />
+ <col id="col_tags" />
+ <col id="col_rating" />
+ <col id="col_action" />
+</colgroup>
+<tr class="th-top">
+ <th class="cel_add"><?php echo _('Add'); ?></th>
+ <th class="cel_artist"><?php echo _('Artist'); ?></th>
+ <th class="cel_songs"><?php echo _('Songs'); ?></th>
+ <th class="cel_albums"><?php echo _('Albums'); ?></th>
+ <th class="cel_time"><?php echo _('Time'); ?></th>
+ <th class="cel_tags"><?php echo _('Tags'); ?></th>
+ <th class="cel_rating"> <?php echo _('Rating'); ?> </th>
+ <th class="cel_action"> <?php echo _('Action'); ?> </th>
+</tr>
+<?php
+// Cache the ratings we are going to use
+if (Config::get('ratings')) { Rating::build_cache('artist',$object_ids); }
+
+/* Foreach through every artist that has been passed to us */
+foreach ($object_ids as $artist_id) {
+ $artist = new Artist($artist_id);
+ $artist->format();
+?>
+<tr id="artist_<?php echo $artist->id; ?>" class="<?php echo flip_class(); ?>">
+ <?php require Config::get('prefix') . '/templates/show_artist_row.inc.php'; ?>
+</tr>
+<?php } //end foreach ($artists as $artist) ?>
+<?php if (!count($object_ids)) { ?>
+<tr class="<?php echo flip_class(); ?>">
+ <td colspan="5"><span class="fatalerror"><?php echo _('Not Enough Data'); ?></span></td>
+</tr>
+<?php } ?>
+<tr class="th-bottom">
+ <th class="cel_add"><?php echo _('Add'); ?></th>
+ <th class="cel_artist"><?php echo _('Artist'); ?></th>
+ <th class="cel_songs"> <?php echo _('Songs'); ?> </th>
+ <th class="cel_albums"> <?php echo _('Albums'); ?> </th>
+ <th class="cel_time"> <?php echo _('Time'); ?> </th>
+ <th class="cel_tags"><?php echo _('Tags'); ?></th>
+ <th class="cel_rating"> <?php echo _('Rating'); ?> </th>
+ <th class="cel_action"> <?php echo _('Action'); ?> </th>
+</tr>
+</table>