Skip to content

Commit 8d8910a

Browse files
committed
refactor: standardize query logic for filters, improve TypeSense compatibility, and handle upstream errors with stale data responses
1 parent fc288a6 commit 8d8910a

File tree

6 files changed

+213
-79
lines changed

6 files changed

+213
-79
lines changed

app/Anime.php

Lines changed: 88 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
use Carbon\CarbonImmutable;
1111
use Database\Factories\AnimeFactory;
1212
use Illuminate\Support\Facades\App;
13-
use Illuminate\Support\Facades\Log;
1413
use Jikan\Helper\Constants;
1514
use Jikan\Jikan;
1615
use Jikan\Request\Anime\AnimeRequest;
@@ -154,25 +153,32 @@ public function filterByRating(\Laravel\Scout\Builder|\Illuminate\Database\Eloqu
154153
/** @noinspection PhpUnused */
155154
public function filterByStartDate(\Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder $query, CarbonImmutable $value): \Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder
156155
{
157-
return $query
158-
->where("aired.from", ">=",
159-
$value
160-
->setTime(0, 0)
161-
->setTimezone(new \DateTimeZone('UTC'))
162-
->toAtomString()
163-
);
156+
$compareVal = $value->setTime(0, 0)->setTimezone(new \DateTimeZone('UTC'));
157+
if (is_scout_query_builder($query)) {
158+
$query = $query->where("start_date", [">=", $compareVal->getTimestamp()]);
159+
} else {
160+
$query = $query->where("aired.from", ">=", $compareVal->toAtomString());
161+
}
162+
return $query;
164163
}
165164

166165
/** @noinspection PhpUnused */
167166
public function filterByEndDate(\Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder $query, CarbonImmutable $value): \Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder
168167
{
169-
return $query
170-
->where("aired.to", "<=",
171-
$value
172-
->setTime(0, 0)
173-
->setTimezone(new \DateTimeZone('UTC'))
174-
->toAtomString()
175-
);
168+
$compareVal = $value->setTime(0, 0)->setTimezone(new \DateTimeZone('UTC'));
169+
if (is_scout_query_builder($query)) {
170+
$query = $query->where("(end_date", [
171+
"<=", $compareVal->getTimestamp(),
172+
" || end_date:=", "null",
173+
")"
174+
]);
175+
} else {
176+
$query = $query->where(function (\Jenssegers\Mongodb\Eloquent\Builder $query) use ($compareVal) {
177+
return $query->where("aired.to", "<=", $compareVal->toAtomString())
178+
->orWhere("aired.to", null);
179+
});
180+
}
181+
return $query;
176182
}
177183

178184
public function filterByProducer(\Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder $query, string $value): \Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder
@@ -182,11 +188,21 @@ public function filterByProducer(\Laravel\Scout\Builder|\Illuminate\Database\Elo
182188
}
183189

184190
$producer = (int)$value;
185-
return $query->where(function (\Jenssegers\Mongodb\Eloquent\Builder $query) use ($producer) {
186-
return $query->where('producers.mal_id', $producer)
187-
->orWhere('licensors.mal_id', $producer)
188-
->orWhere('studios.mal_id', $producer);
189-
});
191+
if (is_scout_query_builder($query)) {
192+
$query = $query->where('(producers', [
193+
"=", $producer,
194+
" || licensors:=", $producer,
195+
" || studios:=", $producer,
196+
")"
197+
]);
198+
} else {
199+
$query = $query->where(function (\Jenssegers\Mongodb\Eloquent\Builder $query) use ($producer) {
200+
return $query->where('producers.mal_id', $producer)
201+
->orWhere('licensors.mal_id', $producer)
202+
->orWhere('studios.mal_id', $producer);
203+
});
204+
}
205+
return $query;
190206
}
191207

