mirror of
https://github.com/Yetangitu/ampache
synced 2025-10-03 09:49:30 +02:00

Upgrade the scrobbler class, Lastfm and Librefm plugins to use the new API. Authentication is changed: -admin needs to create a last.fm API account, set their API key and secret in the ampache.cfg file, -users need to grant Ampache application to last.fm / Libre.fm services by using preference tab > plugins. Resolves ampache/ampache#922 Add the "spread the love" function to share your favorites on Last.fm and Libre.fm. Change-Id: Ia81334f4f4506258a27d40b6c257a1e38bd69097 Signed-off-by: nioc <nioc@users.noreply.github.com>
282 lines
9.1 KiB
PHP
282 lines
9.1 KiB
PHP
<?php
|
|
/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
|
|
/**
|
|
*
|
|
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
|
* Copyright 2001 - 2015 Ampache.org
|
|
*
|
|
* 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.
|
|
*
|
|
*/
|
|
|
|
class scrobbler
|
|
{
|
|
public $error_msg;
|
|
public $challenge;
|
|
public $host;
|
|
public $scheme;
|
|
public $api_key;
|
|
public $queued_tracks;
|
|
private $secret;
|
|
|
|
/**
|
|
* Constructor
|
|
* This is the constructer it takes a username and password
|
|
*/
|
|
public function __construct($api_key, $scheme='https',$host='',$challenge='', $secret='')
|
|
{
|
|
$this->error_msg = '';
|
|
$this->challenge = $challenge;
|
|
$this->host = $host;
|
|
$this->scheme = $scheme;
|
|
$this->api_key = $api_key;
|
|
$this->secret=$secret;
|
|
$this->queued_tracks = array();
|
|
} // scrobbler
|
|
|
|
/**
|
|
* get_api_sig
|
|
* Provide the API signature for calling Last.fm / Libre.fm services
|
|
* It is the md5 of the <name><value> of all parameter plus API's secret
|
|
*/
|
|
public function get_api_sig($vars=null)
|
|
{
|
|
ksort($vars);
|
|
$sig = '';
|
|
foreach ($vars as $name => $value) {
|
|
$sig .= $name.$value;
|
|
}
|
|
$sig .= $this->secret;
|
|
$sig = md5($sig);
|
|
return $sig;
|
|
} // get_api_sig
|
|
|
|
/**
|
|
* call_url
|
|
* This is a generic caller for HTTP requests
|
|
* It need the method (GET/POST), the url and the parameters
|
|
*/
|
|
public function call_url($url, $method='GET', $vars=null)
|
|
{
|
|
// Encode parameters per RFC1738
|
|
$params=http_build_query($vars);
|
|
$opts = array(
|
|
'http'=>array(
|
|
'method'=>$method,
|
|
'header'=> array(
|
|
'Host: '.$this->host,
|
|
'User-Agent: Ampache/'.AmpConfig::get('version')
|
|
),
|
|
)
|
|
);
|
|
// POST request need parameters in body and additional headers
|
|
if ($method == 'POST') {
|
|
$opts['http']['content'] = $params;
|
|
$opts['http']['header'][] = 'Content-type: application/x-www-form-urlencoded';
|
|
$opts['http']['header'][] = 'Content-length: '.strlen($params);
|
|
$params='';
|
|
}
|
|
$context = stream_context_create($opts);
|
|
if ($params!='') {
|
|
// If there are paramters for GET request, adding the "?" caracter before
|
|
$params='?'.$params;
|
|
}
|
|
//debug_event('SCROBBLER', "$this->scheme://$this->host$url$params", 5);
|
|
//debug_event('SCROBBLER', serialize($opts), 5);
|
|
$fp = fopen("$this->scheme://$this->host$url$params", 'r', false, $context);
|
|
if (!$fp) {
|
|
return false;
|
|
}
|
|
ob_start();
|
|
fpassthru($fp);
|
|
$buffer = ob_get_contents();
|
|
ob_end_clean();
|
|
fclose($fp);
|
|
//debug_event('SCROBBLER', $buffer, 5);
|
|
return $buffer;
|
|
} // call_url
|
|
|
|
/**
|
|
* get_error_msg
|
|
*/
|
|
public function get_error_msg()
|
|
{
|
|
return $this->error_msg;
|
|
} // get_error_msg
|
|
|
|
/**
|
|
* get_queue_count
|
|
*/
|
|
public function get_queue_count()
|
|
{
|
|
return count($this->queued_tracks);
|
|
} // get_queue_count
|
|
|
|
/**
|
|
* get_session_key
|
|
* This is a generic caller for HTTP requests
|
|
* It need the method (GET/POST), the url and the parameters
|
|
*/
|
|
public function get_session_key ($token=null)
|
|
{
|
|
if (!is_null($token)) {
|
|
$vars = array(
|
|
'method' => 'auth.getSession',
|
|
'api_key'=> $this->api_key,
|
|
'token' => $token
|
|
);
|
|
//sign the call
|
|
$sig = $this->get_api_sig($vars);
|
|
$vars['api_sig'] = $sig;
|
|
//call the getSession API
|
|
$response=$this->call_url('/2.0/', 'GET', $vars);
|
|
$xml = simplexml_load_string($response);
|
|
if ($xml) {
|
|
$status = (string) $xml['status'];
|
|
if ($status == 'ok') {
|
|
if ($xml->session && $xml->session->key) {
|
|
return $xml->session->key;
|
|
} else {
|
|
$this->error_msg = 'Did not receive a valid response';
|
|
return false;
|
|
}
|
|
} else {
|
|
$this->error_msg = $xml->error;
|
|
return false;
|
|
}
|
|
} else {
|
|
$this->error_msg = 'Did not receive a valid response';
|
|
return false;
|
|
}
|
|
}
|
|
$this->error_msg = 'Need a token to call getSession';
|
|
return false;
|
|
} // get_session_key
|
|
|
|
/**
|
|
* queue_track
|
|
* This queues the LastFM / Libre.fm track by storing it in this object, it doesn't actually
|
|
* submit the track or talk to LastFM / Libre in anyway, kind of useless for our uses but its
|
|
* here, and that's how it is.
|
|
*/
|
|
public function queue_track($artist, $album, $title, $timestamp, $length,$track)
|
|
{
|
|
if ($length < 30) {
|
|
debug_event('Scrobbler',"Not queuing track, too short",'5');
|
|
return false;
|
|
}
|
|
|
|
$newtrack = array();
|
|
$newtrack['artist'] = $artist;
|
|
$newtrack['album'] = $album;
|
|
$newtrack['title'] = $title;
|
|
$newtrack['track'] = $track;
|
|
$newtrack['length'] = $length;
|
|
$newtrack['time'] = $timestamp;
|
|
|
|
$this->queued_tracks[$timestamp] = $newtrack;
|
|
return true;
|
|
} // queue_track
|
|
|
|
/**
|
|
* submit_tracks
|
|
* This actually talks to LastFM / Libre.fm submiting the tracks that are queued up.
|
|
* It passed the API key, session key combinted with the signature
|
|
*/
|
|
public function submit_tracks()
|
|
{
|
|
// Check and make sure that we've got some queued tracks
|
|
if (!count($this->queued_tracks)) {
|
|
$this->error_msg = "No tracks to submit";
|
|
return false;
|
|
}
|
|
|
|
//sort array by timestamp
|
|
ksort($this->queued_tracks);
|
|
|
|
// Build the query string (encoded per RFC1738 by the call method)
|
|
$i = 0;
|
|
$vars= array();
|
|
foreach ($this->queued_tracks as $track) {
|
|
//construct array of parameters for each song
|
|
$vars["artist[$i]"] = $track['artist'];
|
|
$vars["track[$i]"] = $track['title'];
|
|
$vars["timestamp[$i]"] = $track['time'];
|
|
$vars["album[$i]"] = $track['album'];
|
|
$vars["trackNumber[$i]"] = $track['track'];
|
|
$vars["duration[$i]"] = $track['length'];
|
|
$i++;
|
|
}
|
|
// Add the method, API and session keys
|
|
$vars['method'] = 'track.scrobble';
|
|
$vars['api_key'] = $this->api_key;
|
|
$vars['sk'] = $this->challenge;
|
|
|
|
// Sign the call
|
|
$sig = $this->get_api_sig($vars);
|
|
$vars['api_sig'] = $sig;
|
|
|
|
// Call the method and parse response
|
|
$response=$this->call_url('/2.0/', 'POST', $vars);
|
|
$xml = simplexml_load_string($response);
|
|
if ($xml) {
|
|
$status = (string) $xml['status'];
|
|
if ($status == 'ok') {
|
|
return true;
|
|
} else {
|
|
$this->error_msg = $xml->error;
|
|
return false;
|
|
}
|
|
} else {
|
|
$this->error_msg = 'Did not receive a valid response';
|
|
return false;
|
|
}
|
|
} // submit_tracks
|
|
|
|
/**
|
|
* love
|
|
* This takes care of spreading your love to the world
|
|
* It passed the API key, session key combinted with the signature
|
|
*/
|
|
public function love($is_loved, $type, $artist = '', $title = '', $album = '')
|
|
{
|
|
$vars['track'] = $title;
|
|
$vars['artist'] = $artist;
|
|
// Add the method, API and session keys
|
|
$vars['method'] = $is_loved ? 'track.love' : 'track.unlove';
|
|
$vars['api_key'] = $this->api_key;
|
|
$vars['sk'] = $this->challenge;
|
|
|
|
// Sign the call
|
|
$sig = $this->get_api_sig($vars);
|
|
$vars['api_sig'] = $sig;
|
|
|
|
// Call the method and parse response
|
|
$response=$this->call_url('/2.0/', 'POST', $vars);
|
|
$xml = simplexml_load_string($response);
|
|
if ($xml) {
|
|
$status = (string) $xml['status'];
|
|
if ($status == 'ok') {
|
|
return true;
|
|
} else {
|
|
$this->error_msg = $xml->error;
|
|
return false;
|
|
}
|
|
} else {
|
|
$this->error_msg = 'Did not receive a valid response';
|
|
return false;
|
|
}
|
|
} // love
|
|
} // end audioscrobbler class
|
|
|