Skip to content

Commit

Permalink
fix: the streaming resources should have more patterns (#626)
Browse files Browse the repository at this point in the history
* fix: the streaming resources should have more patterns

* fix: fixing resources tests
  • Loading branch information
Kyrch authored Mar 15, 2024
1 parent 6fefbf3 commit a609bf0
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -80,18 +80,19 @@ protected function getAvailableSites(): array
protected function getOrCreateResource(mixed $externalLink): ExternalResource
{
$availableSites = $this->getAvailableSites();
$url = $externalLink['url'];
/** @var ResourceSite $resourceSite */
$resourceSite = $availableSites[$externalLink['site']];
$urlPattern = $this->getUrlPattern($resourceSite->value);
$url = $externalLink['url'];
$urlPattern = $resourceSite->getUrlPattern();

if (preg_match($urlPattern, $url, $matches)) {
$url = $resourceSite->formatAnimeResourceLink(intval($matches[1]), $matches[1]);
$url = $resourceSite->formatAnimeResourceLink(intval($matches[2]), $matches[2], $matches[1]);
}

$resource = ExternalResource::query()
->where(ExternalResource::ATTRIBUTE_SITE, $resourceSite->value)
->where(ExternalResource::ATTRIBUTE_LINK, $url)
->orWhere(ExternalResource::ATTRIBUTE_LINK, $url . "/")
->orWhere(ExternalResource::ATTRIBUTE_LINK, $url . '/')
->first();

if ($resource === null) {
Expand All @@ -101,7 +102,7 @@ protected function getOrCreateResource(mixed $externalLink): ExternalResource
$resource = ExternalResource::query()->create([
ExternalResource::ATTRIBUTE_LINK => $url,
ExternalResource::ATTRIBUTE_SITE => $resourceSite->value,
ExternalResource::ATTRIBUTE_EXTERNAL_ID => $resourceSite->parseIdFromLink($url) ?? null,
ExternalResource::ATTRIBUTE_EXTERNAL_ID => $resourceSite->parseIdFromLink($url),
]);
}

Expand Down Expand Up @@ -141,6 +142,11 @@ protected function getAnilistResource(): ?ExternalResource
return null;
}

/**
* Get the external links by AniList API.
*
* @return array|null
*/
protected function getExternalLinksByAnilistResource(): ?array
{
$anilistResource = $this->getAnilistResource();
Expand Down Expand Up @@ -176,19 +182,4 @@ protected function getExternalLinksByAnilistResource(): ?array

return null;
}

protected function getUrlPattern(int $resourceSite): string
{
$matches = [
ResourceSite::TWITTER->value => '/^https:\/\/twitter\.com\/(\w+)/',
ResourceSite::CRUNCHYROLL->value => '/^https:\/\/www\.crunchyroll\.com\/series\/(\w+)/',
ResourceSite::HIDIVE->value => '/^https:\/\/www\.hidive\.com\/tv\/([\w-]+)/',
ResourceSite::NETFLIX->value => '/^https:\/\/www\.netflix\.com\/title\/(\d+)/',
ResourceSite::DISNEY_PLUS->value => '/^https:\/\/www\.disneyplus\.com\/series\/([\w-]+\/\w+)/',
ResourceSite::HULU->value => '/^https:\/\/www\.hulu\.com\/series\/([\w-]+)/',
ResourceSite::AMAZON_PRIME_VIDEO->value => '/^https:\/\/www\.primevideo\.com\/detail\/(\w+)/',
];

return $matches[$resourceSite] ?? '/^$/';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public function handle(): ActionResult
$language = $externalLink['language'];

if (!in_array($site, array_keys($availableSites))) continue;
if (in_array($site, ['Official Site', 'Twitter']) && $language !== 'Japanese') continue;
if (in_array($site, ['Official Site', 'Twitter']) && !in_array($language, ['Japanese', null])) continue;

if ($this->relation()->getQuery()->where(ExternalResource::ATTRIBUTE_SITE, $availableSites[$site]->value)->exists()) {
$nameLocalized = $availableSites[$site]->localize();
Expand Down
34 changes: 27 additions & 7 deletions app/Enums/Models/Wiki/ResourceSite.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ protected static function parseAnimePlanetIdFromLink(string $link): ?string

return null;
}

/**
* Attempt to parse Kitsu ID from link.
*
Expand Down Expand Up @@ -188,9 +188,10 @@ protected static function parseKitsuIdFromLink(string $link): ?string
*
* @param int $id
* @param string|null $slug
* @param string|null $type
* @return string|null
*/
public function formatAnimeResourceLink(int $id, ?string $slug = null): ?string
public function formatAnimeResourceLink(int $id, ?string $slug = null, ?string $type = null): ?string
{
return match ($this) {
ResourceSite::TWITTER => "https://twitter.com/$slug",
Expand All @@ -201,11 +202,11 @@ public function formatAnimeResourceLink(int $id, ?string $slug = null): ?string
ResourceSite::KITSU => "https://kitsu.io/anime/$slug",
ResourceSite::MAL => "https://myanimelist.net/anime/$id",
ResourceSite::YOUTUBE => "https://www.youtube.com/@$slug",
ResourceSite::CRUNCHYROLL => "https://www.crunchyroll.com/series/$slug",
ResourceSite::HIDIVE => "https://www.hidive.com/tv/$slug",
ResourceSite::NETFLIX => "https://www.netflix.com/title/$id",
ResourceSite::DISNEY_PLUS => "https://www.disneyplus.com/series/$slug/$id",
ResourceSite::HULU => "https://www.hulu.com/series/$slug",
ResourceSite::CRUNCHYROLL => "https://www.crunchyroll.com/$type/$slug",
ResourceSite::HIDIVE => "https://www.hidive.com/$type/$slug",
ResourceSite::NETFLIX => "https://www.netflix.com/$type/$id",
ResourceSite::DISNEY_PLUS => "https://www.disneyplus.com/$type/$slug/$id",
ResourceSite::HULU => "https://www.hulu.com/$type/$slug",
ResourceSite::AMAZON_PRIME_VIDEO => "https://www.primevideo.com/detail/$slug",
default => null,
};
Expand Down Expand Up @@ -271,4 +272,23 @@ public function formatStudioResourceLink(int $id, ?string $slug = null): ?string
default => null,
};
}

/**
* Get the URL pattern of the resource site.
*
* @return string
*/
public function getUrlPattern(): string
{
return match ($this) {
ResourceSite::TWITTER => '/^https?:\/\/(twitter)\.com\/(\w+)/',
ResourceSite::CRUNCHYROLL => '/^https?:\/\/www\.crunchyroll\.com\/(series|watch)\/(\w+)/',
ResourceSite::HIDIVE => '/^https?:\/\/www\.hidive\.com\/(tv|movies)\/([\w-]+)/',
ResourceSite::NETFLIX => '/^https?:\/\/www\.netflix\.com\/(title|watch)\/(\d+)/',
ResourceSite::DISNEY_PLUS => '/^https?:\/\/www\.disneyplus\.com\/(series|movies)\/([\w-]+\/\w+)/',
ResourceSite::HULU => '/^https?:\/\/www\.hulu\.com\/(series|watch|movie)\/([\w-]+)/',
ResourceSite::AMAZON_PRIME_VIDEO => '/^https?:\/\/www\.primevideo\.com\/(detail)\/(\w+)/',
default => '/^$/',
};
}
}
8 changes: 4 additions & 4 deletions app/Rules/Wiki/Resource/AnimeResourceLinkFormatRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ public function validate(string $attribute, mixed $value, Closure $fail): void
ResourceSite::YOUTUBE => '/^https:\/\/www\.youtube\.com\/\@\w+$/',
ResourceSite::APPLE_MUSIC => '/$.^/',
ResourceSite::AMAZON_MUSIC => '/$.^/',
ResourceSite::CRUNCHYROLL => '/^https:\/\/www\.crunchyroll\.com\/series\/\w+$/',
ResourceSite::HIDIVE => '/^https:\/\/www\.hidive\.com\/tv\/[\w-]+$/',
ResourceSite::CRUNCHYROLL => '/^https:\/\/www\.crunchyroll\.com\/(series|watch)\/\w+$/',
ResourceSite::HIDIVE => '/^https:\/\/www\.hidive\.com\/(tv|movies)\/[\w-]+$/',
ResourceSite::NETFLIX => '/^https:\/\/www\.netflix\.com\/title\/\d+$/',
ResourceSite::DISNEY_PLUS => '/^https:\/\/www\.disneyplus\.com\/series\/[\w-]+\/\w+$/',
ResourceSite::HULU => '/^https:\/\/www\.hulu\.com\/series\/[\w-]+$/',
ResourceSite::DISNEY_PLUS => '/^https:\/\/www\.disneyplus\.com\/(series|movies)\/[\w-]+\/\w+$/',
ResourceSite::HULU => '/^https:\/\/www\.hulu\.com\/(series|watch|movie)\/[\w-]+$/',
ResourceSite::AMAZON_PRIME_VIDEO => '/^https:\/\/www\.primevideo\.com\/detail\/\w+$/',
default => null,
};
Expand Down
26 changes: 6 additions & 20 deletions database/seeders/Wiki/Anime/BackfillExternalResourcesSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public function run(): void
$language = $externalLink['language'];