192208
/** @noinspection PhpUnused */
@@ -199,45 +215,74 @@ public function filterByProducers(\Laravel\Scout\Builder|\Illuminate\Database\El
199215
/* @var \Illuminate\Support\Collection $producers */
200216
$producers = collect(explode(',', $value))->filter();
201217

202-
return $query->where(function (\Jenssegers\Mongodb\Eloquent\Builder $query) use ($producers) {
203-
$firstProducer = (int)$producers->first();
204-
$query = $query->where('producers.mal_id', $firstProducer)
205-
->orWhere('licensors.mal_id', $firstProducer)
206-
->orWhere('studios.mal_id', $firstProducer);
207-
208-
foreach ($producers->skip(1) as $producer) {
209-
$producer = (int)$producer;
210-
$query = $query->orWhere('producers.mal_id', $producer)
211-
->orWhere('licensors.mal_id', $producer)
212-
->orWhere('studios.mal_id', $producer);
213-
}
218+
if (is_scout_query_builder($query)) {
219+
$producerFilterList = '[' . $producers->implode(', ') . ']';
220+
$query = $query->where('(producers', [
221+
'=', $producerFilterList,
222+
' || licensors:=', $producerFilterList,
223+
' || studios:=', $producerFilterList,
224+
')'
225+
]);
226+
} else {
227+
$query = $query->where(function (\Jenssegers\Mongodb\Eloquent\Builder $query) use ($producers) {
228+
$firstProducer = (int)$producers->first();
229+
$query = $query->where('producers.mal_id', $firstProducer)
230+
->orWhere('licensors.mal_id', $firstProducer)
231+
->orWhere('studios.mal_id', $firstProducer);
232+
233+
foreach ($producers->skip(1) as $producer) {
234+
$producer = (int)$producer;
235+
$query = $query->orWhere('producers.mal_id', $producer)
236+
->orWhere('licensors.mal_id', $producer)
237+
->orWhere('studios.mal_id', $producer);
238+
}
239+
240+
return $query;
241+
});
242+
}
214243

215-
return $query;
216-
});
244+
return $query;
217245
}
218246

219247
/** @noinspection PhpUnused */
220248
public function scopeExceptItemsWithAdultRating(\Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder $query): \Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder
221249
{
222-
return $query
223-
->where("demographics.mal_id", "!=", Constants::GENRE_ANIME_HENTAI)
224-
->where("demographics.mal_id", "!=", Constants::GENRE_ANIME_EROTICA)
225-
->where("rating", "!=", AnimeRatingEnum::rx()->label)
226-
->where("genres.mal_id", "!=", Constants::GENRE_ANIME_HENTAI);
250+
if (is_scout_query_builder($query)) {
251+
$query = $query
252+
->where("demographics", ["!=", Constants::GENRE_ANIME_HENTAI])
253+
->where("demographics", ["!=", Constants::GENRE_ANIME_EROTICA])
254+
->where("rating", ["!=", AnimeRatingEnum::rx()->label])
255+
->where("genres", ["!=", Constants::GENRE_ANIME_HENTAI]);
256+
} else {
257+
$query = $query
258+
->where("demographics.mal_id", "!=", Constants::GENRE_ANIME_HENTAI)
259+
->where("demographics.mal_id", "!=", Constants::GENRE_ANIME_EROTICA)
260+
->where("rating", "!=", AnimeRatingEnum::rx()->label)
261+
->where("genres.mal_id", "!=", Constants::GENRE_ANIME_HENTAI);
262+
}
263+
return $query;
227264
}
228265

229266
/** @noinspection PhpUnused */
230267
public function scopeExceptKidsItems(\Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder $query): \Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder
231268
{
232-
return $query
233-
->where("demographics.mal_id", "!=", Constants::GENRE_ANIME_KIDS);
269+
if (is_scout_query_builder($query)) {
270+
$query = $query->where("demographics", ["!=", Constants::GENRE_ANIME_KIDS]);
271+
} else {
272+
$query = $query->where("demographics.mal_id", "!=", Constants::GENRE_ANIME_KIDS);
273+
}
274+
return $query;
234275
}
235276

236277
/** @noinspection PhpUnused */
237278
public function scopeOnlyKidsItems(\Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder $query): \Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder
238279
{
239-
return $query
240-
->where("demographics.mal_id", Constants::GENRE_ANIME_KIDS);
280+
if (is_scout_query_builder($query)) {
281+
$query = $query->where("demographics", Constants::GENRE_ANIME_KIDS);
282+
} else {
283+
$query = $query->where("demographics.mal_id", Constants::GENRE_ANIME_KIDS);
284+
}
285+
return $query;
241286
}
242287

243288
public static function scrape(int $id)

app/Concerns/MediaFilters.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public function filterByMaxScore(\Laravel\Scout\Builder|\Illuminate\Database\Elo
1414
return $query;
1515
}
1616

