Skip to content

Commit

Permalink
feat: added anime synonyms to series scout search (#772)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kyrch authored Jan 10, 2025
1 parent d609fbd commit d45545e
Show file tree
Hide file tree
Showing 15 changed files with 193 additions and 84 deletions.
5 changes: 1 addition & 4 deletions app/Actions/Discord/DiscordVideoNotificationAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
namespace App\Actions\Discord;

use App\Enums\Actions\Models\Wiki\Video\NotificationType;
use App\Enums\Actions\Models\Wiki\Video\ShouldForceThread;
use App\Models\Wiki\Video;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Arr;
Expand All @@ -27,7 +26,6 @@ class DiscordVideoNotificationAction
public function handle(Collection $videos, array $fields): void
{
$type = Arr::get($fields, NotificationType::getFieldKey());
$shouldForce = ShouldForceThread::from(intval(Arr::get($fields, ShouldForceThread::getFieldKey())));

$newVideos = [];

Expand All @@ -36,15 +34,14 @@ public function handle(Collection $videos, array $fields): void
->load([
'animethemeentries.animetheme.anime.discordthread',
'animethemeentries.animetheme.anime.images',
'animethemeentries.animetheme.group',
Video::RELATION_GROUP,
'animethemeentries.animetheme.song.artists',
]);

$theme = $video->animethemeentries->first()->animetheme;
$anime = $theme->anime;

if ($anime->discordthread === null) {
if ($shouldForce === ShouldForceThread::NO) return;

$threadAction = new DiscordThreadAction();

Expand Down
2 changes: 1 addition & 1 deletion app/Concerns/Models/CanCreateExternalResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public function createResource(string $url, ResourceSite $site, (BaseModel&HasRe
$url = $site->formatResourceLink($model::class, intval($matches[2]), $matches[2], $matches[1]);
}

if ($id !== null) {
if ($id !== null && !$site->usesIdInLink()) {
$url = $site->formatResourceLink($model::class, intval($id), $id);
}
}
Expand Down
28 changes: 0 additions & 28 deletions app/Enums/Actions/Models/Wiki/Video/ShouldForceThread.php

This file was deleted.

17 changes: 15 additions & 2 deletions app/Enums/Models/Wiki/ResourceSite.php
Original file line number Diff line number Diff line change
Expand Up @@ -292,12 +292,12 @@ public static function getForModel(?string $modelClass): array
* Get the URL of the site for resources by determined model.
*
* @param class-string $modelClass
* @param int $id
* @param int|null $id
* @param string|null $slug
* @param string|null $type
* @return string|null
*/
public function formatResourceLink(string $modelClass, int $id, ?string $slug = null, ?string $type = null): ?string
public function formatResourceLink(string $modelClass, ?int $id = null, ?string $slug = null, ?string $type = null): ?string
{
if ($modelClass === Anime::class) {
return match ($this) {
Expand Down Expand Up @@ -362,6 +362,19 @@ public function formatResourceLink(string $modelClass, int $id, ?string $slug =
return null;
}

/**
* Determine whether the resource uses external id in the url.
*
* @return bool
*/
public function usesIdInLink(): bool
{
return match ($this) {
ResourceSite::ANIME_PLANET => false,
default => true,
};
}

/**
* Get the URL capture groups of the resource site.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use App\Actions\Discord\DiscordVideoNotificationAction as DiscordVideoNotificationActionAction;
use App\Enums\Actions\Models\Wiki\Video\NotificationType;
use App\Enums\Actions\Models\Wiki\Video\ShouldForceThread;
use App\Filament\BulkActions\BaseBulkAction;
use App\Filament\Components\Fields\Select;
use App\Models\Discord\DiscordThread;
Expand Down Expand Up @@ -70,14 +69,6 @@ public function getForm(Form $form): ?Form
->default(NotificationType::ADDED->value)
->required()
->rules(['required', new Enum(NotificationType::class)]),

Select::make(ShouldForceThread::getFieldKey())
->label(__('filament.bulk_actions.discord.notification.should_force.name'))
->helperText(__('filament.bulk_actions.discord.notification.should_force.help'))
->options(ShouldForceThread::asSelectArray())
->default(ShouldForceThread::NO->value)
->required()
->rules(['required', new Enum(ShouldForceThread::class)]),
]);
}
}
2 changes: 1 addition & 1 deletion app/Http/Controllers/Api/Pivot/PivotController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use App\Http\Api\Schema\Schema;
use App\Http\Controllers\Controller;
use App\Http\Middleware\Auth\Authenticate;
use App\Http\Middleware\Models\AuthorizesPivot;
use App\Http\Middleware\Models\Pivot\AuthorizesPivot;
use Illuminate\Support\Str;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace App\Http\Middleware\Models;
namespace App\Http\Middleware\Models\Pivot;

use App\Models\Auth\User;
use Closure;
Expand Down
28 changes: 28 additions & 0 deletions app/Models/Wiki/Series.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use App\Pivots\Wiki\AnimeSeries;
use Database\Factories\Wiki\SeriesFactory;
use Elastic\ScoutDriverPlus\Searchable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Support\Collection;

Expand All @@ -39,6 +40,7 @@ class Series extends BaseModel
final public const ATTRIBUTE_SLUG = 'slug';

final public const RELATION_ANIME = 'anime';
final public const RELATION_ANIME_SYNONYMS = 'anime.animesynonyms';

/**
* The attributes that are mass assignable.
Expand Down Expand Up @@ -78,6 +80,32 @@ class Series extends BaseModel
*/
protected $primaryKey = Series::ATTRIBUTE_ID;

/**
* Modify the query used to retrieve models when making all of the models searchable.
*
* @param Builder $query
* @return Builder
*/
protected function makeAllSearchableUsing(Builder $query): Builder
{
return $query->with(Series::RELATION_ANIME_SYNONYMS);
}

/**
* Get the indexable data array for the model.
*
* @return array
*/
public function toSearchableArray(): array
{
$array = $this->toArray();
$array['anime'] = $this->anime->map(
fn (Anime $anime) => $anime->toSearchableArray()
)->toArray();

return $array;
}

/**
* Get the route key for the model.
*
Expand Down
5 changes: 0 additions & 5 deletions app/Policies/Wiki/ArtistPolicy.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,6 @@ public function attachAnyArtist(User $user): bool
*/
public function attachArtist(User $user, Artist $artist, Artist $artist2): bool
{
if ($artist->is($artist2)) {
// An artist cannot be a member/group of themselves
return false;
}

$attached = ArtistMember::query()
->where(ArtistMember::ATTRIBUTE_ARTIST, $artist->getKey())
->where(ArtistMember::ATTRIBUTE_MEMBER, $artist2->getKey())
Expand Down
14 changes: 7 additions & 7 deletions app/Scout/Elasticsearch/Api/Query/ElasticQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ abstract public function build(Criteria $criteria): SearchParametersBuilder;
* - Matching at least one term (word) (x0.6)
* - Matching fuzzy (x0.4)
*
* @param string $field
* @param string $searchTerm
* @param string $field
* @param string $searchTerm
* @return array
*/
protected function createTextQuery(string $field, string $searchTerm): array
Expand Down Expand Up @@ -71,8 +71,8 @@ protected function createTextQuery(string $field, string $searchTerm): array
/**
* Helper function for raw queries. This will wrap queries in nested queries.
*
* @param string $nestedResource
* @param array $nestedQueries
* @param string $nestedResource
* @param array $nestedQueries
* @return array
*/
protected function createNestedQuery(string $nestedResource, array $nestedQueries): array
Expand All @@ -92,9 +92,9 @@ protected function createNestedQuery(string $nestedResource, array $nestedQuerie
* Shorthand function for calling `$this->createNestedQuery()` with the output from
* `$this->createTextQuery()`.
*
* @param string $nestedResource
* @param string $field
* @param string $searchTerm
* @param string $nestedResource
* @param string $field
* @param string $searchTerm
* @return array
*/
protected function createNestedTextQuery(string $nestedResource, string $field, string $searchTerm): array
Expand Down
42 changes: 20 additions & 22 deletions app/Scout/Elasticsearch/Api/Query/Wiki/SeriesQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
use App\Http\Api\Criteria\Search\Criteria;
use App\Models\Wiki\Series;
use App\Scout\Elasticsearch\Api\Query\ElasticQuery;
use Elastic\ScoutDriverPlus\Builders\MatchPhraseQueryBuilder;
use Elastic\ScoutDriverPlus\Builders\MatchQueryBuilder;
use Elastic\ScoutDriverPlus\Builders\SearchParametersBuilder;
use Elastic\ScoutDriverPlus\Support\Query;

Expand All @@ -26,26 +24,26 @@ class SeriesQuery extends ElasticQuery
public function build(Criteria $criteria): SearchParametersBuilder
{
$query = Query::bool()
->should(
new MatchPhraseQueryBuilder()
->field('name')
->query($criteria->getTerm())
)
->should(
new MatchQueryBuilder()
->field('name')
->query($criteria->getTerm())
->operator('AND')
)
->should(
new MatchQueryBuilder()
->field('name')
->query($criteria->getTerm())
->operator('AND')
->lenient(true)
->fuzziness('AUTO')
)
->minimumShouldMatch(1);
->mustRaw([
'dis_max' => [
'queries' => [
[
'bool' => [
'should' => $this->createTextQuery('name', $criteria->getTerm())
]
],
[
'bool' => [
'boost' => 0.6,
'should' => $this->createNestedQuery(
'anime',
$this->createNestedTextQuery('anime.synonyms', 'text', $criteria->getTerm())
)
]
]
]
]
]);

return Series::searchQuery($query);
}
Expand Down
2 changes: 2 additions & 0 deletions database/seeders/DatabaseSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Database\Seeders\Admin\Feature\FeatureSeeder;
use Database\Seeders\Auth\Permission\PermissionSeeder;
use Database\Seeders\Auth\Role\RoleSeeder;
use Database\Seeders\Scout\ImportModelsSeeder;
use Database\Seeders\Wiki\Audio\AudioSeeder;
use Database\Seeders\Wiki\Video\VideoSeeder;
use Illuminate\Database\Seeder;
Expand All @@ -29,5 +30,6 @@ public function run(): void
$this->call(AudioSeeder::class);
$this->call(HashidsSeeder::class);
$this->call(FeatureSeeder::class);
$this->call(ImportModelsSeeder::class);
}
}
62 changes: 62 additions & 0 deletions database/seeders/Scout/ImportModelsSeeder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

declare(strict_types=1);

namespace Database\Seeders\Scout;

use App\Models\List\Playlist;
use App\Models\Wiki\Anime;
use App\Models\Wiki\Anime\AnimeSynonym;
use App\Models\Wiki\Anime\AnimeTheme;
use App\Models\Wiki\Anime\Theme\AnimeThemeEntry;
use App\Models\Wiki\Artist;
use App\Models\Wiki\Series;
use App\Models\Wiki\Song;
use App\Models\Wiki\Studio;
use App\Models\Wiki\Video;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Config;

/**
* Class ImportModelsSeeder.
*/
class ImportModelsSeeder extends Seeder
{
/**
* Seed the application's database.
*
* @return void
*/
public function run(): void
{
$driver = Config::get('scout.driver');
if (empty($driver)) {
$this->command->info('No driver configured for Scout. Skipping models importing.');
return;
}

$this->scoutImport(Playlist::class);
$this->scoutImport(Anime::class);
$this->scoutImport(AnimeSynonym::class);
$this->scoutImport(AnimeTheme::class);
$this->scoutImport(AnimeThemeEntry::class);
$this->scoutImport(Artist::class);
$this->scoutImport(Series::class);
$this->scoutImport(Song::class);
$this->scoutImport(Studio::class);
$this->scoutImport(Video::class);
}

/**
* Call the scout import command for the given model.
*
* @param string $modelClass
* @return void
*/
private function scoutImport(string $modelClass): void
{
$this->command->info("Importing Models for {$modelClass}");
Artisan::call('scout:import', ['model' => $modelClass]);
}
}
Loading

0 comments on commit d45545e

Please sign in to comment.