if (!in_array($site, array_keys($availableSites))) continue;
if (in_array($site, ['Official Site', 'Twitter']) && $language !== 'Japanese') continue;
if (in_array($site, ['Official Site', 'Twitter']) && !in_array($language, ['Japanese', null])) continue;

if ($this->relation($anime)->getQuery()->where(ExternalResource::ATTRIBUTE_SITE, $availableSites[$site]->value)->exists()) {
$nameLocalized = $availableSites[$site]->localize();
Expand Down Expand Up @@ -155,12 +155,13 @@ protected function attachResource(ExternalResource $resource, Anime $anime): voi
protected function getOrCreateResource(mixed $externalLink, Anime $anime): ExternalResource
{
$availableSites = $this->getAvailableSites();
$url = $externalLink['url'];
/** @var ResourceSite $resourceSite */
$resourceSite = $availableSites[$externalLink['site']];
$urlPattern = $this->getUrlPattern($resourceSite->value);
$url = $externalLink['url'];
$urlPattern = $resourceSite->getUrlPattern();

if (preg_match($urlPattern, $url, $matches)) {
$url = $resourceSite->formatAnimeResourceLink(intval($matches[1]), $matches[1]);
$url = $resourceSite->formatAnimeResourceLink(intval($matches[2]), $matches[2], $matches[1]);
}

$resource = ExternalResource::query()
Expand All @@ -177,7 +178,7 @@ protected function getOrCreateResource(mixed $externalLink, Anime $anime): Exter
$resource = ExternalResource::query()->create([
ExternalResource::ATTRIBUTE_LINK => $url,
ExternalResource::ATTRIBUTE_SITE => $resourceSite->value,
ExternalResource::ATTRIBUTE_EXTERNAL_ID => $resourceSite->parseIdFromLink($url) ?? null,
ExternalResource::ATTRIBUTE_EXTERNAL_ID => $resourceSite->parseIdFromLink($url),
]);
}

Expand All @@ -203,19 +204,4 @@ protected function getAvailableSites(): array
'Disney Plus' => ResourceSite::DISNEY_PLUS,
];
}

