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 */ 22 23declare(strict_types=0); 24 25namespace Ampache\Module\Api\Method; 26 27use Ampache\Config\AmpConfig; 28use Ampache\Repository\Model\Song; 29use Ampache\Repository\Model\User; 30use Ampache\Module\Api\Api; 31use Ampache\Module\System\Session; 32use Ampache\Repository\UserRepositoryInterface; 33 34/** 35 * Class ScrobbleMethod 36 * @package Lib\ApiMethods 37 */ 38final class ScrobbleMethod 39{ 40 private const ACTION = 'scrobble'; 41 42 /** 43 * scrobble 44 * MINIMUM_API_VERSION=400001 45 * 46 * Search for a song using text info and then record a play if found. 47 * This allows other sources to record play history to Ampache 48 * 49 * @param array $input 50 * song = (string) $song_name 51 * artist = (string) $artist_name 52 * album = (string) $album_name 53 * songmbid = (string) $song_mbid //optional 54 * artistmbid = (string) $artist_mbid //optional 55 * albummbid = (string) $album_mbid //optional 56 * date = (integer) UNIXTIME() //optional 57 * client = (string) $agent //optional 58 * @return boolean 59 */ 60 public static function scrobble(array $input) 61 { 62 if (!Api::check_parameter($input, array('song', 'artist', 'album'), self::ACTION)) { 63 return false; 64 } 65 ob_end_clean(); 66 $charset = AmpConfig::get('site_charset'); 67 $song_name = (string) html_entity_decode(scrub_out($input['song']), ENT_QUOTES, $charset); 68 $artist_name = (string) html_entity_decode(scrub_in((string) $input['artist']), ENT_QUOTES, $charset); 69 $album_name = (string) html_entity_decode(scrub_in((string) $input['album']), ENT_QUOTES, $charset); 70 $song_mbid = (string) scrub_in($input['song_mbid']); //optional 71 $artist_mbid = (string) scrub_in($input['artist_mbid']); //optional 72 $album_mbid = (string) scrub_in($input['album_mbid']); //optional 73 $date = (is_numeric(scrub_in($input['date']))) ? (int) scrub_in($input['date']) : time(); //optional 74 $user = User::get_from_username(Session::username($input['auth'])); 75 $user_id = $user->id; 76 $valid = in_array($user->id, static::getUserRepository()->getValid()); 77 78 // validate supplied user 79 if ($valid === false) { 80 /* HINT: Requested object string/id/type ("album", "myusername", "some song title", 1298376) */ 81 Api::error(sprintf(T_('Not Found: %s'), $user_id), '4704', self::ACTION, 'empty', $input['api_format']); 82 83 return false; 84 } 85 86 // validate minimum required options 87 debug_event(self::class, 'scrobble searching for:' . $song_name . ' - ' . $artist_name . ' - ' . $album_name, 4); 88 if (!$song_name || !$album_name || !$artist_name) { 89 Api::error(T_('Bad Request'), '4710', self::ACTION, 'input', $input['api_format']); 90 91 return false; 92 } 93 94 // validate client string or fall back to 'api' 95 $agent = ($input['client']) 96 ? $input['client'] 97 : 'api'; 98 $scrobble_id = Song::can_scrobble($song_name, $artist_name, $album_name, (string) $song_mbid, (string) $artist_mbid, (string) $album_mbid); 99 100 if ($scrobble_id === '') { 101 Api::error(T_('Not Found'), '4704', self::ACTION, 'song', $input['api_format']); 102 } else { 103 $media = new Song((int) $scrobble_id); 104 if (!$media->id) { 105 /* HINT: Requested object string/id/type ("album", "myusername", "some song title", 1298376) */ 106 Api::error(sprintf(T_('Not Found: %s'), $scrobble_id), '4704', self::ACTION, 'song', $input['api_format']); 107 108 return false; 109 } 110 debug_event(self::class, 'scrobble: ' . $media->id . ' for ' . $user->username . ' using ' . $agent . ' ' . $date, 5); 111 112 // internal scrobbling (user_activity and object_count tables) 113 if ($media->set_played($user_id, $agent, array(), $date)) { 114 // scrobble plugins 115 User::save_mediaplay($user, $media); 116 } 117 118 Api::message('successfully scrobbled: ' . $scrobble_id, $input['api_format']); 119 } 120 Session::extend($input['auth']); 121 122 return true; 123 } 124 125 /** 126 * @deprecated inject dependency 127 */ 128 private static function getUserRepository(): UserRepositoryInterface 129 { 130 global $dic; 131 132 return $dic->get(UserRepositoryInterface::class); 133 } 134} 135