%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/TrackXML.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/Track.php'); require_once($install_path . '/scrobble-utils.php'); require_once('xml.php'); /** * Class with functions that returns XML-formatted data for tracks. * * These functions are mainly used by web service methods. * * @package API */ class TrackXML { public static function addTags($userid, $artist, $album, $trackName, $tags) { try { $track = new Track($trackName, $artist); $res = $track->addTags($tags, $userid); } catch (Exception $e) { return(XML::error('failed', '7', 'Invalid resource specified')); } if(!$res) { $xml = XML::error('failed', '7', 'Invalid resource specified'); } else { $xml = new SimpleXMLElement('<lfm status="ok"></lfm>'); } return $xml; } public static function removeTag($userid, $artist, $trackName, $tag) { try { $track = new Track($trackName, $artist); $res = $track->removeTag($tag, $userid); } catch (Exception $e) { return(XML::error('failed', '7', 'Invalid resource specified')); } if(!$res) { $xml = XML::error('failed', '7', 'Invalid resource specified'); } else { $xml = new SimpleXMLElement('<lfm status="ok"></lfm>'); } return $xml; } public static function getInfo($artist, $name, $username) { global $adodb; try { $track = new Track($name, $artist); } catch (Exception $e) { return(XML::error('failed', '7', 'Invalid resource specified')); } $xml = new SimpleXMLElement('<lfm status="ok"></lfm>'); $root = $xml->addChild('track', null); $root->addChild('name', $track->name); $root->addChild('mbid', $track->mbid); $root->addChild('url', $track->getURL()); $root->addChild('duration', $track->duration * 1000); $streamable = $root->addChild('streamable', $track->streamable); $streamable->addAttribute('fulltrack', $track->streamable); $root->addChild('listeners', $track->getListenerCount()); $root->addChild('playcount', $track->getPlayCount()); if($username) { $userid = $adodb->GetOne('SELECT uniqueid FROM Users WHERE ' . 'username = ' . $adodb->qstr($username)); $root->addChild('userloved', $track->isLoved($userid) ? 1 : 0); } return $xml; } public static function getTopTags($artist, $name, $limit, $cache) { try { $track = new Track($name, $artist); $res = $track->getTopTags($limit, 0, $cache); } catch (Exception $e) { return(XML::error('failed', '7', 'Invalid resource specified')); } if(!$res) { return(XML::error('failed', '6', 'No tags for this track')); } $xml = new SimpleXMLElement('<lfm status="ok"></lfm>'); $root = $xml->addChild('toptags', null); $root->addAttribute('artist', $artist); $root->addAttribute('track', $name); foreach ($res as &$row) { $tag_node = $root->addChild('tag', null); $tag_node->addChild('name', repamp($row['tag'])); $tag_node->addChild('count', $row['freq']); $tag_node->addChild('url', Server::getTagURL($row['tag'])); } return $xml; } public static function getTopFans($name, $artistname, $limit, $cache) { global $adodb; try { $track = new Track($name, $artistname); $res = $track->getTopListeners($limit, 0, False, null, null, $cache); } catch (Exception $e) { return XML::error('error', '7', 'Invalid resource specified'); } $xml = new SimpleXMLElement('<lfm status="ok"></lfm>'); $root = $xml->addChild('topfans', null); $root->addAttribute('artist', $track->artist_name); $root->addAttribute('track', $track->name); foreach($res as &$row) { try { $user = new User($row['username']); $user_node = $root->addChild('user', null); $user_node->addChild('name', $user->name); $user_node->addChild('realname', $user->fullname); $user_node->addChild('url', repamp($user->getURL())); $image_small = $user_node->addChild('image', null); $image_small->addAttribute('size', 'small'); $image_medium = $user_node->addChild('image', null); $image_medium->addAttribute('size', 'medium'); $image_large = $user_node->addChild('image', null); $image_large->addAttribute('size', 'large'); $user_node->addChild('weight', $row['freq']); } catch (Exception $e) {} } return $xml; } public static function getTags($artist, $name, $userid, $limit, $cache) { try { $track = new Track($name, $artist); $res = $track->getTags($userid, $limit, 0, $cache); } catch (Exception $e) { return(XML::error('failed', '7', 'Invalid resource specified')); } if(!$res) { return(XML::error('failed', '6', 'No tags for this track')); } $xml = new SimpleXMLElement('<lfm status="ok"></lfm>'); $root = $xml->addChild('tags', null); $root->addAttribute('artist', $artist); $root->addAttribute('track', $name); foreach ($res as &$row) { $tag_node = $root->addChild('tag', null); $tag_node->addChild('name', repamp($row['tag'])); $tag_node->addChild('url', Server::getTagURL($row['tag'])); } return $xml; } public static function ban($artist, $name, $userid) { try { $track = new Track($name, $artist); $res = $track->ban($userid); } catch (Exception $e) { return XML::error('failed', '7', 'Invalid resource specified'); } if(!$res) { $xml = XML::error('failed', '7', 'Invalid resource specified'); } else { $xml = new SimpleXMLElement('<lfm status="ok"></lfm>'); } return $xml; } public static function love($artist, $name, $userid) { try { $track = new Track($name, $artist); $res = $track->love($userid); } catch (Exception $e) { return XML::error('failed', '7', 'Invalid resource specified'); } if(!$res) { $xml = XML::error('failed', '7', 'Invalid resource specified'); } else { $xml = new SimpleXMLElement('<lfm status="ok"></lfm>'); } return $xml; } public static function unban($artist, $name, $userid) { try { $track = new Track($name, $artist); $res = $track->unban($userid); } catch (Exception $e) { return XML::error('failed', '7', 'Invalid resource specified'); } if(!$res) { $xml = XML::error('failed', '7', 'Invalid resource specified'); } else { $xml = new SimpleXMLElement('<lfm status="ok"></lfm>'); } return $xml; } public static function unlove($artist, $name, $userid) { try { $track = new Track($name, $artist); $res = $track->unlove($userid); } catch (Exception $e) { return XML::error('failed', '7', 'Invalid resource specified'); } if(!$res) { $xml = XML::error('failed', '7', 'Invalid resource specified'); } else { $xml = new SimpleXMLElement('<lfm status="ok"></lfm>'); } return $xml; } public static function updateNowPlaying($userid, $artist, $track, $album, $tracknumber, $context, $mbid, $duration, $albumartist, $api_key) { global $adodb; $sessionid = Server::getScrobbleSession($userid, $api_key); $t = array( 'artist' => $artist, 'track' => $track, 'album' => $album, 'tracknumber' => $tracknumber, 'mbid' => $mbid, 'duration' => $duration, 'albumartist' => $albumartist ); $t = prepareTrack($userid, $t, 'nowplaying'); // Delete last played track $query = 'DELETE FROM Now_Playing WHERE sessionid = ?'; $params = array($sessionid); try { $adodb->Execute($query, $params); } catch (Exception $e) {} // Calculate expiry time if (!$t['duration'] || ($t['duration'] > 5400)) { // Default expiry time of 300 seconds if duration is false or above 5400 seconds $expires = time() + 300; } else { $expires = time() + $t['duration']; } if ($t['ignored_code'] === 0) { // Clean up expired tracks in now_playing table $params = array(time()); $query = 'DELETE FROM Now_Playing WHERE expires < ?'; $adodb->Execute($query, $params); $adodb->StartTrans(); try { // getTrackID will create the track in Track table if it doesnt exist getTrackID($t['artist'], $t['album'], $t['track'], $t['mbid'], $t['duration']); $params = array($sessionid, $t['track'], $t['artist'], $t['album'], $t['mbid'], $expires); $query = 'INSERT INTO Now_Playing(sessionid, track, artist, album, mbid, expires) VALUES (?,?,?,?,?,?)'; $adodb->Execute($query, $params); } catch (Exception $e) { $adodb->FailTrans(); $adodb->CompleteTrans(); reportError($e->getMessage(), $e->getTraceAsString()); return XML::error('failed', '16', 'The service is temporarily unavailable, please try again.'); } $adodb->CompleteTrans(); } $xml = new SimpleXMLElement('<lfm status="ok"></lfm>'); $root = $xml->addChild('nowplaying', null); $track_node = $root->addChild('track', repamp($t['track'])); $track_node->addAttribute('corrected', $t['track_corrected']); $artist_node = $root->addChild('artist', repamp($t['artist'])); $artist_node->addAttribute('corrected', $t['artist_corrected']); $album_node = $root->addChild('album', repamp($t['album'])); $album_node->addAttribute('corrected', $t['album_corrected']); $albumartist_node = $root->addChild('albumArtist', repamp($t['albumartist'])); $albumartist_node->addAttribute('corrected', $t['albumartist_corrected']); $ignoredmessage_node = $root->addChild('ignoredMessage', $t['ignored_message']); $ignoredmessage_node->addAttribute('code', $t['ignored_code']); return $xml; } public static function scrobble($userid, $artist, $track, $timestamp, $album, $context, $streamid, $chosenbyuser, $tracknumber, $mbid, $albumartist, $duration, $api_key) { global $adodb; $sessionid = Server::getScrobbleSession($userid, $api_key); $accepted_count = 0; $ignored_count = 0; $tracks_array = array(); // Convert input to track arrays and add them to tracks_array if (is_array($artist)) { for ($i = 0; $i < count($artist); $i++) { $tracks_array[$i] = array( 'artist' => $artist[$i], 'track' => $track[$i], 'timestamp' => $timestamp[$i], 'album' => $album[$i], 'tracknumber' => $tracknumber[$i], 'mbid' => $mbid[$i], 'albumartist' => $albumartist[$i], 'duration' => $duration[$i], ); } } else { $tracks_array[0] = array( 'artist' => $artist, 'track' => $track, 'timestamp' => $timestamp, 'album' => $album, 'tracknumber' => $tracknumber, 'mbid' => $mbid, 'albumartist' => $albumartist, 'duration' => $duration, ); } // Correct and inspect scrobbles to see if some should be ignored for ($i = 0; $i < count($tracks_array); $i++) { $tracks_array[$i] = prepareTrack($userid, $tracks_array[$i], 'scrobble'); } $adodb->StartTrans(); for ($i = 0; $i < count($tracks_array); $i++) { $t = $tracks_array[$i]; if ($t['ignored_code'] === 0) { try { // Create artist, album and track if not already in db $t['track_id'] = getTrackID($t['artist'], $t['album'], $t['track'], $t['mbid'], $t['duration']); $t['scrobbletrack_id'] = getScrobbleTrackID($t['artist'], $t['album'], $t['track'], $t['mbid'], $t['duration'], $t['track_id']); } catch (Exception $e) { // Roll back database entries, log error and respond with error message $adodb->FailTrans(); $adodb->CompleteTrans(); reportError($e->getMessage(), $e->getTraceAsString()); return XML::error('failed', '16', 'The service is temporarily unavailable, please try again.'); } try { // Scrobble // TODO last.fm spec says we shouldnt scrobble corrected values, // so maybe we should only use corrected values for validation and in xml $query = 'INSERT INTO Scrobbles (userid, artist, album, track, time, mbid, source, rating, length, stid) VALUES (?,?,?,?,?,?,?,?,?,?)'; $params = array( $userid, $t['artist'], $t['album'], $t['track'], $t['timestamp'], $t['mbid'], null, null, $t['duration'], $t['scrobbletrack_id'] ); $adodb->Execute($query, $params); } catch (Exception $e) { // Roll back database entries, log error and respond with error message $adodb->FailTrans(); $adodb->CompleteTrans(); reportError($e->getMessage(), $e->getTraceAsString()); return XML::error('failed', '16', 'The service is temporarily unavailable, please try again.'); } } $tracks_array[$i] = $t; } $adodb->CompleteTrans(); // Check if forwarding is enabled before looping through array $params = array($userid); $query = 'SELECT userid FROM Service_Connections WHERE userid = ? AND forward = 1'; $forward_enabled = $adodb->CacheGetOne(600, $query, $params); if ($forward_enabled) { for ($i = 0; $i < count($tracks_array); $i++) { $t = $tracks_array[$i]; if ($t['ignored_code'] === 0) { /* Forward scrobbles, we are forwarding unmodified input submitted by user, * but only the scrobbles that passed our ignore filters, see prepareTrack(). */ forwardScrobble($userid, $t['artist_old'], $t['album_old'], $t['track_old'], $t['timestamp_old'], $t['mbid_old'], '', '', $t['duration_old']); } } } // Build xml $xml = new SimpleXMLElement('<lfm status="ok"></lfm>'); $root = $xml->addChild('scrobbles', null); for ($i = 0; $i < count($tracks_array); $i++) { $t = $tracks_array[$i]; $scrobble = $root->addChild('scrobble', null); $track_node = $scrobble->addChild('track', repamp($t['track'])); $track_node->addAttribute('corrected', $t['track_corrected']); $artist_node = $scrobble->addChild('artist', repamp($t['artist'])); $artist_node->addAttribute('corrected', $t['artist_corrected']); $album_node = $scrobble->addChild('album', repamp($t['album'])); $album_node->addAttribute('corrected', $t['album_corrected']); $albumartist_node = $scrobble->addChild('albumArtist', repamp($t['albumartist'])); $albumartist_node->addAttribute('corrected', $t['albumartist_corrected']); $scrobble->addChild('timestamp', $t['timestamp']); $ignoredmessage_node = $scrobble->addChild('ignoredMessage', $t['ignored_message']); $ignoredmessage_node->addAttribute('code', $t['ignored_code']); if ($t['ignored_code'] === 0) { $accepted_count += 1; } else { $ignored_count += 1; } } $root->addAttribute('accepted', $accepted_count); $root->addAttribute('ignored', $ignored_count); return $xml; } }