protected function getUrlPattern(int $resourceSite): string
{
$matches = [
ResourceSite::TWITTER->value => '/^https:\/\/twitter\.com\/(\w+)/',
ResourceSite::CRUNCHYROLL->value => '/^https:\/\/www\.crunchyroll\.com\/series\/(\w+)/',
ResourceSite::HIDIVE->value => '/^https:\/\/www\.hidive\.com\/tv\/([\w-]+)/',
ResourceSite::NETFLIX->value => '/^https:\/\/www\.netflix\.com\/title\/(\d+)/',
ResourceSite::DISNEY_PLUS->value => '/^https:\/\/www\.disneyplus\.com\/series\/([\w-]+\/\w+)/',
ResourceSite::HULU->value => '/^https:\/\/www\.hulu\.com\/series\/([\w-]+)/',
ResourceSite::AMAZON_PRIME_VIDEO->value => '/^https:\/\/www\.primevideo\.com\/detail\/(\w+)/',
];

return $matches[$resourceSite] ?? '/^$/';
}
}
72 changes: 72 additions & 0 deletions database/seeders/Wiki/Anime/FixExternalResourcesSeeder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

declare(strict_types=1);

namespace Database\Seeders\Wiki\Anime;

use App\Enums\Models\Wiki\ResourceSite;
use App\Models\Wiki\ExternalResource;
use Exception;
use Illuminate\Database\Seeder;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;

class FixExternalResourcesSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
try {
DB::beginTransaction();

$availableSites = $this->getAvailableSites();
$resourceSites = array_values($availableSites);

$externalResources = ExternalResource::query();

foreach ($resourceSites as $resourceSite) {
$externalResources = $externalResources->orWhere(ExternalResource::ATTRIBUTE_SITE, $resourceSite->value);
}

$externalResources = $externalResources->get();

foreach ($externalResources as $externalResource) {
$url = Arr::get($externalResource, ExternalResource::ATTRIBUTE_LINK);
$site = Arr::get($externalResource, ExternalResource::ATTRIBUTE_SITE);
$urlPattern = $site->getUrlPattern();

if (preg_match($urlPattern, $url, $matches)) {
$url = $site->formatAnimeResourceLink(intval($matches[2]), $matches[2], $matches[1]);

$externalResource->update([
ExternalResource::ATTRIBUTE_LINK => $url,
]);
}
}

DB::commit();

} catch (Exception $e) {
echo 'error ' . $e->getMessage();
echo "\n";

DB::rollBack();

throw $e;
}
}

protected function getAvailableSites(): array
{
/** Key name in Anilist API => @var ResourceSite */
return [
'Netflix' => ResourceSite::NETFLIX,
'Crunchyroll' => ResourceSite::CRUNCHYROLL,
'HIDIVE' => ResourceSite::HIDIVE,
'Hulu' => ResourceSite::HULU,
'Disney Plus' => ResourceSite::DISNEY_PLUS,
];
}
}
19 changes: 19 additions & 0 deletions tests/Unit/Models/Wiki/ExternalResourceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
use App\Models\Wiki\Anime;
use App\Models\Wiki\Artist;
use App\Models\Wiki\ExternalResource;
use App\Models\Wiki\Song;
use App\Models\Wiki\Studio;
use App\Pivots\Wiki\AnimeResource;
use App\Pivots\Wiki\ArtistResource;
use App\Pivots\Wiki\SongResource;
use App\Pivots\Wiki\StudioResource;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Foundation\Testing\WithFaker;
Expand Down Expand Up @@ -87,6 +89,23 @@ public function testArtists(): void
static::assertEquals(ArtistResource::class, $resource->artists()->getPivotClass());
}

/**
* Resource shall have a many-to-many relationship with the type Song.
*/
public function testSong(): void
{
$songCount = $this->faker->randomDigitNotNull();

$resource = ExternalResource::factory()
->has(Song::factory()->count($songCount))
->createOne();

static::assertInstanceOf(BelongsToMany::class, $resource->song());
static::assertEquals($songCount, $resource->song()->count());
static::assertInstanceOf(Song::class, $resource->song()->first());
static::assertEquals(SongResource::class, $resource->song()->getPivotClass());
}

/**
* Resource shall have a many-to-many relationship with the type Studio.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public function testPassesForPattern(): void
ResourceSite::AMAZON_PRIME_VIDEO,
]);

$url = $site->formatAnimeResourceLink($this->faker->randomDigitNotNull(), $this->faker->word());
$url = $site->formatAnimeResourceLink($this->faker->randomDigitNotNull(), $this->faker->word(), $this->faker->word());

$attribute = $this->faker->word();

Expand Down

0 comments on commit a609bf0

Please sign in to comment.