git.gnu.io has moved to IP address 209.51.188.249 -- please double check where you are logging in.

Commit 905a2373 authored by Jonas Haraldsson's avatar Jonas Haraldsson

Merge branch '2.0-scrobble' into clean-2.0-scrobble

Conflicts resolved:
	nixtape/api/TrackXML.php
parents aee14fc1 8cc59057
How to install phpdoc and generate api docs gnu-fm (on Debian Squeeze)
----------
---
1. Install dependencies and phpDocumentor-alpha:
---
# aptitude install php-pear php5-xsl
# pear channel-discover pear.phpdoc.org
# pear install phpdoc/phpDocumentor-alpha
for other ways to install, see http://www.phpdoc.org/docs/latest/for-users/installation.html
---
2. Create dir which will be holding the docs, and generate docs:
---
cd /path/to/gnu-fm/nixtape
mkdir docs
phpdoc -d 2.0/ -t docs/
The docs can now be found at http://mynixtapedomain.tld/docs/
Add something similar to this to your crontab to keep the docs up-to-date:
0 0 * * * phpdoc -q -d /path/to/gnu-fm/nixtape/2.0/ -t /path/to/gnu-fm/nixtape/docs
......@@ -2,12 +2,19 @@ Options +FollowSymLinks -MultiViews
RewriteEngine on
RewriteRule ^user/([^/]+)/?$ user-profile.php?user=$1 [NC,QSA]
RewriteRule ^user/([^/]+)/journal/?$ user-journal.php?user=$1 [NC,QSA]
RewriteRule ^user/([^/]+)/groups/?$ user-groups.php?user=$1 [NC,QSA]
RewriteRule ^user/([^/]+)/recent-tracks/?$ user-recent-tracks.php?user=$1 [NC,QSA]
RewriteRule ^user/([^/]+)/stats/?$ user-stats.php?user=$1 [NC,QSA]
RewriteRule ^user/([^/]+)/station/?$ user-station.php?user=$1 [NC,QSA]
RewriteRule ^user/([^/]+)/recommended/?$ user-recommended.php?user=$1 [NC,QSA]
RewriteRule ^user/([^/]+)/library/?$ user-library.php?user=$1 [NC,QSA]
RewriteRule ^user/([^/]+)/library/music/?$ user-library.php?user=$1&section=music [NC,QSA]
RewriteRule ^user/([^/]+)/library/scrobbles/?$ user-library.php?user=$1&section=scrobbles [NC,QSA]
RewriteRule ^user/([^/]+)/library/loved/?$ user-library.php?user=$1&section=loved [NC,QSA]
RewriteRule ^user/([^/]+)/library/banned/?$ user-library.php?user=$1&section=banned [NC,QSA]
RewriteRule ^user/([^/]+)/library/tags/?$ user-library.php?user=$1&section=tags [NC,QSA]
RewriteRule ^user/([^/]+)/library/tags/([^/]+)/?$ user-library.php?user=$1&section=tags&tag=$2 [NC,QSA]
RewriteRule ^user/([^/]+)/library/music/([^/]+)/?$ user-library.php?user=$1&section=music&artist=$2 [NC,QSA]
RewriteRule ^user/([^/]+)/library/music/([^/]+)/([^/]+)/?$ user-library.php?user=$1&section=music&artist=$2&album=$3 [NC,QSA]
RewriteRule ^user/([^/]+)/library/music/([^/]+)/_/([^/]+)/?$ user-library.php?user=$1&section=music&artist=$2&track=$3 [NC,QSA]
RewriteRule ^artist/([^/]+)/track/([^/]+)/edit/?$ track-add.php?artist=$1&track=$2 [NC,QSA]
RewriteRule ^artist/([^/]+)/track/([^/]+)/tag/?$ track-tag.php?artist=$1&track=$2 [NC,QSA]
RewriteRule ^artist/([^/]+)/track/([^/]+)/?$ track.php?artist=$1&track=$2 [NC,QSA]
......@@ -21,12 +28,8 @@ RewriteRule ^artist/([^/]+)/album/([^/]+)/?$ album.php?artist=$1&album=$2 [
RewriteRule ^artist/([^/]+)/?$ artist.php?artist=$1 [NC,QSA]
RewriteRule ^artist/([^/]+)/manage/?$ artist-manage.php?artist=$1 [NC,QSA]
RewriteRule ^artist/([^/]+)/tag/?$ artist-tag.php?artist=$1 [NC,QSA]
RewriteRule ^group/new$ edit_group.php?group=new [NC,QSA]
RewriteRule ^group/([^/]+)/?$ group.php?group=$1 [NC,QSA]
RewriteRule ^group/?$ group.php [NC,QSA]
RewriteRule ^country/([^/]+)/?$ location.php?country=$1 [NC,QSA]
RewriteRule ^logout login.php?action=logout [NC,QSA]
RewriteRule ^listen listen.php [NC,QSA]
RewriteRule ^music popular.php [NC,QSA]
RewriteRule ^users users.php [NC,QSA]
RewriteRule ^tag/([^/]+)/?$ tag.php?tag=$1 [NC,QSA]
......@@ -32,6 +32,7 @@ require_once('../api/JSONEncoder.php');
require_once('../api/TrackXML.php');
require_once('../api/AlbumXML.php');
require_once('../api/TagXML.php');
require_once('../api/LibraryXML.php');
require_once('../data/Server.php');
require_once('../radio/radio-utils.php');
......@@ -86,13 +87,15 @@ $method_map = array(
'artist.getinfo' => method_artist_getInfo,
'artist.gettoptracks' => method_artist_getTopTracks,
'artist.gettoptags' => method_artist_getTopTags,
'artist.gettopfans' => method_artist_getTopFans,
'artist.gettags' => method_artist_getTags,
'artist.getflattr' => method_artist_getFlattr,
'album.addtags' => method_album_addTags,
'album.gettoptags' => method_album_getTopTags,
'album.gettags' => method_album_getTags,
'library.removescrobble'=> method_library_removeScrobble,
'user.getinfo' => method_user_getInfo,
'user.gettopartists' => method_user_getTopArtists,
'user.gettopartists' => method_user_getTopArtists,
'user.gettoptracks' => method_user_getTopTracks,
'user.getrecenttracks' => method_user_getRecentTracks,
'user.gettoptags' => method_user_getTopTags,
......@@ -109,7 +112,9 @@ $method_map = array(
'tag.gettoptracks' => method_tag_getTopTracks,
'tag.getinfo' => method_tag_getInfo,
'track.addtags' => method_track_addTags,
'track.removetag' => method_track_removeTag,
'track.gettoptags' => method_track_getTopTags,
'track.gettopfans' => method_track_getTopFans,
'track.gettags' => method_track_getTags,
'track.ban' => method_track_ban,
'track.love' => method_track_love,
......@@ -478,7 +483,7 @@ function method_artist_getInfo() {
}
/**
* artist.gettoptracks : Get the top tracks for an aritst.
* artist.gettoptracks : Get the top tracks for an artist.
*
* ###Description
* Get the top tracks for an artist, ordered by play count.
......@@ -515,7 +520,7 @@ function method_artist_getTopTracks() {
* Get the top tags used for an artist, ordered by tag count.
*
* ###Parameters
* * **artist** (required) : Name of the album's artist.
* * **artist** (required) : Name of the artist.
* * **limit** (optional) : How many items to show. Defaults to 50.
* * **format** (optional) : Format of response, **xml** or **json**. Default is xml.
* - - -
......@@ -537,6 +542,35 @@ function method_artist_getTopTags() {
respond($xml);
}
/**
* artist.gettopfans : Get the top fans for an artist.
*
* ###Description
* Get the top fans used for an artist, ordered by play count.
*
* ###Parameters
* * **artist** (required) : Name of the artist.
* * **limit** (optional) : How many items to show. Defaults to 50.
* * **format** (optional) : Format of response, **xml** or **json**. Default is xml.
* - - -
*
* @package Webservice
* @subpackage Artist
* @api
*/
function method_artist_getTopFans() {
if (!isset($_REQUEST['artist'])) {
report_failure(LFM_INVALID_PARAMS);
}
$limit = get_with_default('limit', 50);
$cache = 600;
$xml = ArtistXML::getTopFans($_REQUEST['artist'], $limit, $cache);
respond($xml);
}
/**
* artist.gettags : Get a user's top tags for an artist.
*
......@@ -708,20 +742,14 @@ function method_album_getTags() {
* @api
*/
function method_auth_getToken() {
global $adodb;
$key = md5(time() . rand());
$token = Server::getAuthToken();
try {
$result = $adodb->Execute('INSERT INTO Auth (token, expires) VALUES ('
. $adodb->qstr($key) . ', '
. (int)(time() + 3600)
. ')');
} catch (Exception $e) {
if(!$token) {
report_failure(LFM_SERVICE_OFFLINE);
}
$xml = simplexml_load_string('<lfm status="ok"><token>' . $key . '</token></lfm>');
$xml = simplexml_load_string('<lfm status="ok"><token>' . $token . '</token></lfm>');
respond($xml);
}
/**
......@@ -862,6 +890,39 @@ function method_auth_getSession() {
}
}
/**
* library.removescrobble : Remove a scrobble
*
* ###Description
* Remove a scrobble from user's library
*
* #Parameters
* * **timestamp** (required) : Timestamp in Unix time.
* * **artist** (required) : Artist name.
* * **track** (required) : Track name.
* * **sk** (required) : Session key.
* * **format** (optional) : Format of response, **xml** or **json**. Default is xml.
*
* #Additional info
* **This method requires authentication**.
*
* **HTTP request method** : POST
* - - -
*
* @package Webservice
* @subpackage Library
* @api
*/
function method_library_removeScrobble() {
if (!isset($_POST['artist']) || !isset($_POST['track']) || !isset($_POST['timestamp'])) {
report_failure(LFM_INVALID_PARAMS);
}
$userid = get_userid();
$xml = LibraryXML::removeScrobble($userid, $_POST['timestamp'], $_POST['artist'], $_POST['track']);
respond($xml);
}
/**
* radio.tune : Tune in to a radio station
*
......@@ -1011,8 +1072,8 @@ function method_radio_getPlaylist() {
* Add tags to a track using a comma-separated list of tags.
*
* ###Parameters
* * **artist** (required) : Name of the tracks's artist.
* * **track** (required) : Name of the tracks.
* * **artist** (required) : Name of the track's artist.
* * **track** (required) : Name of the track.
* * **tags** (required) : Comma-separated list of tags.
* * **sk** (required) : Session key.
* * **album** (optional) : Name of the tracks's album.
......@@ -1038,6 +1099,40 @@ function method_track_addTags() {
respond($xml);
}
/**
* track.removetag : Remove tag from a track.
*
* ###Description
* Remove a tag from a track.
*
* ###Parameters
* * **artist** (required) : Name of the track's artist.
* * **track** (required) : Name of the track.
* * **tag** (required) : Name of tag.
* * **sk** (required) : Session key.
* * **format** (optional) : Format of response, **xml** or **json**. Default is xml.
*
* ###Additional info
* **This method requires authentication**.
*
* **HTTP request method** : POST.
* - - -
*
* @package Webservice
* @subpackage Track
* @api
*/
function method_track_removeTag() {
if (!isset($_POST['artist']) || !isset($_POST['track']) || !isset($_POST['tag'])) {
report_failure(LFM_INVALID_PARAMS);
}
$userid = get_userid();
$xml = TrackXML::removeTag($userid, $_POST['artist'], $_POST['track'], $_POST['tag']);
respond($xml);
}
/**
* track.gettoptags : Get the top tags for a track.
*
......@@ -1068,6 +1163,36 @@ function method_track_getTopTags() {
respond($xml);
}
/**
* track.gettopfans : Get the top fans for a track.
*
* ###Description
* Get the top fans for a track, ordered by play count.
*
* ###Parameters
* * **artist** (required) : Name of the artist.
* * **track** (required) : Name of the track.
* * **limit** (optional) : How many items to show. Defaults to 50.
* * **format** (optional) : Format of response, **xml** or **json**. Default is xml.
* - - -
*
* @package Webservice
* @subpackage Track
* @api
*/
function method_track_getTopFans() {
if (!isset($_REQUEST['artist']) OR !isset($_REQUEST['track'])) {
report_failure(LFM_INVALID_PARAMS);
}
$limit = get_with_default('limit', 50);
$cache = 600;
$xml = TrackXML::getTopFans($_REQUEST['track'], $_REQUEST['artist'], $limit, $cache);
respond($xml);
}
/**
* track.gettags : Get a user's top tags for a track.
*
......
......@@ -42,9 +42,17 @@ if (!isset($this_user) || !$this_user->manages($artist->name)) {
$edit = false;
if (isset($_GET['album'])) {
$edit = true;
$album = new Album($_GET['album'], $artist->name);
}
try {
$album = new Album($_GET['album'], $artist->name);
} catch (Exception $e) {
$smarty->assign('pageheading', 'Album not found.');
$smarty->assign('details', 'The album ' . $_GET['album'] . ' by artist ' . $artist->name . ' was not found in the database.');
$smarty->display('error.tpl');
die();
}
}
$smarty->assign('artist', $artist);
$smarty->assign('edit', $edit);
......
<?php
/* GNU FM -- a free network service for sharing your music listening habits
Copyright (C) 2013 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/>.
*/
function album_menu($album, $active_page) {
global $this_user;
$submenu = array(
array('name' => _('Overview'), 'url' => $album->getURL()),
);
foreach($submenu as &$item) {
$item['active'] = ($item['name'] == $active_page);
}
return $submenu;
}
try {
$album = new Album($_GET['album'], $_GET['artist']);
$smarty->assign('album', $album);
} catch (Exception $e) {
$smarty->assign('pageheading', 'Album not found.');
$smarty->assign('details', 'The album ' . $_GET['album'] . ' by artist ' . $_GET['artist'] . ' was not found in the database.');
$smarty->display('error.tpl');
die();
}
try {
$artist = new Artist($album->artist_name);
$smarty->assign('artist', $artist);
} catch (Exception $e) {
$smarty->assign('pageheading', 'Artist not found.');
$smarty->assign('details', 'The artist ' . $track->artist_name . ' was not found in the database.');
$smarty->display('error.tpl');
die();
}
if (isset($this_user) && $this_user->manages($artist->name)) {
$smarty->assign('edit_link', $album->getEditURL());
$smarty->assign('add_track_link', $album->getAddTrackURL());
}
$smarty->assign('pagetitle', $artist->name . ' : ' . $album->name);
......@@ -19,40 +19,18 @@
*/
require_once('database.php');
require_once('templating.php');
require_once('data/Album.php');
$album = new Album($_GET['album'], $_GET['artist']);
try {
$artist = new Artist($album->artist_name);
} catch (Exception $e) {
$smarty->assign('pageheading', 'Artist not found.');
$smarty->assign('details', 'The artist ' . $track->artist_name . ' was not found in the database.');
$smarty->display('error.tpl');
die();
}
if (isset($this_user) && $this_user->manages($artist->name)) {
$smarty->assign('edit_link', $album->getEditURL());
}
require_once('album-menu.php');
$smarty->assign('name', $album->name);
$smarty->assign('id', $album->id);
$smarty->assign('artist', $artist);
$smarty->assign('album', $album);
$smarty->assign('pagetitle', $artist->name . ' : ' . $album->name);
$aAlbumTracks = $album->getTracks();
if ($aAlbumTracks) {
$smarty->assign('tracks', $aAlbumTracks);
}
if (isset($this_user) && $this_user->manages($artist->name)) {
$smarty->assign('add_track_link', $album->getAddTrackURL());
}
$smarty->assign('extra_head_links', array(
array(
'rel' => 'meta',
......@@ -62,5 +40,4 @@ $smarty->assign('extra_head_links', array(
)
));
$smarty->assign('headerfile', 'album-header.tpl');
$smarty->display('album.tpl');
......@@ -135,6 +135,42 @@ class ArtistXML {
return $xml;
}
public static function getTopFans($artistname, $limit, $cache) {
global $adodb;
try {
$artist = new Artist($artistname);
$res = $artist->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', $artist->name);
$i = $offset + 1;
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) {}
$i++;
}
return $xml;
}
public static function getTopTags($artistName, $limit, $cache) {
try {
......
<?php
/* GNU FM -- a free network service for sharing your music listening habits
Copyright (C) 2013 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 . '/data/Library.php');
require_once('xml.php');
/**
* Class with functions that returns XML-formatted data involving a user's library.
*
* These functions are mainly used by web service methods.
*
* @package API
*/
class LibraryXML {
public static function removeScrobble($userid, $timestamp, $artist, $track) {
$result = Library::removeScrobble($userid, $timestamp, $artist, $track);
if (!$result) {
return XML::error('error', '7', 'Invalid resource specified');
}
$xml = new SimpleXMLElement('<lfm status="ok"></lfm>');
return $xml;
}
}
......@@ -35,12 +35,32 @@ class TrackXML {
public static function addTags($userid, $artist, $album, $trackName, $tags) {
try {
$track = new Track($trackName, $artist);
$track->addTags($tags, $userid);
$res = $track->addTags($tags, $userid);
} catch (Exception $e) {
return(XML::error('failed', '7', 'Invalid resource specified'));
}
$xml = new SimpleXMLElement('<lfm status="ok"></lfm>');
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;
}
......@@ -72,6 +92,41 @@ class TrackXML {
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 {
......@@ -101,59 +156,67 @@ class TrackXML {
}
public static function ban($artist, $name, $userid) {
global $adodb;
try {
$res = $adodb->Execute('INSERT INTO Banned_Tracks VALUES ('
. $userid . ', '
. $adodb->qstr($name) . ', '
. $adodb->qstr($artist) . ', '
. time() . ')');
} catch (Exception $e) {}
$xml = new SimpleXMLElement('<lfm status="ok"></lfm>');
$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) {
global $adodb;
try {
$res = $adodb->Execute('INSERT INTO Loved_Tracks VALUES ('
. $userid . ', '
. $adodb->qstr($name) . ', '
. $adodb->qstr($artist) . ', '
. time() . ')');
} catch (Exception $e) {}
$xml = new SimpleXMLElement('<lfm status="ok"></lfm>');
$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) {
global $adodb;
try {
$res = $adodb->Execute('DELETE FROM Banned_Tracks WHERE userid=' . $userid . ' AND track=' . $adodb->qstr($name) . ' AND artist=' . $adodb->qstr($artist));
} catch (Exception $e) {}
$xml = new SimpleXMLElement('<lfm status="ok"></lfm>');
$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) {
global $adodb;
try {
$res = $adodb->Execute('DELETE FROM Loved_Tracks WHERE userid=' . $userid . ' AND track=' . $adodb->qstr($name) . ' AND artist=' . $adodb->qstr($artist));
} catch (Exception $e) {}
$xml = new SimpleXMLElement('<lfm status="ok"></lfm>');
$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;
}
</