%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; } }