diff --git a/php/src/app/Http/Controllers/SearchController.php b/php/src/app/Http/Controllers/SearchController.php index 25c21b7..481c574 100644 --- a/php/src/app/Http/Controllers/SearchController.php +++ b/php/src/app/Http/Controllers/SearchController.php @@ -13,40 +13,41 @@ use Facebook\WebDriver\WebDriverBy; class SearchController extends Controller { - - protected static function buildResponse($artist_id) { - return [ - 'name' => $artist_id->name, - 'url_remote' => $artist_id->url_remote, - 'thumbnail' => $artist_id->thumbnail, - ]; - } - - protected function setUp() + protected function getArtist($driver) { - $host = 'http://selenium-hub:4444'; - $capabilities = DesiredCapabilities::chrome(); - $chromeOptions = new ChromeOptions(); - // TODO: Add '--headless' back in to arguments - $chromeOptions->addArguments(['--no-sandbox', '--disable-dev-shm-usage']); - $capabilities->setCapability(ChromeOptions::CAPABILITY_W3C, $chromeOptions); - $driver = RemoteWebDriver::create($host, $capabilities); - $driver->manage()->window()->maximize(); - return $driver; + $response = []; + $artistContainer = $driver->findElement(WebDriverBy::cssSelector('.main-card-content-container')); + $artistThumbnail = $artistContainer->findElement(WebDriverBy::cssSelector('img'))->getAttribute('src'); + $artistLink = $artistContainer->findElements(WebDriverBy::cssSelector('a')); + $artistHref = $artistLink[0]->getAttribute('href'); + $artistName = $artistLink[0]->getAttribute('title'); + + if ($artistHref && $artistThumbnail && $artistName) { + $existingArtist = Artist::findByName($artistName)->first(); + + if (!$existingArtist) { + $artist_id = new Artist(); + $artist_id->name = $artistName; + $artist_id->thumbnail = $artistThumbnail; + $artist_id->url_remote = $artistHref; + $artist_id->save(); + $response[] = $this->buildResponse($artist_id); + } elseif (!$existingArtist->selected) { + $this->buildResponse($existingArtist); + } + } + return $response; } - public function search_artist(Request $request, string $artist) + protected function getArtists($driver) { $response = []; - $url = 'https://music.youtube.com/search?q=' . str_replace(' ', '+', $artist); - $driver = $this->setUp(); - $driver->get($url); - // Click the artist button to force a "structure" of results $artistBtnXpath = '//a[@title="Show artist results"]'; $driver->wait(10, 500)->until( WebDriverExpectedCondition::visibilityOfElementLocated(WebDriverBy::xpath($artistBtnXpath)) ); + $driver->findElement(WebDriverBy::xpath($artistBtnXpath))->click(); // Youtube has multiple elements with the same ID (Naughty!). We will give a reasonable analog time to render. sleep(5); @@ -78,20 +79,20 @@ class SearchController extends Controller $artist_id->thumbnail = $artistThumbnail; $artist_id->url_remote = $artistHref; $artist_id->save(); - - $response += [$this->buildResponse($artist_id)]; - } elseif (!$existingArtist->selected) { + \Log::info('New Artist added: ' . $artist_id->name); + $response[] = $this->buildResponse($artist_id); + } elseif ($existingArtist->exists() && !$existingArtist->selected) { // Send the unselected artists back to client as suggestions - $response += [$this->buildResponse($existingArtist)]; + \Log::info('Artist already found' . $existingArtist->name); + $response[] = $this->buildResponse($existingArtist); } // Limit the results, there are alot of them - if($resultCap <= $resultIndex) { + if ($resultCap <= $resultIndex) { break; } } } - // There are 4 div#contents returned, one empty and 3 with duplicated info if ($divCount === 1) { break; @@ -99,7 +100,48 @@ class SearchController extends Controller } } - $driver->quit(); + return $response; + } + + protected static function buildResponse($artist_id) + { + return [ + 'name' => $artist_id->name, + 'url_remote' => $artist_id->url_remote, + 'thumbnail' => $artist_id->thumbnail, + ]; + } + + protected function setUp() + { + $host = 'http://selenium-hub:4444'; + $capabilities = DesiredCapabilities::chrome(); + $chromeOptions = new ChromeOptions(); + // TODO: Add '--headless' back in to arguments + $chromeOptions->addArguments(['--no-sandbox', '--disable-dev-shm-usage']); + $capabilities->setCapability(ChromeOptions::CAPABILITY_W3C, $chromeOptions); + $driver = RemoteWebDriver::create($host, $capabilities); + $driver->manage()->window()->maximize(); + return $driver; + } + + public function search_artist(Request $request, string $artist) + { + $response = []; + $url = 'https://music.youtube.com/search?q=' . str_replace(' ', '+', $artist); + $driver = $this->setUp(); + $driver->get($url); + + // Add handling for no artist button; Some artists searches don't have this option (Ex The Black Dahlia Murder) + try { + $response = $this->getArtists($driver); + } catch (\Exception) { + \Log::warning('Could not get list of artists, attempting to get single artist card..'); + $response = $this->getArtist($driver); + } finally { + $driver->quit(); + } + return response()->json($response); } } diff --git a/php/src/database/migrations/2024_08_06_030651_add_artist_field_state.php b/php/src/database/migrations/2024_08_06_030651_add_artist_field_state.php new file mode 100644 index 0000000..733604b --- /dev/null +++ b/php/src/database/migrations/2024_08_06_030651_add_artist_field_state.php @@ -0,0 +1,32 @@ +enum('state', [ + 'pending', + 'in_progress', + 'done', + ])->default('pending'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('artists', function (Blueprint $table) { + // + }); + } +}; diff --git a/php/src/public/js/app.js b/php/src/public/js/app.js index f8d72d6..11b4838 100644 --- a/php/src/public/js/app.js +++ b/php/src/public/js/app.js @@ -37,6 +37,7 @@ $('#download_btn').on('click', () => { icon = 'success'; title = 'Shazam!'; proc_notification(icon, title, 'Artist found'); + $('#search_bar').val(''); loader.fadeOut(700); }, error: (response) => {