%PDF- %PDF-
| Direktori : /data/www_bck/varak.net_bck/gnufm.varak.net/api/ |
| Current File : //data/www_bck/varak.net_bck/gnufm.varak.net/api/UserXML.php |
<?php
/* GNU FM -- a free network service for sharing your music listening habits
Copyright (C) 2009 Free Software Foundation, Inc
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
require_once($install_path . '/database.php');
require_once($install_path . '/data/User.php');
require_once('xml.php');
/**
* Class with functions that returns XML-formatted data for users.
*
* These functions are mainly used by web service methods.
*
* @package API
*/
class UserXML {
public static function getInfo($username) {
try {
$user = new User($username);
} catch (Exception $e) {
return XML::error('failed', '7', 'Invalid resource specified');
}
$xml = new SimpleXMLElement('<lfm status="ok"></lfm>');
$user_node = $xml->addChild('user', null);
$user_node->addChild('name', $user->name);
$user_node->addChild('realname', $user->fullname);
$user_node->addChild('homepage', $user->homepage);
$user_node->addChild('location', $user->location);
$ic = $user_node->addChild('image', repamp($user->getAvatar(34)));
$ic->addAttribute('size', 'small');
$ic = $user_node->addChild('image', repamp($user->getAvatar(64)));
$ic->addAttribute('size', 'medium');
$ic = $user_node->addChild('image', repamp($user->getAvatar(126)));
$ic->addAttribute('size', 'large');
$ic = $user_node->addChild('image', repamp($user->getAvatar(252)));
$ic->addAttribute('size', 'extralarge');
$user_node->addChild('bio', $user->bio);
$user_node->addChild('url', $user->getURL());
$user_node->addChild('playcount', $user->getTotalTracks());
$user_node->addChild('profile_created', strftime('%c', $user->created));
if (isset($user->modified)) {
$user_node->addChild('profile_updated', strftime('%c', $user->modified));
}
return $xml;
}
public static function getTopArtists($username, $limit, $streamable, $page, $period, $cache) {
global $adodb;
try {
$timestamp = UserXML::_periodToTimestamp($period);
} catch (Exception $e) {
return(XML::error('error', '13', 'Invalid method signature supplied'));
}
$offset = ($page - 1) * $limit;
$begin = $timestamp - ($timestamp % 3600);
try {
$user = new User($username);
$res = $user->getTopArtists($limit, $offset, $streamable, $begin, null, $cache);
} catch (Exception $e) {
return XML::error('error', '7', 'Invalid resource specified');
}
$query = 'SELECT COUNT(DISTINCT(artist)) FROM Scrobbles s';
if($streamable) {
$query .= ' INNER JOIN Artist a ON s.artist=a.name WHERE a.streamable=1';
$andquery = True;
} else {
$query .= ' WHERE';
$andquery = False;
}
if ($begin) {
$andquery ? $query .= ' AND' : $andquery = True;
$query .= ' time>' . $begin;
}
$andquery ? $query .= ' AND' : null;
$query .= ' userid=' . $user->uniqueid;
$total = $adodb->CacheGetOne($cache, $query);
$totalPages = ceil($total/$limit);
$xml = new SimpleXMLElement('<lfm status="ok"></lfm>');
$root = $xml->addChild('topartists', null);
$root->addAttribute('user', $user->name);
$root->addAttribute('type', $period);
$root->addAttribute('page', $page);
$root->addAttribute('perPage', $limit);
$root->addAttribute('totalPages', $totalPages);
$root->addAttribute('total', $total);
$i = $offset + 1;
foreach($res as &$row) {
$artist_node = $root->addChild('artist', null);
$artist_node->addAttribute('rank', $i);
$artist_node->addChild('name', repamp($row['artist']));
$artist_node->addChild('playcount', $row['freq']);
try {
$artist = new Artist($row['artist']);
$artist_node->addChild('mbid', $artist->mbid);
$artist_node->addChild('url', $artist->geturl());
$artist_node->addChild('streamable', $artist->streamable);
$image_small = $artist_node->addChild('image', $artist->image_small);
$image_small->addAttribute('size', 'small');
$image_medium = $artist_node->addChild('image', $artist->image_medium);
$image_medium->addAttribute('size', 'medium');
$image_large = $artist_node->addChild('image', $artist->image_large);
$image_large->addAttribute('size', 'large');
} catch (Exception $e) {}
$i++;
}
return $xml;
}
public static function getTopTracks($username, $limit, $streamable, $page, $period, $cache) {
global $adodb;
try {
$timestamp = UserXML::_periodToTimestamp($period);
} catch (Exception $e) {
return(XML::error('error', '13', 'Invalid method signature supplied'));
}
$offset = ($page - 1) * $limit;
$begin = $timestamp - ($timestamp % 3600);
try {
$user = new User($username);
$res = $user->getTopTracks($limit, $offset, $streamable, $begin, null, $cache);
} catch (Exception $e) {
return XML::error('error', '7', 'Invalid resource specified');
}
// Get total track count, using subquery to get distinct row(artist, track) count
$query = 'SELECT count(*) FROM (SELECT count(*) FROM Scrobbles s';
if($streamable) {
$query .= ' WHERE ROW(s.artist, s.track) IN (SELECT artist_name, name FROM Track WHERE streamable=1)';
$andquery = True;
} else {
$query .= ' WHERE';
$andquery = False;
}
if ($begin) {
$andquery ? $query .= ' AND' : $andquery = True;
$query .= ' time>' . $begin;
}
$andquery ? $query .= ' AND' : null;
$query .= ' userid=' . $user->uniqueid . ' GROUP BY s.track, s.artist) c';
$total = $adodb->CacheGetOne($cache, $query);
$totalPages = ceil($total/$limit);
$xml = new SimpleXMLElement('<lfm status="ok"></lfm>');
$root = $xml->addChild('toptracks', null);
$root->addAttribute('user', $user->name);
$root->addAttribute('type', $period);
$root->addAttribute('page', $page);
$root->addAttribute('perPage', $limit);
$root->addAttribute('totalPages', $totalPages);
$root->addAttribute('total', $total);
$i = $offset + 1;
foreach($res as &$row) {
try {
$track = new Track($row['track'], $row['artist']);
$artist = $track->getArtist();
$track_node = $root->addChild('track', null);
$track_node->addAttribute('rank', $i);
$track_node->addChild('name', repamp($track->name));
$track_node->addChild('duration', $track->duration);
$track_node->addChild('playcount', $row['freq']);
$track_node->addChild('mbid', $track->mbid);
$track_node->addChild('url', repamp($row['trackurl']));
$track_node->addChild('streamable', $track->streamable);
$artist_node = $track_node->addChild('artist', null);
$artist_node->addChild('name', repamp($artist->name));
$artist_node->addChild('mbid', $artist->mbid);
$artist_node->addChild('url', repamp($row['artisturl']));
$image_small = $track_node->addChild('image', $artist->image_small);
$image_small->addAttribute('size', 'small');
$image_medium = $track_node->addChild('image', $artist->image_medium);
$image_medium->addAttribute('size', 'medium');
$image_large = $track_node->addChild('image', $artist->image_large);
$image_large->addAttribute('size', 'large');
} catch (Exception $e) {}
$i++;
}
return $xml;
}
public static function getRecentTracks($u, $limit, $page, $from, $to) {
global $adodb;
if (!isset($limit)) {
$limit = 10;
}
$offset = ($page - 1) * $limit;
$err = 0;
try {
$user = new User($u);
if ($page == 1) {
$npres = $user->getNowPlaying(1);
}
$res = $user->getScrobbles($limit, $offset, $from, $to);
} catch (Exception $e) {
$err = 1;
}
if ($err || !$res) {
return(XML::error('error', '7', 'Invalid resource specified'));
}
$totalTracks = $user->getTotalTracks();
$totalPages = ceil($totalTracks / $limit);
$xml = new SimpleXMLElement('<lfm status="ok"></lfm>');
$root = $xml->addChild('recenttracks', null);
$root->addAttribute('user', $user->name);
$root->addAttribute('page', $page);
$root->addAttribute('perPage', $limit);
$root->addAttribute('totalPages', $totalPages);
if ($npres) {
foreach ($npres as &$row) {
$track = $root->addChild('track');
$track->addAttribute('nowplaying', 'true');
$row['time'] = time();
UserXML::_addTrackDetails($track, $row);
}
}
foreach ($res as &$row) {
$track = $root->addChild('track', null);
UserXML::_addTrackDetails($track, $row);
}
return $xml;
}
private static function _addTrackDetails($track, $row) {
$artist = $track->addChild('artist', repamp($row['artist']));
$artist->addAttribute('mbid', $row['artist_mbid']);
$name = $track->addChild('name', repamp($row['track']));
$track->addChild('mbid', $row['mbid']);
$album = $track->addChild('album', repamp($row['album']));
$album->addAttribute('mbid', $row['album_mbid']);
$track->addChild('url', repamp(Server::getTrackURL($row['artist'], $row['album'], $row['track'])));
$date = $track->addChild('date', gmdate('d M Y H:i', $row['time']) . ' GMT');
$date->addAttribute('uts', $row['time']);
$track->addChild('streamable', null);
}
private static function _periodToTimestamp($period) {
//TODO: Do better, this is too ugly :\
if (strcmp($period, 'overall') == 0) {
$timestamp = 0;
} else if (strcmp($period, '7day') == 0) {
$timestamp = strtotime('-7 days');
} else if (strcmp($period, '1month') == 0) {
$timestamp = strtotime('-1 month');
} else if (strcmp($period, '3month') == 0) {
$timestamp = strtotime('-3 months');
} else if (strcmp($period, '6month') == 0) {
$timestamp = strtotime('-6 months');
} else if (strcmp($period, '12month') == 0) {
$timestamp = strtotime('-12 months');
} else {
throw new Exception("Not a valid period");
}
return $timestamp;
}
public static function getTopTags($u, $limit, $cache) {
global $base_url;
try {
$user = new User($u);
$res = $user->getTopTags($limit, 0, $cache);
} catch (Exception $e) {
return XML::error('error', '7', 'Invalid resource specified');
}
if(!$res) {
return XML::error('error', '6', 'No tags for this user');
}
$xml = new SimpleXMLElement('<lfm status="ok"></lfm>');
$root = $xml->addChild('toptags');
$root->addAttribute('user', $user->name);
foreach ($res as &$row) {
$tag = $root->addChild('tag', null);
$tag->addChild('name', repamp($row['tag']));
$tag->addChild('count', repamp($row['freq']));
$tag->addChild('url', Server::getTagURL($row['tag']));
}
return $xml;
}
public static function getPersonalTags($u, $tag, $taggingtype, $limit, $page, $cache, $streamable) {
$offset = ($page - 1) * $limit;
try {
$user = new User($u);
$res = $user->getPersonalTags($tag, $taggingtype, $limit, $offset, $cache, $streamable);
} catch (Exception $e) {
return XML::error('error', '7', 'Invalid resource specified');
}
if(!$res) {
return XML::error('error', '6', 'No tag with this name');
}
$xml = new SimpleXMLElement('<lfm status="ok"></lfm>');
$root = $xml->addChild('taggings');
$root->addAttribute('user', repamp($user->name));
$root->addAttribute('tag', repamp($tag));
$root->addAttribute('page', $page);
$root->addAttribute('perPage', $limit);
$root->addAttribute('totalPages', null); //TODO
$root->addAttribute('total', null); //TODO
if(strtolower($taggingtype) == 'artist') {
$artists = $root->addChild('artists', null);
foreach($res as &$row) {
$artist = new Artist($row['artist']);
$artist_node = $artists->addChild('artist', null);
$artist_node->addChild('name', repamp($artist->name));
$artist_node->addChild('mbid', $artist->mbid);
$artist_node->addChild('url', $artist->getURL());
$artist_node->addChild('streamable', $artist->streamable);
$image_small = $artist_node->addchild('image', $artist->image_small);
$image_small->addAttribute('size', 'small');
$image_medium = $artist_node->addchild('image', $artist->image_medium);
$image_medium->addAttribute('size', 'medium');
$image_large = $artist_node->addchild('image', $artist->image_large);
$image_large->addAttribute('size', 'large');
}
}elseif(strtolower($taggingtype) == 'album') {
$albums = $root->addChild('albums', null);
foreach($res as &$row) {
$album = new Album($row['album'], $row['artist']);
$album_node = $albums->addChild('album', null);
$album_node->addChild('name', repamp($album->name));
$album_node->addChild('mbid', $album->mbid);
$album_node->addChild('url', $album->getURL());
$artist = new Artist($row['artist']);
$artist_node = $album_node->addChild('artist', null);
$artist_node->addChild('name', repamp($artist->name));
$artist_node->addChild('mbid', $artist->mbid);
$artist_node->addChild('url', $artist->getURL());
$album_node->addChild('image', $album->image);
}
}elseif(strtolower($taggingtype) == 'track') {
$tracks = $root->addChild('tracks', null);
foreach($res as &$row) {
$track = new Track($row['track'], $row['artist']);
$track_node = $tracks->addChild('track', null);
$track_node->addChild('name', repamp($track->name));
$track_node->addChild('duration', $track->duration);
$track_node->addChild('mbid', $track->mbid);
$track_node->addChild('url', $track->getURL());
$track_node->addChild('streamable', $track->streamable);
$artist = new Artist($row['artist']);
$artist_node = $track_node->addChild('artist', null);
$artist_node->addChild('name', repamp($artist->name));
$artist_node->addChild('mbid', $artist->mbid);
$artist_node->addChild('url', $artist->getURL());
$image_small = $track_node->addchild('image', $artist->image_small);
$image_small->addAttribute('size', 'small');
$image_medium = $track_node->addchild('image', $artist->image_medium);
$image_medium->addAttribute('size', 'medium');
$image_large = $track_node->addchild('image', $artist->image_large);
$image_large->addAttribute('size', 'large');
}
} else {
return XML::error('error', '7', 'Invalid resource specified');
}
return $xml;
}
public static function getTagInfo($u, $tag, $cache) {
try {
$user = new User($u);
$res = $user->getTagInfo($tag, $cache);
} catch (Exception $e) {
return XML::error('error', '7', 'Invalid resource specified');
}
if(!$res) {
return XML::error('error', '6', 'No tag with that name');
}
$xml = new SimpleXMLElement('<lfm status="ok"></lfm>');
$root = $xml->addChild('tag');
$root->addChild('name', repamp($tag));
$root->addChild('url', Server::getTagURL($tag));
$root->addChild('taggings', $res[0]['freq']);
return $xml;
}
public static function getLovedTracks($username, $limit = 50, $page = 1, $streamable = False, $cache = 600) {
global $adodb;
$offset = ($page - 1) * $limit;
try {
$user = new User($username);
$res = $user->getLovedTracks($limit, $offset, $streamable, null, $cache);
} catch (Exception $ex) {
return XML::error('error', '7', 'Invalid resource specified');
}
// Get total track count, using subquery to get distinct row(artist, track) count
$query = 'SELECT COUNT(*) FROM (SELECT count(*) FROM Loved_Tracks lt';
if($streamable) {
$query .= ' WHERE ROW(lt.artist, lt.track) IN (SELECT artist_name, name FROM Track WHERE streamable=1)';
$andquery = True;
} else {
$query .= ' WHERE';
$andquery = False;
}
$andquery ? $query .= ' AND' : null;
$query .= ' userid=' . $user->uniqueid . ' GROUP BY lt.track, lt.artist) c';
$total = $adodb->CacheGetOne($cache, $query);
$totalPages = ceil($total/$limit);
$xml = new SimpleXMLElement('<lfm status="ok"></lfm>');
$root = $xml->addChild('lovedtracks');
$root->addAttribute('user', $user->name);
$root->addAttribute('page', $page);
$root->addAttribute('perPage', $limit);
$root->addAttribute('totalPages', $totalPages);
$root->addAttribute('total', $total);
foreach ($res as &$row) {
$track_node = $root->addChild('track', null);
UserXML::_addLBTrackDetails($track_node, $row);
}
return $xml;
}
public static function getBannedTracks($u, $limit = 50, $page = 1) {
global $adodb;
$offset = ($page - 1) * $limit;
try {
$user = new User($u);
$res = $user->getBannedTracks($limit, $offset);
} catch (Exception $ex) {
return XML::error('error', '7', 'Invalid resource specified');
}
$totalPages = $adodb->GetOne('SELECT COUNT(track) FROM Banned_Tracks WHERE userid = ' . $user->uniqueid);
$totalPages = ceil($totalPages / $limit);
$xml = new SimpleXMLElement('<lfm status="ok"></lfm>');
$root = $xml->addChild('bannedtracks');
$root->addAttribute('user', $user->name);
$root->addAttribute('page', $page);
$root->addAttribute('perPage', $limit);
$root->addAttribute('totalPages', $totalPages);
foreach ($res as &$row) {
$track_node = $root->addChild('track', null);
UserXML::_addLBTrackDetails($track_node, $row);
}
return $xml;
}
private static function _addLBTrackDetails($track_node, $row) {
$track = new Track($row['track'], $row['artist']);
$track_node->addChild('name', repamp($track->name));
$track_node->addChild('mbid', $track->mbid);
$track_node->addChild('url', $track->getURL());
$date = $track_node->addChild('date', gmdate('d M Y H:i', $row['time']) . ' GMT');
$date->addAttribute('uts', $row['time']);
try {
$artist = new Artist($row['artist']);
$artist_node = $track_node->addChild('artist', null);
$artist_node->addChild('name', repamp($artist->name));
$artist_node->addChild('mbid', $artist->mbid);
$artist_node->addChild('url', $artist->getURL());
} catch (Exception $e) {}
}
public static function getNeighbours($u, $limit = 50) {
try {
$user = new User($u);
$res = $user->getNeighbours($limit);
} catch (Exception $e) {
return XML::error('error', '7', 'Invalid resource specified');
}
$xml = new SimpleXMLElement('<lfm status="ok"></lfm>');
$root = $xml->addChild('neighbours');
$root->addAttribute('user', $user->name);
if (empty($res)) {
return $xml;
}
$highest_match = $res[0]['shared_artists'];
foreach ($res as $row) {
$neighbour = $row['user'];
$user_node = $root->addChild('user', null);
$user_node->addChild('name', repamp($neighbour->name));
$user_node->addChild('fullname', repamp($neighbour->fullname));
$user_node->addChild('url', repamp($neighbour->getURL()));
// Give a normalised value
$user_node->addChild('match', $row['shared_artists'] / $highest_match);
}
return $xml;
}
}