1<?php 2/* 3 * vim:set softtabstop=4 shiftwidth=4 expandtab: 4 * 5 * LICENSE: GNU Affero General Public License, version 3 (AGPL-3.0-or-later) 6 * Copyright 2001 - 2020 Ampache.org 7 * 8 * This program is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Affero General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Affero General Public License for more details. 17 * 18 * You should have received a copy of the GNU Affero General Public License 19 * along with this program. If not, see <https://www.gnu.org/licenses/>. 20 * 21 */ 22declare(strict_types=0); 23 24namespace Ampache\Plugin; 25 26use Ampache\Config\AmpConfig; 27use Ampache\Repository\Model\Plugin; 28use Ampache\Repository\Model\Preference; 29use Ampache\Repository\Model\Song; 30use Ampache\Repository\Model\User; 31use Ampache\Module\Playback\Scrobble\Scrobbler; 32use Ampache\Module\Statistics\Stats; 33 34class AmpacheLastfm 35{ 36 public $name = 'Last.FM'; 37 public $categories = 'scrobbling'; 38 public $description = 'Records your played songs to your Last.FM account'; 39 public $url; 40 public $version = '000005'; 41 public $min_ampache = '360003'; 42 public $max_ampache = '999999'; 43 44 // These are internal settings used by this class, run this->load to fill them out 45 private $challenge; 46 private $user_id; 47 private $api_key; 48 private $secret; 49 private $scheme = 'http'; 50 private $host = 'www.last.fm'; 51 private $api_host = 'ws.audioscrobbler.com'; 52 53 /** 54 * Constructor 55 * This function does nothing... 56 */ 57 public function __construct() 58 { 59 $this->description = T_('Scrobble songs you play to your Last.FM account'); 60 $this->url = $this->scheme . '://' . $this->host; 61 62 return true; 63 } // constructor 64 65 /** 66 * install 67 * This is a required plugin function. It inserts our preferences 68 * into Ampache 69 */ 70 public function install() 71 { 72 73 // Check and see if it's already installed (they've just hit refresh, those dorks) 74 if (Preference::exists('lastfm_user')) { 75 return false; 76 } 77 78 Preference::insert('lastfm_challenge', T_('Last.FM Submit Challenge'), '', 25, 'string', 'internal', 79 $this->name); 80 Preference::insert('lastfm_grant_link', T_('Last.FM Grant URL'), '', 25, 'string', 'plugins', $this->name); 81 82 return true; 83 } // install 84 85 /** 86 * uninstall 87 * This is a required plugin function. It removes our preferences from 88 * the database returning it to its original form 89 */ 90 public function uninstall() 91 { 92 Preference::delete('lastfm_challenge'); 93 Preference::delete('lastfm_grant_link'); 94 } // uninstall 95 96 /** 97 * upgrade 98 * This is a recommended plugin function 99 */ 100 public function upgrade() 101 { 102 $from_version = Plugin::get_plugin_version($this->name); 103 if ($from_version < 4) { 104 Preference::rename('lastfm_pass', 'lastfm_md5_pass'); 105 } 106 if ($from_version < 5) { 107 Preference::delete('lastfm_md5_pass'); 108 Preference::delete('lastfm_user'); 109 Preference::delete('lastfm_url'); 110 Preference::delete('lastfm_host'); 111 Preference::delete('lastfm_port'); 112 Preference::insert('lastfm_grant_link', T_('Last.FM Grant URL'), '', 25, 'string', 'plugins'); 113 } 114 115 return true; 116 } // upgrade 117 118 /** 119 * save_mediaplay 120 * This takes care of queueing and then submitting the tracks. 121 * @param Song $song 122 * @return boolean 123 */ 124 public function save_mediaplay($song) 125 { 126 // Only support songs 127 if (get_class($song) != Song::class) { 128 return false; 129 } 130 // Make sure there's actually a session before we keep going 131 if (!$this->challenge) { 132 debug_event('lastfm.plugin', 'Session key missing', 5); 133 134 return false; 135 } 136 137 if ($song->time < 30) { 138 debug_event('lastfm.plugin', 'Song less then 30 seconds not queueing', 3); 139 140 return false; 141 } 142 143 // Create our scrobbler and then queue it 144 $scrobbler = new Scrobbler($this->api_key, $this->scheme, $this->api_host, $this->challenge, $this->secret); 145 146 // Check to see if the scrobbling works by queueing song 147 if (!$scrobbler->queue_track($song->f_artist_full, $song->f_album_full, $song->title, time(), $song->time, 148 $song->track)) { 149 return false; 150 } 151 152 // Go ahead and submit it now 153 if (!$scrobbler->submit_tracks()) { 154 debug_event('lastfm.plugin', 'Error Submit Failed: ' . $scrobbler->error_msg, 3); 155 156 return false; 157 } 158 159 debug_event('lastfm.plugin', 'Submission Successful', 5); 160 161 return true; 162 } // submit 163 164 /** 165 * set_flag 166 * This takes care of spreading your love on Last.fm 167 * @param Song $song 168 * @param boolean $flagged 169 * @return boolean 170 */ 171 public function set_flag($song, $flagged) 172 { 173 // Make sure there's actually a session before we keep going 174 if (!$this->challenge) { 175 debug_event('lastfm.plugin', 'Session key missing', 5); 176 177 return false; 178 } 179 // Create our scrobbler and then queue it 180 $scrobbler = new Scrobbler($this->api_key, $this->scheme, $this->api_host, $this->challenge, $this->secret); 181 if (!$scrobbler->love($flagged, $song->f_artist_full, $song->title)) { 182 debug_event('lastfm.plugin', 'Error Love Failed: ' . $scrobbler->error_msg, 3); 183 184 return false; 185 } 186 debug_event('lastfm.plugin', 'Sent Love Successfully', 5); 187 188 return true; 189 } // set_flag 190 191 /** 192 * get_session 193 * This call the getSession method and properly updates the preferences as needed. 194 * This requires a userid so it knows whose crap to update. 195 * @param string $user_id 196 * @param string $token 197 * @return boolean 198 */ 199 public function get_session($user_id, $token) 200 { 201 $scrobbler = new Scrobbler($this->api_key, $this->scheme, $this->api_host, '', $this->secret); 202 $session_key = $scrobbler->get_session_key($token); 203 if (!$session_key) { 204 debug_event('lastfm.plugin', 'getSession Failed: ' . $scrobbler->error_msg, 3); 205 206 return false; 207 } 208 $this->challenge = $session_key; 209 210 // Update the preferences 211 Preference::update('lastfm_challenge', $user_id, $session_key); 212 debug_event('lastfm.plugin', 'getSession Successful', 3); 213 214 return true; 215 } // get_session 216 217 /** 218 * load 219 * This loads up the data we need into this object, this stuff comes 220 * from the preferences. 221 * @param User $user 222 * @return boolean 223 */ 224 public function load($user) 225 { 226 $this->api_key = AmpConfig::get('lastfm_api_key'); 227 $this->secret = AmpConfig::get('lastfm_api_secret'); 228 $user->set_preferences(); 229 $data = $user->prefs; 230 $this->user_id = $user->id; 231 // check if user have a session key 232 if (strlen(trim($data['lastfm_challenge']))) { 233 $this->challenge = trim($data['lastfm_challenge']); 234 } else { 235 debug_event('lastfm.plugin', 'No session key, not scrobbling (need to grant Ampache to last.fm)', 4); 236 237 return false; 238 } 239 240 return true; 241 } // load 242} 243