mirror of
https://github.com/Yetangitu/ampache
synced 2025-10-03 17:59:21 +02:00
Merge branch 'develop' of https://github.com/nioc/ampache into nioc-develop
This commit is contained in:
commit
24918b6cd0
7 changed files with 413 additions and 374 deletions
|
@ -501,6 +501,11 @@ art_order = "db,tags,folder,musicbrainz,lastfm,google"
|
|||
; recommendations and metadata.
|
||||
lastfm_api_key = "d5df942424c71b754e54ce1832505ae2"
|
||||
|
||||
; Last.FM API secret
|
||||
; Set this to your Last.FM api secret to actually use Last.FM for
|
||||
; scrobbling.
|
||||
lastfm_api_secret = ""
|
||||
|
||||
; Wanted
|
||||
; Set this to true to enable display missing albums and the
|
||||
; possibility for users to mark it as wanted.
|
||||
|
|
|
@ -23,35 +23,90 @@
|
|||
class scrobbler
|
||||
{
|
||||
public $error_msg;
|
||||
public $username;
|
||||
public $password;
|
||||
public $challenge;
|
||||
public $submit_host;
|
||||
public $submit_port;
|
||||
public $submit_url;
|
||||
public $host;
|
||||
public $scheme;
|
||||
public $api_key;
|
||||
public $queued_tracks;
|
||||
public $reset_handshake = false;
|
||||
public $scrobble_host = 'post.audioscrobbler.com';
|
||||
private $secret;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* This is the constructer it takes a username and password
|
||||
*/
|
||||
public function __construct($username, $password,$host='',$port='',$url='',$challenge='',$scrobble_host='')
|
||||
public function __construct($api_key, $scheme='https',$host='',$challenge='', $secret='')
|
||||
{
|
||||
$this->error_msg = '';
|
||||
$this->username = trim($username);
|
||||
$this->password = trim($password);
|
||||
$this->challenge = $challenge;
|
||||
$this->submit_host = $host;
|
||||
$this->submit_port = $port;
|
||||
$this->submit_url = $url;
|
||||
$this->host = $host;
|
||||
$this->scheme = $scheme;
|
||||
$this->api_key = $api_key;
|
||||
$this->secret=$secret;
|
||||
$this->queued_tracks = array();
|
||||
if ($scrobble_host) {
|
||||
$this->scrobble_host = $scrobble_host;
|
||||
}
|
||||
} // 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
|
||||
*/
|
||||
|
@ -69,83 +124,50 @@ class scrobbler
|
|||
} // get_queue_count
|
||||
|
||||
/**
|
||||
* handshake
|
||||
* This does a handshake with the audioscrobber server it doesn't pass the password, but
|
||||
* it does pass the username and has a 10 second timeout
|
||||
* get_session_key
|
||||
* This is a generic caller for HTTP requests
|
||||
* It need the method (GET/POST), the url and the parameters
|
||||
*/
|
||||
public function handshake()
|
||||
public function get_session_key ($token=null)
|
||||
{
|
||||
$data = array();
|
||||
$as_socket = fsockopen($this->scrobble_host, 80, $errno, $errstr, 2);
|
||||
if (!$as_socket) {
|
||||
$this->error_msg = $errstr;
|
||||
return false;
|
||||
}
|
||||
|
||||
$username = rawurlencode($this->username);
|
||||
$timestamp = time();
|
||||
$auth_token = rawurlencode(md5($this->password . $timestamp));
|
||||
|
||||
$get_string = "GET /?hs=true&p=1.2&c=apa&v=0.1&u=$username&t=$timestamp&a=$auth_token HTTP/1.1\r\n";
|
||||
|
||||
fwrite($as_socket, $get_string);
|
||||
fwrite($as_socket, "Host: $this->scrobble_host\r\n");
|
||||
fwrite($as_socket, "Accept: */*\r\n\r\n");
|
||||
|
||||
$buffer = '';
|
||||
while (!feof($as_socket)) {
|
||||
$buffer .= fread($as_socket, 4096);
|
||||
}
|
||||
fclose($as_socket);
|
||||
$split_response = preg_split("/\r\n\r\n/", $buffer);
|
||||
if (!isset($split_response[1])) {
|
||||
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;
|
||||
}
|
||||
$response = explode("\n", $split_response[1]);
|
||||
|
||||
// Handle the fact Libre.FM has extranious values at the start of it's handshake response
|
||||
if (is_numeric(trim($response['0']))) {
|
||||
array_shift($response);
|
||||
debug_event('SCROBBLER','Junk in handshake, removing first line',1);
|
||||
}
|
||||
if (substr($response[0], 0, 6) == 'FAILED') {
|
||||
$this->error_msg = substr($response[0], 7);
|
||||
return false;
|
||||
}
|
||||
if (substr($response[0], 0, 7) == 'BADUSER') {
|
||||
$this->error_msg = 'Invalid Username';
|
||||
return false;
|
||||
}
|
||||
if (substr($response[0],0,7) == 'BADTIME') {
|
||||
$this->error_msg = 'Your time is too far off from the server, or your PHP timezone is incorrect';
|
||||
return false;
|
||||
}
|
||||
if (substr($response[0], 0, 6) == 'UPDATE') {
|
||||
$this->error_msg = 'You need to update your client: '.substr($response[0], 7);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preg_match('/http:\/\/([^\/]+)\/(.*)$/', $response[3], $matches)) {
|
||||
$host_parts = explode(":",$matches[1]);
|
||||
$data['submit_host'] = $host_parts[0];
|
||||
$data['submit_port'] = $host_parts[1] ? $host_parts[1] : '80';
|
||||
$data['submit_url'] = '/' . $matches[2];
|
||||
} else {
|
||||
$this->error_msg = "Invalid POST URL returned, unable to continue. Sent:\n$get_string\n----\nReceived:\n" . $buffer .
|
||||
"\n---------\nExpected:" . print_r($response, true);
|
||||
$this->error_msg = $xml->error;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove any extra junk around the challenge
|
||||
$data['challenge'] = trim($response[1]);
|
||||
return $data;
|
||||
} // handshake
|
||||
} 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 track by storing it in this object, it doesn't actually
|
||||
* submit the track or talk to LastFM in anyway, kind of useless for our uses but its
|
||||
* 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)
|
||||
|
@ -169,8 +191,8 @@ class scrobbler
|
|||
|
||||
/**
|
||||
* submit_tracks
|
||||
* This actually talks to LastFM submiting the tracks that are queued up. It
|
||||
* passed the md5'd password combinted with the challenge, which is then md5'd
|
||||
* 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()
|
||||
{
|
||||
|
@ -183,84 +205,78 @@ class scrobbler
|
|||
//sort array by timestamp
|
||||
ksort($this->queued_tracks);
|
||||
|
||||
// build the query string
|
||||
$query_str = 's='.rawurlencode($this->challenge).'&';
|
||||
|
||||
// Build the query string (encoded per RFC1738 by the call method)
|
||||
$i = 0;
|
||||
|
||||
$vars= array();
|
||||
foreach ($this->queued_tracks as $track) {
|
||||
$query_str .= "a[$i]=".rawurlencode($track['artist'])."&t[$i]=".rawurlencode($track['title'])."&b[$i]=".rawurlencode($track['album'])."&";
|
||||
$query_str .= "m[$i]=&l[$i]=".rawurlencode($track['length'])."&i[$i]=".rawurlencode($track['time'])."&";
|
||||
$query_str .= "n[$i]=" . rawurlencode($track['track']) . "&o[$i]=P&r[$i]=&";
|
||||
//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;
|
||||
|
||||
if (!trim($this->submit_host) || !$this->submit_port) {
|
||||
$this->reset_handshake = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
$as_socket = fsockopen($this->submit_host, intval($this->submit_port), $errno, $errstr, 2);
|
||||
|
||||
if (!$as_socket) {
|
||||
$this->error_msg = $errstr;
|
||||
$this->reset_handshake = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
$action = "POST ".$this->submit_url." HTTP/1.0\r\n";
|
||||
fwrite($as_socket, $action);
|
||||
fwrite($as_socket, "Host: ".$this->submit_host."\r\n");
|
||||
fwrite($as_socket, "Accept: */*\r\n");
|
||||
fwrite($as_socket, "User-Agent: Ampache/3.6\r\n");
|
||||
fwrite($as_socket, "Content-type: application/x-www-form-urlencoded\r\n");
|
||||
fwrite($as_socket, "Content-length: ".strlen($query_str)."\r\n\r\n");
|
||||
|
||||
fwrite($as_socket, $query_str."\r\n\r\n");
|
||||
// Allow us to debug this
|
||||
debug_event('SCROBBLER','Query String:' . $query_str,6);
|
||||
|
||||
$buffer = '';
|
||||
while (!feof($as_socket)) {
|
||||
$buffer .= fread($as_socket, 8192);
|
||||
}
|
||||
fclose($as_socket);
|
||||
|
||||
$split_response = preg_split("/\r\n\r\n/", $buffer);
|
||||
if (!isset($split_response[1])) {
|
||||
$this->error_msg = 'Did not receive a valid response';
|
||||
$this->reset_handshake = true;
|
||||
return false;
|
||||
}
|
||||
$response = explode("\n", $split_response[1]);
|
||||
if (!isset($response[0])) {
|
||||
$this->error_msg = 'Unknown error submitting tracks'.
|
||||
"\nDebug output:\n".$buffer;
|
||||
$this->reset_handshake = true;
|
||||
return false;
|
||||
}
|
||||
if (substr($response[0], 0, 6) == 'FAILED') {
|
||||
$this->error_msg = $response[0];
|
||||
$this->reset_handshake = true;
|
||||
return false;
|
||||
}
|
||||
if (substr($response[0], 0, 7) == 'BADAUTH') {
|
||||
$this->error_msg = 'Invalid username/password (' . trim($response[0]) . ')';
|
||||
return false;
|
||||
}
|
||||
if (substr($response[0],0,10) == 'BADSESSION') {
|
||||
$this->error_msg = 'Invalid Session passed (' . trim($response[0]) . ')';
|
||||
$this->reset_handshake = true;
|
||||
return false;
|
||||
}
|
||||
if (substr($response[0], 0, 2) != 'OK') {
|
||||
$this->error_msg = 'Response Not ok, unknown error'.
|
||||
"\nDebug output:\n".$buffer;
|
||||
$this->reset_handshake = true;
|
||||
return false;
|
||||
}
|
||||
// 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
|
||||
|
||||
|
|
|
@ -161,6 +161,25 @@ class Userflag extends database_object
|
|||
|
||||
parent::add_to_cache('userflag_' . $this->type . '_user' . $user_id, $this->id, $flagged);
|
||||
|
||||
// Forward flag to last.fm and Libre.fm (song only)
|
||||
if ($this->type == 'song') {
|
||||
$user = new User($user_id);
|
||||
$song = new Song($this->id);
|
||||
if ($song) {
|
||||
$song->format();
|
||||
foreach (Plugin::get_plugins('save_mediaplay') as $plugin_name) {
|
||||
try {
|
||||
$plugin = new Plugin($plugin_name);
|
||||
if ($plugin->load($user)) {
|
||||
$plugin->_plugin->set_flag($song, $flagged);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
debug_event('user.class.php', 'Stats plugin error: ' . $e->getMessage(), '1');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} // set_flag
|
||||
|
||||
|
|
|
@ -380,6 +380,16 @@ function create_preference_input($name,$value)
|
|||
echo "\t<option value=\"name_desc\" $is_sort_name_desc>" . T_('Name descending') . "</option>\n";
|
||||
echo "</select>\n";
|
||||
break;
|
||||
case 'lastfm_grant_link':
|
||||
case 'librefm_grant_link':
|
||||
// construct links for granting access Ampache application to Last.fm and Libre.fm
|
||||
$plugin_name = ucfirst(str_replace('_grant_link', '', $name));
|
||||
$plugin = new Plugin($plugin_name);
|
||||
$url = $plugin->_plugin->url;
|
||||
$api_key = rawurlencode(AmpConfig::get('lastfm_api_key'));
|
||||
$callback = rawurlencode(AmpConfig::get('web_path').'/preferences.php?tab=plugins&action=grant&plugin='.$plugin_name);
|
||||
echo "<a href='$url/api/auth/?api_key=$api_key&cb=$callback'>" . UI::get_icon('plugin', T_("Click for grant Ampache to ").$plugin_name).'</a>';
|
||||
break;
|
||||
default:
|
||||
if (preg_match('/_pass$/', $name)) {
|
||||
echo '<input type="password" name="' . $name . '" value="******" />';
|
||||
|
|
|
@ -20,34 +20,34 @@
|
|||
*
|
||||
*/
|
||||
|
||||
class AmpacheLastfm {
|
||||
|
||||
class AmpacheLastfm
|
||||
{
|
||||
public $name = 'Last.FM';
|
||||
public $categories = 'scrobbling';
|
||||
public $description = 'Records your played songs to your Last.FM Account';
|
||||
public $url = 'http://www.lastfm.com';
|
||||
public $version = '000004';
|
||||
public $url;
|
||||
public $version = '000005';
|
||||
public $min_ampache = '360003';
|
||||
public $max_ampache = '999999';
|
||||
|
||||
// These are internal settings used by this class, run this->load to
|
||||
// fill them out
|
||||
private $username;
|
||||
private $password;
|
||||
private $hostname;
|
||||
private $port;
|
||||
private $path;
|
||||
private $challenge;
|
||||
private $user_id;
|
||||
private $api_key;
|
||||
private $secret;
|
||||
private $scheme = 'https';
|
||||
private $host = 'www.last.fm';
|
||||
private $api_host = 'ws.audioscrobbler.com';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* This function does nothing...
|
||||
*/
|
||||
public function __construct() {
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->url = $this->scheme.'://'.$this->host;
|
||||
return true;
|
||||
|
||||
} // constructor
|
||||
|
||||
/**
|
||||
|
@ -55,20 +55,18 @@ class AmpacheLastfm {
|
|||
* This is a required plugin function. It inserts our preferences
|
||||
* into Ampache
|
||||
*/
|
||||
public function install() {
|
||||
public function install()
|
||||
{
|
||||
|
||||
// Check and see if it's already installed (they've just hit refresh, those dorks)
|
||||
if (Preference::exists('lastfm_user')) { return false; }
|
||||
if (Preference::exists('lastfm_user')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Preference::insert('lastfm_user','Last.FM Username','','25','string','plugins');
|
||||
Preference::insert('lastfm_md5_pass','Last.FM Password','','25','string','plugins');
|
||||
Preference::insert('lastfm_port','Last.FM Submit Port','','25','string','internal');
|
||||
Preference::insert('lastfm_host','Last.FM Submit Host','','25','string','internal');
|
||||
Preference::insert('lastfm_url','Last.FM Submit URL','','25','string','internal');
|
||||
Preference::insert('lastfm_challenge','Last.FM Submit Challenge','','25','string','internal');
|
||||
Preference::insert('lastfm_grant_link','Last.FM Grant URL','','25','string','plugins');
|
||||
|
||||
return true;
|
||||
|
||||
} // install
|
||||
|
||||
/**
|
||||
|
@ -76,26 +74,30 @@ class AmpacheLastfm {
|
|||
* This is a required plugin function. It removes our preferences from
|
||||
* the database returning it to its original form
|
||||
*/
|
||||
public function uninstall() {
|
||||
|
||||
Preference::delete('lastfm_md5_pass');
|
||||
Preference::delete('lastfm_user');
|
||||
Preference::delete('lastfm_url');
|
||||
Preference::delete('lastfm_host');
|
||||
Preference::delete('lastfm_port');
|
||||
public function uninstall()
|
||||
{
|
||||
Preference::delete('lastfm_challenge');
|
||||
|
||||
Preference::delete('lastfm_grant_link');
|
||||
} // uninstall
|
||||
|
||||
/**
|
||||
* upgrade
|
||||
* This is a recommended plugin function
|
||||
*/
|
||||
public function upgrade() {
|
||||
public function upgrade()
|
||||
{
|
||||
$from_version = Plugin::get_plugin_version($this->name);
|
||||
if ($from_version < 4) {
|
||||
Preference::rename('lastfm_pass', 'lastfm_md5_pass');
|
||||
}
|
||||
if ($from_version < 5) {
|
||||
Preference::delete('lastfm_md5_pass');
|
||||
Preference::delete('lastfm_user');
|
||||
Preference::delete('lastfm_url');
|
||||
Preference::delete('lastfm_host');
|
||||
Preference::delete('lastfm_port');
|
||||
Preference::insert('lastfm_grant_link','Last.FM Grant URL','','25','string','plugins');
|
||||
}
|
||||
return true;
|
||||
} // upgrade
|
||||
|
||||
|
@ -103,9 +105,18 @@ class AmpacheLastfm {
|
|||
* save_songplay
|
||||
* This takes care of queueing and then submitting the tracks.
|
||||
*/
|
||||
public function save_mediaplay($song) {
|
||||
public function save_mediaplay($song)
|
||||
{
|
||||
// Only support songs
|
||||
if (strtolower(get_class($song)) != 'song') return false;
|
||||
if (strtolower(get_class($song)) != 'song') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure there's actually a session before we keep going
|
||||
if (!$this->challenge) {
|
||||
debug_event($this->name,'Session key missing','5');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Let's pull the last song submitted by this user
|
||||
$previous = Stats::get_last_song($this->user_id);
|
||||
|
@ -123,118 +134,89 @@ class AmpacheLastfm {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Make sure there's actually a username and password before we keep going
|
||||
if (!$this->username || !$this->password) {
|
||||
debug_event($this->name,'Username or password missing','3');
|
||||
return false;
|
||||
}
|
||||
// Create our scrobbler and then queue it
|
||||
$scrobbler = new scrobbler($this->api_key, $this->scheme, $this->api_host, $this->challenge, $this->secret);
|
||||
|
||||
// Create our scrobbler with everything this time and then queue it
|
||||
$scrobbler = new scrobbler($this->username,$this->password,$this->hostname,$this->port,$this->path,$this->challenge);
|
||||
|
||||
// Check to see if the scrobbling works
|
||||
// Check to see if the scrobbling works by queueing song
|
||||
if (!$scrobbler->queue_track($song->f_artist_full,$song->f_album_full,$song->title,time(),$song->time,$song->track)) {
|
||||
// Depending on the error we might need to do soemthing here
|
||||
return false;
|
||||
}
|
||||
|
||||
// Go ahead and submit it now
|
||||
if (!$scrobbler->submit_tracks()) {
|
||||
debug_event($this->name,'Error Submit Failed: ' . $scrobbler->error_msg,'3');
|
||||
if ($scrobbler->reset_handshake) {
|
||||
debug_event($this->name,'Re-running Handshake due to error','3');
|
||||
$this->set_handshake($this->user_id);
|
||||
// Try try again
|
||||
if ($scrobbler->submit_tracks()) {
|
||||
debug_event($this->name,'Submission Successful','5');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
debug_event($this->name,'Submission Successful','5');
|
||||
|
||||
return true;
|
||||
|
||||
} // submit
|
||||
|
||||
/**
|
||||
* set_handshake
|
||||
* This runs a handshake and properly updates the preferences as needed.
|
||||
* It returns the data as an array so we don't have to requery the db.
|
||||
* This requires a userid so it knows whose crap to update.
|
||||
* set_flag
|
||||
* This takes care of spreading your love on Last.fm
|
||||
*/
|
||||
public function set_handshake($user_id) {
|
||||
|
||||
$scrobbler = new scrobbler($this->username,$this->password);
|
||||
$data = $scrobbler->handshake();
|
||||
|
||||
if (!$data) {
|
||||
debug_event($this->name,'Handshake Failed: ' . $scrobbler->error_msg,'3');
|
||||
public function set_flag($song, $flagged)
|
||||
{
|
||||
// Make sure there's actually a session before we keep going
|
||||
if (!$this->challenge) {
|
||||
debug_event($this->name,'Session key missing','5');
|
||||
return false;
|
||||
}
|
||||
// Create our scrobbler and then queue it
|
||||
$scrobbler = new scrobbler($this->api_key, $this->scheme, $this->api_host, $this->challenge, $this->secret);
|
||||
if (!$scrobbler->love($flagged, 'song', $song->f_artist_full, $song->title, $song->f_album_full)) {
|
||||
debug_event($this->name,'Error Love Failed: ' . $scrobbler->error_msg,'3');
|
||||
return false;
|
||||
}
|
||||
debug_event($this->name,'Sent Love Successfully','5');
|
||||
return true;
|
||||
} // set_flag
|
||||
|
||||
$this->hostname = $data['submit_host'];
|
||||
$this->port = $data['submit_port'];
|
||||
$this->path = $data['submit_url'];
|
||||
$this->challenge = $data['challenge'];
|
||||
/**
|
||||
* get_session
|
||||
* This call the getSession method and properly updates the preferences as needed.
|
||||
* This requires a userid so it knows whose crap to update.
|
||||
*/
|
||||
public function get_session($user_id, $token)
|
||||
{
|
||||
$scrobbler = new scrobbler($this->api_key, $this->scheme, $this->api_host,'', $this->secret);
|
||||
$session_key = $scrobbler->get_session_key($token);
|
||||
if (!$session_key) {
|
||||
debug_event($this->name,'getSession Failed: ' . $scrobbler->error_msg,'3');
|
||||
return false;
|
||||
}
|
||||
$this->challenge = $session_key;
|
||||
|
||||
// Update the preferences
|
||||
Preference::update('lastfm_port',$user_id,$data['submit_port']);
|
||||
Preference::update('lastfm_host',$user_id,$data['submit_host']);
|
||||
Preference::update('lastfm_url',$user_id,$data['submit_url']);
|
||||
Preference::update('lastfm_challenge',$user_id,$data['challenge']);
|
||||
Preference::update('lastfm_challenge',$user_id,$session_key);
|
||||
debug_event($this->name,'getSession Successful','3');
|
||||
|
||||
return true;
|
||||
|
||||
} // set_handshake
|
||||
} // get_session
|
||||
|
||||
/**
|
||||
* load
|
||||
* This loads up the data we need into this object, this stuff comes
|
||||
* from the preferences.
|
||||
*/
|
||||
public function load($user) {
|
||||
|
||||
public function load($user)
|
||||
{
|
||||
$this->api_key=AmpConfig::get('lastfm_api_key');
|
||||
$this->secret=AmpConfig::get('lastfm_api_secret');
|
||||
$user->set_preferences();
|
||||
$data = $user->prefs;
|
||||
|
||||
if (strlen(trim($data['lastfm_user']))) {
|
||||
$this->username = trim($data['lastfm_user']);
|
||||
}
|
||||
else {
|
||||
debug_event($this->name,'No Username, not scrobbling','3');
|
||||
return false;
|
||||
}
|
||||
if (strlen(trim($data['lastfm_md5_pass']))) {
|
||||
$this->password = trim($data['lastfm_md5_pass']);
|
||||
}
|
||||
else {
|
||||
debug_event($this->name,'No Password, not scrobbling','3');
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->user_id = $user->id;
|
||||
|
||||
// If we don't have the other stuff try to get it before giving up
|
||||
if (!$data['lastfm_host'] || !$data['lastfm_port'] || !$data['lastfm_url'] || !$data['lastfm_challenge']) {
|
||||
debug_event($this->name, 'Running Handshake, missing information', '1');
|
||||
if (!$this->set_handshake($this->user_id)) {
|
||||
debug_event($this->name, 'Handshake failed, you lose', '3');
|
||||
// check if user have a session key
|
||||
if (strlen(trim($data['lastfm_challenge']))) {
|
||||
$this->challenge= trim($data['lastfm_challenge']);
|
||||
} else {
|
||||
debug_event($this->name,'No session key, not scrobbling (need to grant Ampache to last.fm)','5');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->hostname = $data['lastfm_host'];
|
||||
$this->port = $data['lastfm_port'];
|
||||
$this->path = $data['lastfm_url'];
|
||||
$this->challenge = $data['lastfm_challenge'];
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} // load
|
||||
|
||||
} // end AmpacheLastfm
|
||||
?>
|
||||
|
|
|
@ -20,34 +20,34 @@
|
|||
*
|
||||
*/
|
||||
|
||||
class Ampachelibrefm {
|
||||
|
||||
class Ampachelibrefm
|
||||
{
|
||||
public $name = 'Libre.FM';
|
||||
public $categories = 'scrobbling';
|
||||
public $description = 'Records your played songs to your Libre.FM Account';
|
||||
public $url = 'https://libre.fm';
|
||||
public $version = '000002';
|
||||
public $url;
|
||||
public $version = '000003';
|
||||
public $min_ampache = '360003';
|
||||
public $max_ampache = '999999';
|
||||
|
||||
// These are internal settings used by this class, run this->load to
|
||||
// fill them out
|
||||
private $username;
|
||||
private $password;
|
||||
private $hostname;
|
||||
private $port;
|
||||
private $path;
|
||||
private $challenge;
|
||||
private $user_id;
|
||||
private $api_key;
|
||||
private $secret;
|
||||
private $scheme = 'https';
|
||||
private $host = 'libre.fm';
|
||||
private $api_host = 'libre.fm';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* This function does nothing...
|
||||
*/
|
||||
public function __construct() {
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->url = $this->scheme.'://'.$this->host;
|
||||
return true;
|
||||
|
||||
} // constructor
|
||||
|
||||
/**
|
||||
|
@ -55,20 +55,18 @@ class Ampachelibrefm {
|
|||
* This is a required plugin function. It inserts our preferences
|
||||
* into Ampache
|
||||
*/
|
||||
public function install() {
|
||||
public function install()
|
||||
{
|
||||
|
||||
// Check and see if it's already installed (they've just hit refresh, those dorks)
|
||||
if (Preference::exists('librefm_user')) { return false; }
|
||||
if (Preference::exists('librefm_user')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Preference::insert('librefm_user','Libre.FM Username','','25','string','plugins');
|
||||
Preference::insert('librefm_md5_pass','Libre.FM Password','','25','string','plugins');
|
||||
Preference::insert('librefm_port','Libre.FM Submit Port','','25','string','internal');
|
||||
Preference::insert('librefm_host','Libre.FM Submit Host','','25','string','internal');
|
||||
Preference::insert('librefm_url','Libre.FM Submit URL','','25','string','internal');
|
||||
Preference::insert('librefm_challenge','Libre.FM Submit Challenge','','25','string','internal');
|
||||
Preference::insert('librefm_grant_link','Libre.FM Grant URL','','25','string','plugins');
|
||||
|
||||
return true;
|
||||
|
||||
} // install
|
||||
|
||||
/**
|
||||
|
@ -76,26 +74,30 @@ class Ampachelibrefm {
|
|||
* This is a required plugin function. It removes our preferences from
|
||||
* the database returning it to its original form
|
||||
*/
|
||||
public function uninstall() {
|
||||
|
||||
Preference::delete('librefm_md5_pass');
|
||||
Preference::delete('librefm_user');
|
||||
Preference::delete('librefm_url');
|
||||
Preference::delete('librefm_host');
|
||||
Preference::delete('librefm_port');
|
||||
public function uninstall()
|
||||
{
|
||||
Preference::delete('librefm_challenge');
|
||||
|
||||
Preference::delete('librefm_grant_link');
|
||||
} // uninstall
|
||||
|
||||
/**
|
||||
* upgrade
|
||||
* This is a recommended plugin function
|
||||
*/
|
||||
public function upgrade() {
|
||||
public function upgrade()
|
||||
{
|
||||
$from_version = Plugin::get_plugin_version($this->name);
|
||||
if ($from_version < 2) {
|
||||
Preference::rename('librefm_pass', 'librefm_md5_pass');
|
||||
}
|
||||
if ($from_version < 3) {
|
||||
Preference::delete('librefm_md5_pass');
|
||||
Preference::delete('librefm_user');
|
||||
Preference::delete('librefm_url');
|
||||
Preference::delete('librefm_host');
|
||||
Preference::delete('librefm_port');
|
||||
Preference::insert('librefm_grant_link','Libre.FM Grant URL','','25','string','plugins');
|
||||
}
|
||||
return true;
|
||||
} // upgrade
|
||||
|
||||
|
@ -103,10 +105,18 @@ class Ampachelibrefm {
|
|||
* save_songplay
|
||||
* This takes care of queueing and then submitting the tracks.
|
||||
*/
|
||||
public function save_mediaplay($song) {
|
||||
|
||||
public function save_mediaplay($song)
|
||||
{
|
||||
// Only support songs
|
||||
if (strtolower(get_class($song)) != 'song') return false;
|
||||
if (strtolower(get_class($song)) != 'song') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure there's actually a session before we keep going
|
||||
if (!$this->challenge) {
|
||||
debug_event($this->name,'Session key missing','5');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Before we start let's pull the last song submitted by this user
|
||||
$previous = Stats::get_last_song($this->user_id);
|
||||
|
@ -124,117 +134,89 @@ class Ampachelibrefm {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Make sure there's actually a username and password before we keep going
|
||||
if (!$this->username || !$this->password) {
|
||||
debug_event($this->name,'Username or password missing','3');
|
||||
return false;
|
||||
}
|
||||
// Create our scrobbler and then queue it
|
||||
$scrobbler = new scrobbler($this->api_key, $this->scheme, $this->api_host, $this->challenge, $this->secret);
|
||||
|
||||
// Create our scrobbler with everything this time and then queue it
|
||||
$scrobbler = new scrobbler($this->username,$this->password,$this->hostname,$this->port,$this->path,$this->challenge,'turtle.libre.fm');
|
||||
|
||||
// Check to see if the scrobbling works
|
||||
// Check to see if the scrobbling works by queueing song
|
||||
if (!$scrobbler->queue_track($song->f_artist_full,$song->f_album_full,$song->title,time(),$song->time,$song->track)) {
|
||||
// Depending on the error we might need to do soemthing here
|
||||
return false;
|
||||
}
|
||||
|
||||
// Go ahead and submit it now
|
||||
if (!$scrobbler->submit_tracks()) {
|
||||
debug_event($this->name,'Error Submit Failed: ' . $scrobbler->error_msg,'3');
|
||||
if ($scrobbler->reset_handshake) {
|
||||
debug_event($this->name, 'Re-running Handshake due to error', '1');
|
||||
$this->set_handshake($this->user_id);
|
||||
// Try try again
|
||||
if ($scrobbler->submit_tracks()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
debug_event($this->name,'Submission Successful','5');
|
||||
|
||||
return true;
|
||||
|
||||
} // submit
|
||||
|
||||
/**
|
||||
* set_handshake
|
||||
* This runs a handshake and properly updates the preferences as needed.
|
||||
* It returns the data as an array so we don't have to requery the db.
|
||||
* This requires a userid so it knows whose crap to update.
|
||||
* set_flag
|
||||
* This takes care of spreading your love on Libre.fm
|
||||
*/
|
||||
public function set_handshake($user_id) {
|
||||
|
||||
$scrobbler = new scrobbler($this->username,$this->password,'','','','','turtle.libre.fm');
|
||||
$data = $scrobbler->handshake();
|
||||
|
||||
if (!$data) {
|
||||
debug_event($this->name,'Handshake Failed: ' . $scrobbler->error_msg,'3');
|
||||
public function set_flag($song, $flagged)
|
||||
{
|
||||
// Make sure there's actually a session before we keep going
|
||||
if (!$this->challenge) {
|
||||
debug_event($this->name,'Session key missing','5');
|
||||
return false;
|
||||
}
|
||||
// Create our scrobbler and then queue it
|
||||
$scrobbler = new scrobbler($this->api_key, $this->scheme, $this->api_host, $this->challenge, $this->secret);
|
||||
if (!$scrobbler->love($flagged, 'song', $song->f_artist_full, $song->title, $song->f_album_full)) {
|
||||
debug_event($this->name,'Error Love Failed: ' . $scrobbler->error_msg,'3');
|
||||
return false;
|
||||
}
|
||||
debug_event($this->name,'Sent Love Successfully','5');
|
||||
return true;
|
||||
} // set_flag
|
||||
|
||||
$this->hostname = $data['submit_host'];
|
||||
$this->port = $data['submit_port'];
|
||||
$this->path = $data['submit_url'];
|
||||
$this->challenge = $data['challenge'];
|
||||
/**
|
||||
* get_session
|
||||
* This call the getSession method and properly updates the preferences as needed.
|
||||
* This requires a userid so it knows whose crap to update.
|
||||
*/
|
||||
public function get_session($user_id, $token)
|
||||
{
|
||||
$scrobbler = new scrobbler($this->api_key, $this->scheme, $this->api_host,'', $this->secret);
|
||||
$session_key = $scrobbler->get_session_key($token);
|
||||
if (!$session_key) {
|
||||
debug_event($this->name,'getSession Failed: ' . $scrobbler->error_msg,'3');
|
||||
return false;
|
||||
}
|
||||
$this->challenge = $session_key;
|
||||
|
||||
// Update the preferences
|
||||
Preference::update('librefm_port',$user_id,$data['submit_port']);
|
||||
Preference::update('librefm_host',$user_id,$data['submit_host']);
|
||||
Preference::update('librefm_url',$user_id,$data['submit_url']);
|
||||
Preference::update('librefm_challenge',$user_id,$data['challenge']);
|
||||
Preference::update('librefm_challenge',$user_id,$session_key);
|
||||
debug_event($this->name,'getSession Successful','3');
|
||||
|
||||
return true;
|
||||
|
||||
} // set_handshake
|
||||
} // get_session
|
||||
|
||||
/**
|
||||
* load
|
||||
* This loads up the data we need into this object, this stuff comes
|
||||
* from the preferences.
|
||||
*/
|
||||
public function load($user) {
|
||||
|
||||
public function load($user)
|
||||
{
|
||||
$this->api_key=AmpConfig::get('lastfm_api_key');
|
||||
$this->secret='';
|
||||
$user->set_preferences();
|
||||
$data = $user->prefs;
|
||||
|
||||
if (strlen(trim($data['librefm_user']))) {
|
||||
$this->username = trim($data['librefm_user']);
|
||||
}
|
||||
else {
|
||||
debug_event($this->name,'No Username, not scrobbling','3');
|
||||
return false;
|
||||
}
|
||||
if (strlen(trim($data['librefm_md5_pass']))) {
|
||||
$this->password = trim($data['librefm_md5_pass']);
|
||||
}
|
||||
else {
|
||||
debug_event($this->name,'No Password, not scrobbling','3');
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->user_id = $user->id;
|
||||
|
||||
// If we don't have the other stuff try to get it before giving up
|
||||
if (!$data['librefm_host'] || !$data['librefm_port'] || !$data['librefm_url'] || !$data['librefm_challenge']) {
|
||||
debug_event($this->name,'Running Handshake, missing information','3');
|
||||
if (!$this->set_handshake($this->user_id)) {
|
||||
debug_event($this->name,'Handshake failed, you lose','3');
|
||||
// check if user have a session key
|
||||
if (strlen(trim($data['librefm_challenge']))) {
|
||||
$this->challenge= trim($data['librefm_challenge']);
|
||||
} else {
|
||||
debug_event($this->name,'No session key, not scrobbling (need to grant Ampache to libre.fm)','5');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->hostname = $data['librefm_host'];
|
||||
$this->port = $data['librefm_port'];
|
||||
$this->path = $data['librefm_url'];
|
||||
$this->challenge = $data['librefm_challenge'];
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} // load
|
||||
|
||||
} // end Ampachelibrefm
|
||||
?>
|
||||
|
|
|
@ -148,6 +148,30 @@ switch ($_REQUEST['action']) {
|
|||
|
||||
$notification_text = T_('User updated successfully');
|
||||
break;
|
||||
case 'grant':
|
||||
// Make sure we're a user and they came from the form
|
||||
if (!Access::check('interface','25') && $GLOBALS['user']->id > 0) {
|
||||
UI::access_denied();
|
||||
exit;
|
||||
}
|
||||
if ($_REQUEST['token'] && in_array($_REQUEST['plugin'], Plugin::get_plugins('save_mediaplay'))) {
|
||||
// we receive a token for a valid plugin, have to call getSession and obtain a session key
|
||||
if ($plugin = new Plugin($_REQUEST['plugin'])) {
|
||||
$plugin->load($GLOBALS['user']);
|
||||
if ($plugin->_plugin->get_session($GLOBALS['user']->id, $_REQUEST['token'])) {
|
||||
$title = T_('Updated');
|
||||
$text = T_('Your Account has been updated').' : '.$_REQUEST['plugin'];
|
||||
$next_url = AmpConfig::get('web_path') . '/preferences.php?tab=plugins';
|
||||
} else {
|
||||
$title = T_('Error');
|
||||
$text = T_('Your Account has not been updated').' : '.$_REQUEST['plugin'];
|
||||
$next_url = AmpConfig::get('web_path') . '/preferences.php?tab=plugins';
|
||||
}
|
||||
}
|
||||
}
|
||||
$fullname = $GLOBALS['user']->fullname;
|
||||
$preferences = $GLOBALS['user']->get_preferences($_REQUEST['tab']);
|
||||
break;
|
||||
default:
|
||||
$fullname = $GLOBALS['user']->fullname;
|
||||
$preferences = $GLOBALS['user']->get_preferences($_REQUEST['tab']);
|
||||
|
@ -161,6 +185,7 @@ UI::show_header();
|
|||
*/
|
||||
switch ($_REQUEST['action']) {
|
||||
case 'confirm':
|
||||
case 'grant':
|
||||
show_confirmation($title,$text,$next_url,$cancel);
|
||||
break;
|
||||
default:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue