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