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\Repository\Model\Art;
27use Ampache\Repository\Model\Preference;
28use Ampache\Repository\Model\User;
29use Exception;
30use Requests;
31
32class AmpacheDiscogs
33{
34    public $name        = 'Discogs';
35    public $categories  = 'metadata';
36    public $description = 'Discogs metadata integration';
37    public $url         = 'http://www.discogs.com';
38    public $version     = '000001';
39    public $min_ampache = '370021';
40    public $max_ampache = '999999';
41
42    private $api_key;
43    private $secret;
44
45    /**
46     * Constructor
47     * This function does nothing
48     */
49    public function __construct()
50    {
51        $this->description = T_('Discogs metadata integration');
52
53        return true;
54    }
55
56    /**
57     * install
58     * This is a required plugin function
59     */
60    public function install()
61    {
62        if (Preference::exists('discogs_api_key')) {
63            return false;
64        }
65        Preference::insert('discogs_api_key', T_('Discogs consumer key'), '', 75, 'string', 'plugins', $this->name);
66        Preference::insert('discogs_secret_api_key', T_('Discogs secret'), '', 75, 'string', 'plugins', $this->name);
67
68        return true;
69    } // install
70
71    /**
72     * uninstall
73     * This is a required plugin function
74     */
75    public function uninstall()
76    {
77        Preference::delete('discogs_api_key');
78        Preference::delete('discogs_secret_api_key');
79
80        return true;
81    } // uninstall
82
83    /**
84     * load
85     * This is a required plugin function; here it populates the prefs we
86     * need for this object.
87     * @param User $user
88     * @return boolean
89     */
90    public function load($user)
91    {
92        $user->set_preferences();
93        $data = $user->prefs;
94        // load system when nothing is given
95        if (!strlen(trim($data['discogs_api_key'])) || !strlen(trim($data['discogs_secret_api_key']))) {
96            $data                           = array();
97            $data['discogs_api_key']        = Preference::get_by_user(-1, 'discogs_api_key');
98            $data['discogs_secret_api_key'] = Preference::get_by_user(-1, 'discogs_secret_api_key');
99        }
100
101        if (strlen(trim($data['discogs_api_key']))) {
102            $this->api_key = trim($data['discogs_api_key']);
103        } else {
104            debug_event(self::class, 'No Discogs api key, metadata plugin skipped', 3);
105
106            return false;
107        }
108        if (strlen(trim($data['discogs_secret_api_key']))) {
109            $this->secret = trim($data['discogs_secret_api_key']);
110        } else {
111            debug_event(self::class, 'No Discogs secret, metadata plugin skipped', 3);
112
113            return false;
114        }
115
116        return true;
117    } // load
118
119    /**
120     * @param $query
121     * @return mixed
122     */
123    protected function query_discogs($query)
124    {
125        $url = 'https://api.discogs.com/' . $query;
126        $url .= (strpos($query, '?') !== false) ? '&' : '?';
127        $url .= 'key=' . $this->api_key . '&secret=' . $this->secret;
128        debug_event(self::class, 'Discogs request: ' . $url, 5);
129        $request = Requests::get($url);
130
131        return json_decode($request->body, true);
132    }
133
134    /**
135     * @param $artist
136     * @return mixed
137     */
138    protected function search_artist($artist)
139    {
140        $query = "database/search?type=artist&title=" . rawurlencode($artist) . "&per_page=10";
141
142        return $this->query_discogs($query);
143    }
144
145    /**
146     * @param integer $object_id
147     * @return mixed
148     */
149    protected function get_artist($object_id)
150    {
151        $query = "artists/" . $object_id;
152
153        return $this->query_discogs($query);
154    }
155
156    /**
157     * @param $artist
158     * @param $album
159     * @return mixed
160     */
161    protected function search_album($artist, $album)
162    {
163        $query = "database/search?type=master&release_title=" . rawurlencode($album) . "&artist=" . rawurlencode($artist) . "&per_page=10";
164
165        return $this->query_discogs($query);
166    }
167
168    /**
169     * @param integer $object_id
170     * @return mixed
171     */
172    protected function get_album($object_id)
173    {
174        $query = "masters/" . $object_id;
175
176        return $this->query_discogs($query);
177    }
178
179    /**
180     * get_metadata
181     * Returns song metadata for what we're passed in.
182     * @param array $gather_types
183     * @param array $media_info
184     * @return array|null
185     */
186    public function get_metadata($gather_types, $media_info)
187    {
188        debug_event(self::class, 'Getting metadata from Discogs...', 5);
189
190        // MUSIC metadata only
191        if (!in_array('music', $gather_types)) {
192            debug_event(self::class, 'Not a valid media type, skipped.', 5);
193
194            return null;
195        }
196
197        $results = array();
198        try {
199            if (in_array('artist', $gather_types)) {
200                $artists = $this->search_artist($media_info['title']);
201                if (count($artists['results']) > 0) {
202                    $artist = $this->get_artist($artists['results'][0]['id']);
203                    if (count($artist['images']) > 0) {
204                        $results['art'] = $artist['images'][0]['uri'];
205                    }
206                }
207            } else {
208                if (in_array('album', $gather_types)) {
209                    $albums = $this->search_album($media_info['artist'], $media_info['title']);
210                    if (!empty($albums['results'])) {
211                        $album = $this->get_album($albums['results'][0]['id']);
212                        if (count($album['images']) > 0) {
213                            $results['art'] = $album['images'][0]['uri'];
214                        }
215                    }
216                }
217            }
218        } catch (Exception $error) {
219            debug_event(self::class, 'Error getting metadata: ' . $error->getMessage(), 1);
220        }
221
222        return $results;
223    } // get_metadata
224
225    /**
226     * @param string $type
227     * @param array $options
228     * @param integer $limit
229     * @return array
230     */
231    public function gather_arts($type, $options = array(), $limit = 5)
232    {
233        return Art::gather_metadata_plugin($this, $type, $options);
234    }
235}
236