17-
if ($query instanceof \Laravel\Scout\Builder) {
17+
if (is_scout_query_builder($query)) {
1818
if (array_key_exists("score", $query->wheres)) {
1919
$minScoreValue = $query->wheres["score"][1];
2020
$maxScoreValue = floatval($value);
@@ -33,7 +33,7 @@ public function filterByMinScore(\Laravel\Scout\Builder|\Illuminate\Database\Elo
3333
return $query;
3434
}
3535

36-
if ($query instanceof \Laravel\Scout\Builder) {
36+
if (is_scout_query_builder($query)) {
3737
if (array_key_exists("score", $query->wheres)) {
3838
$maxScoreValue = $query->wheres["score"][1];
3939
$minScoreValue = floatval($value);
@@ -64,7 +64,7 @@ public function filterByGenres(\Laravel\Scout\Builder|\Illuminate\Database\Eloqu
6464
}
6565
$genres = explode(',', $value);
6666

67-
if ($query instanceof \Laravel\Scout\Builder) {
67+
if (is_scout_query_builder($query)) {
6868
// https://typesense.org/docs/0.24.1/api/search.html#filter-parameters
6969
$genreFilterList = '[' . implode(', ', $genres) . ']';
7070
$query = $query->where('(genres', [
@@ -99,7 +99,7 @@ public function filterByGenresExclude(\Laravel\Scout\Builder|\Illuminate\Databas
9999
}
100100
$genres = explode(',', $value);
101101

102-
if ($query instanceof \Laravel\Scout\Builder) {
102+
if (is_scout_query_builder($query)) {
103103
// https://typesense.org/docs/0.24.1/api/search.html#filter-parameters
104104
$genreFilterList = '[' . implode(', ', $genres) . ']';
105105
$query = $query->where('(genres', [

app/Console/Commands/Indexer/IncrementalIndexer.php

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -177,14 +177,27 @@ private function fetchIds(string $mediaType, array $idsToFetch, int $delay, bool
177177

178178
public function handle(): int
179179
{
180+
$inputs = [
181+
'mediaType' => $this->argument('mediaType'),
182+
];
183+
184+
if ($this->option('failed'))
185+
{
186+
$inputs['failed'] = $this->option('failed');
187+
}
188+
189+
if ($this->option('resume'))
190+
{
191+
$inputs['resume'] = $this->option('resume');
192+
}
193+
194+
if ($this->option('delay'))
195+
{
196+
$inputs['delay'] = $this->option('delay');
197+
}
180198
// validate inputs
181199
$validator = Validator::make(
182-
[
183-
'mediaType' => $this->argument('mediaType'),
184-
'delay' => $this->option('delay'),
185-
'resume' => $this->option('resume'),
186-
'failed' => $this->option('failed')
187-
],
200+
$inputs,
188201
[
189202
'mediaType' => 'required|array',
190203
'mediaType.*' => 'in:anime,manga',

app/Manga.php

Lines changed: 62 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,13 @@ public function __construct(array $attributes = [])
6868
/** @noinspection PhpUnused */
6969
public function filterByStartDate(\Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder $query, CarbonImmutable $value): \Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder
7070
{
71-
return $query
72-
->where("published.from", ">=",
73-
$value->setTime(0, 0)
74-
->setTimezone(new \DateTimeZone('UTC'))
75-
->toAtomString()
76-
);
71+
$compareVal = $value->setTime(0, 0)->setTimezone(new \DateTimeZone('UTC'));
72+
if (is_scout_query_builder($query)) {
73+
$query = $query->where("start_date", [">=", $compareVal->getTimestamp()]);
74+
} else {
75+
$query = $query->where("published.from", ">=", $compareVal->toAtomString());
76+
}
77+
return $query;
7778
}
7879

7980
/** @noinspection PhpUnused */
@@ -85,12 +86,20 @@ public function filterByType(\Laravel\Scout\Builder|\Illuminate\Database\Eloquen
8586
/** @noinspection PhpUnused */
8687
public function filterByEndDate(\Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder $query, CarbonImmutable $value): \Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder
8788
{
88-
return $query
89-
->where("published.to", "<=",
90-
$value->setTime(0, 0)
91-
->setTimezone(new \DateTimeZone('UTC'))
92-
->toAtomString()
93-
);
89+
$compareVal = $value->setTime(0, 0)->setTimezone(new \DateTimeZone('UTC'));
90+
if (is_scout_query_builder($query)) {
91+
$query = $query->where("(end_date", [
92+
"<=", $compareVal->getTimestamp(),
93+
" || end_date:=", "null",
94+
")"
95+
]);
96+
} else {
97+
$query = $query->where(function (\Jenssegers\Mongodb\Eloquent\Builder $query) use ($compareVal) {
98+
return $query->where("published.to", "<=", $compareVal->toAtomString())
99+
->orWhere("published.to", null);
100+
});
101+
}
102+
return $query;
94103
}
95104

96105
public function filterByMagazine(\Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder $query, string $value): \Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder
@@ -100,8 +109,12 @@ public function filterByMagazine(\Laravel\Scout\Builder|\Illuminate\Database\Elo
100109
}
101110

102111
$magazine = (int)$value;
103-
return $query
104-
->where('serializations.mal_id', $magazine);
112+
if (is_scout_query_builder($query)) {
113+
$query = $query->where('magazines', $magazine);
114+
} else {
115+
$query = $query->where('serializations.mal_id', $magazine);
116+
}
117+
return $query;
105118
}
106119

107120
/** @noinspection PhpUnused */
@@ -112,33 +125,57 @@ public function filterByMagazines(\Laravel\Scout\Builder|\Illuminate\Database\El
112125
}
113126

114127
/** @var \Illuminate\Support\Collection $magazines */
115-
$magazines = collect(explode(',', $value))->filter()->map(fn($x) => (int)$x)->toArray();
128+
$magazines = collect(explode(',', $value))->filter()->map(fn($x) => (int)$x);
129+
130+
if (is_scout_query_builder($query)) {
131+
$magazineFilterList = '[' . $magazines->implode(', ') . ']';
132+
$query = $query->where('magazines', $magazineFilterList);
133+
} else {
134+
$query = $query->whereIn("serializations.mal_id", $magazines->toArray());
135+
}
116136

117-
return $query->whereIn("serializations.mal_id", $magazines);
137+
return $query;
118138
}
119139

120140
/** @noinspection PhpUnused */
121141
public function scopeExceptItemsWithAdultRating(\Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder $query): \Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder
122142
{
123-
return $query
124-
->where("type", "!=", MangaTypeEnum::doujin()->label)
125-
->where("demographics.mal_id", "!=", Constants::GENRE_MANGA_HENTAI)
126-
->where("demographics.mal_id", "!=", Constants::GENRE_MANGA_EROTICA)
127-
->where("genres.mal_id", "!=", Constants::GENRE_MANGA_HENTAI);
143+
if (is_scout_query_builder($query)) {
144+
$query = $query
145+
->where("type", ["!=", MangaTypeEnum::doujin()->label])
146+
->where("demographics", ["!=", Constants::GENRE_MANGA_HENTAI])
147+
->where("demographics", ["!=", Constants::GENRE_MANGA_EROTICA])
148+
->where("genres", ["!=", Constants::GENRE_MANGA_HENTAI]);
149+
} else {
150+
$query = $query
151+
->where("type", "!=", MangaTypeEnum::doujin()->label)
152+
->where("demographics.mal_id", "!=", Constants::GENRE_MANGA_HENTAI)
153+
->where("demographics.mal_id", "!=", Constants::GENRE_MANGA_EROTICA)
154+
->where("genres.mal_id", "!=", Constants::GENRE_MANGA_HENTAI);
155+
}
156+
return $query;
128157
}
129158

130159
/** @noinspection PhpUnused */
131160
public function scopeExceptKidsItems(\Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder $query): \Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder
132161
{
133-
return $query
134-
->where("demographics.mal_id", "!=", Constants::GENRE_MANGA_KIDS);
162+
if (is_scout_query_builder($query)) {
163+
$query = $query->where("demographics", ["!=", Constants::GENRE_MANGA_KIDS]);
164+
} else {
165+
$query = $query->where("demographics.mal_id", "!=", Constants::GENRE_MANGA_KIDS);
166+
}
167+
return $query;
135168
}
136169

137170
/** @noinspection PhpUnused */
138171
public function scopeOnlyKidsItems(\Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder $query): \Laravel\Scout\Builder|\Illuminate\Database\Eloquent\Builder
139172
{
140-
return $query
141-
->where("demographics.mal_id", Constants::GENRE_MANGA_KIDS);
173+
if (is_scout_query_builder($query)) {
174+
$query = $query->where("demographics", Constants::GENRE_MANGA_KIDS);
175+
} else {
176+
$query = $query->where("demographics.mal_id", Constants::GENRE_MANGA_KIDS);
177+
}
178+
return $query;
142179
}
143180

144181
public static function scrape(int $id)

0 commit comments

Comments
 (0)