Skip to content

Commit

Permalink
Merge branch 'master' into feature/ts-sync-height
Browse files Browse the repository at this point in the history
  • Loading branch information
notbakaneko committed Apr 24, 2024
2 parents 29e241a + 2dd1533 commit 3a0aef0
Show file tree
Hide file tree
Showing 53 changed files with 500 additions and 553 deletions.
1 change: 0 additions & 1 deletion .env.example
Expand Up @@ -8,7 +8,6 @@ APP_DEBUG=true
APP_KEY=
APP_LOG_LEVEL=debug
# APP_SENTRY=https://...
# APP_SENTRY_PUBLIC=https://...
# APP_SENTRY_ENVIRONMENT=

# DOCS_URL=
Expand Down
16 changes: 15 additions & 1 deletion app/Exceptions/Handler.php
Expand Up @@ -48,7 +48,7 @@ class Handler extends ExceptionHandler
public static function exceptionMessage($e)
{
if ($e instanceof ModelNotFoundException) {
return;
return static::modelNotFoundMessage($e);
}

if (static::statusCode($e) >= 500) {
Expand Down Expand Up @@ -90,6 +90,20 @@ private static function isOAuthSessionException(Throwable $e): bool
&& $e->getMessage() === 'Authorization request was not present in the session.';
}

private static function modelNotFoundMessage(ModelNotFoundException $e): string
{
$model = $e->getModel();
$modelTransKey = "models.name.{$model}";

$params = [
'model' => trans_exists($modelTransKey, $GLOBALS['cfg']['app']['fallback_locale'])
? osu_trans($modelTransKey)
: trim(strtr($model, ['App\Models\\' => '']), '\\'),
];

return osu_trans('models.not_found', $params);
}

private static function reportWithSentry(Throwable $e): void
{
$ref = log_error_sentry($e, ['http_code' => (string) static::statusCode($e)]);
Expand Down
4 changes: 2 additions & 2 deletions app/Http/Controllers/BeatmapsController.php
Expand Up @@ -75,7 +75,7 @@ private static function beatmapScores(string $id, ?string $scoreTransformerType,
'type' => $type,
'user' => $currentUser,
]);
$scores = $esFetch->all()->loadMissing(['beatmap', 'user.country']);
$scores = $esFetch->all()->loadMissing(['beatmap', 'user.country', 'processHistory']);
$userScore = $esFetch->userBest();
$scoreTransformer = new ScoreTransformer($scoreTransformerType);

Expand Down Expand Up @@ -494,7 +494,7 @@ public function userScoreAll($beatmapId, $userId)
'sort' => 'score_desc',
'user_id' => (int) $userId,
]);
$scores = (new ScoreSearch($params))->records();
$scores = (new ScoreSearch($params))->records()->loadMissing('processHistory');

return [
'scores' => json_collection($scores, new ScoreTransformer()),
Expand Down
16 changes: 13 additions & 3 deletions app/Http/Controllers/ScoresController.php
Expand Up @@ -91,12 +91,22 @@ public function download($rulesetOrSoloId, $id = null)

public function show($rulesetOrSoloId, $legacyId = null)
{
$scoreQuery = $legacyId === null
? SoloScore::whereKey($rulesetOrSoloId)
: SoloScore::where([
if ($legacyId === null) {
$scoreQuery = SoloScore::whereKey($rulesetOrSoloId);
} else {
// `SoloScore` tables can have records with `legacy_score_id = 0`
// which correspond to rows from `osu_scores_*` (non-high) tables.
// do not attempt to perform lookups for zero to avoid weird results.
// negative IDs should never occur (ID columns in score tables are all `bigint unsigned`).
if ($legacyId <= 0) {
abort(404, 'invalid score ID');
}

$scoreQuery = SoloScore::where([
'ruleset_id' => Ruleset::tryFromName($rulesetOrSoloId) ?? abort(404, 'unknown ruleset name'),
'legacy_score_id' => $legacyId,
]);
}
$score = $scoreQuery->whereHas('beatmap.beatmapset')->visibleUsers()->firstOrFail();

$userIncludes = array_map(function ($include) {
Expand Down
5 changes: 5 additions & 0 deletions app/Jobs/EsDocument.php
Expand Up @@ -33,6 +33,11 @@ public function __construct($model)
];
}

public function displayName()
{
return static::class." ({$this->modelMeta['class']} {$this->modelMeta['id']})";
}

/**
* Execute the job.
*
Expand Down
5 changes: 5 additions & 0 deletions app/Jobs/Notifications/BeatmapsetNotification.php
Expand Up @@ -28,6 +28,11 @@ public function __construct(Beatmapset $beatmapset, ?User $source = null)
$this->beatmapset = $beatmapset;
}

public function displayName()
{
return static::class." (Beatmapset {$this->beatmapset->getKey()})";
}

public function getDetails(): array
{
return [
Expand Down
5 changes: 5 additions & 0 deletions app/Jobs/RegenerateBeatmapsetCover.php
Expand Up @@ -42,6 +42,11 @@ public function __construct(Beatmapset $beatmapset, array $sizesToRegenerate = n
$this->sizesToRegenerate = $sizesToRegenerate;
}

public function displayName()
{
return static::class." (Beatmapset {$this->beatmapset->getKey()})";
}

/**
* Execute the job.
*
Expand Down
7 changes: 6 additions & 1 deletion app/Jobs/RemoveBeatmapsetBestScores.php
Expand Up @@ -18,7 +18,7 @@ class RemoveBeatmapsetBestScores implements ShouldQueue
{
use Queueable, SerializesModels;

public $timeout = 3600;
public $timeout = 36000;
public $beatmapset;
public $maxScoreIds = null;

Expand All @@ -36,6 +36,11 @@ public function __construct(Beatmapset $beatmapset)
}
}

public function displayName()
{
return static::class." (Beatmapset {$this->beatmapset->getKey()})";
}

/**
* Execute the job.
*
Expand Down
7 changes: 6 additions & 1 deletion app/Jobs/RemoveBeatmapsetSoloScores.php
Expand Up @@ -19,7 +19,7 @@ class RemoveBeatmapsetSoloScores implements ShouldQueue
{
use Queueable;

public $timeout = 3600;
public $timeout = 36000;

private int $beatmapsetId;
private int $maxScoreId;
Expand All @@ -37,6 +37,11 @@ public function __construct(Beatmapset $beatmapset)
$this->maxScoreId = Score::max('id') ?? 0;
}

public function displayName()
{
return static::class." (Beatmapset {$this->beatmapsetId})";
}

/**
* Execute the job.
*
Expand Down
2 changes: 2 additions & 0 deletions app/Libraries/Search/ArtistTrackSearchParams.php
Expand Up @@ -27,10 +27,12 @@ class ArtistTrackSearchParams extends SearchParams
public ?string $album;
public ?string $artist;
public ?array $bpm;
public ?array $bpmInput;
public bool $exclusiveOnly = false;
public ?string $genre;
public bool $isDefaultSort = false;
public ?array $length;
public ?array $lengthInput;
public string $sortField;
public string $sortOrder;

Expand Down
6 changes: 5 additions & 1 deletion app/Libraries/Search/ScoreSearchParams.php
Expand Up @@ -86,7 +86,11 @@ public static function showLegacyForUser(
return null;
}

return ($user->userProfileCustomization ?? UserProfileCustomization::DEFAULTS)['legacy_score_only']
$profileCustomization = $user !== null
? $user->profileCustomization()
: UserProfileCustomization::DEFAULTS;

return $profileCustomization['legacy_score_only']
? true
: null;
}
Expand Down
8 changes: 1 addition & 7 deletions app/Models/Chat/Channel.php
Expand Up @@ -456,14 +456,8 @@ public function receiveMessage(User $sender, ?string $content, bool $isAction =
throw new API\ExcessiveChatMessagesException(osu_trans('api.error.chat.limit_exceeded'));
}

$chatFilters = app('chat-filters')->all();

foreach ($chatFilters as $filter) {
$content = str_replace($filter->match, $filter->replacement, $content);
}

$message = new Message([
'content' => $content,
'content' => app('chat-filters')->filter($content),
'is_action' => $isAction,
'timestamp' => $now,
]);
Expand Down
6 changes: 6 additions & 0 deletions app/Models/Solo/Score.php
Expand Up @@ -149,6 +149,11 @@ public function user()
return $this->belongsTo(User::class, 'user_id');
}

public function processHistory()
{
return $this->hasOne(ScoreProcessHistory::class, 'score_id');
}

public function scopeDefault(Builder $query): Builder
{
return $query->whereHas('beatmap.beatmapset');
Expand Down Expand Up @@ -243,6 +248,7 @@ public function getAttribute($key)

'beatmap',
'performance',
'processHistory',
'reportedIn',
'user' => $this->getRelationValue($key),
};
Expand Down
25 changes: 25 additions & 0 deletions app/Models/Solo/ScoreProcessHistory.php
@@ -0,0 +1,25 @@
<?php

// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0.
// See the LICENCE file in the repository root for full licence text.

declare(strict_types=1);

namespace App\Models\Solo;

use App\Models\Model;

/**
* @property int $score_id
* @property int $processed_version
* @property \Carbon\Carbon $processed_at
*/
class ScoreProcessHistory extends Model
{
protected $table = 'score_process_history';

public function score()
{
return $this->belongsTo(Score::class, 'score_id');
}
}
2 changes: 1 addition & 1 deletion app/Models/Store/Order.php
Expand Up @@ -694,7 +694,7 @@ private function newOrderItem(array $params, Product $product)
$params['extra_data'] = ExtraDataSupporterTag::fromOrderItemParams($params, $this->user);
break;
// TODO: look at migrating to extra_data
case 'username-change':
case Product::USERNAME_CHANGE:
// ignore received cost
$params['cost'] = $this->user->usernameChangeCost();
break;
Expand Down
2 changes: 1 addition & 1 deletion app/Models/Store/OrderItem.php
Expand Up @@ -115,7 +115,7 @@ public function getCustomClassInstance()
{
// only one for now
if ($this->product->custom_class === 'username-change') {
return new ChangeUsername($this->order->user, $this->extra_info);
return new ChangeUsername($this->order->user, $this->extra_info ?? '');
}
}

Expand Down
2 changes: 2 additions & 0 deletions app/Models/Store/Product.php
Expand Up @@ -40,8 +40,10 @@
*/
class Product extends Model
{
const BUTTON_DISABLED = [self::SUPPORTER_TAG_NAME, self::USERNAME_CHANGE];
const REDIRECT_PLACEHOLDER = 'redirect';
const SUPPORTER_TAG_NAME = 'supporter-tag';
const USERNAME_CHANGE = 'username-change';

protected $primaryKey = 'product_id';

Expand Down
17 changes: 15 additions & 2 deletions app/Models/UserProfileCustomization.php
Expand Up @@ -5,6 +5,7 @@

namespace App\Models;

use App\Models\Solo\Score;
use Illuminate\Database\Eloquent\Casts\AsArrayObject;

/**
Expand All @@ -28,7 +29,7 @@ class UserProfileCustomization extends Model
'comments_sort' => Comment::DEFAULT_SORT,
'extras_order' => self::SECTIONS,
'forum_posts_show_deleted' => true,
'legacy_score_only' => true,
'legacy_score_only' => false,
'profile_cover_expanded' => true,
'user_list_filter' => self::USER_LIST['filters']['default'],
'user_list_sort' => self::USER_LIST['sorts']['default'],
Expand Down Expand Up @@ -195,7 +196,19 @@ public function setForumPostsShowDeletedAttribute($value)

public function getLegacyScoreOnlyAttribute(): bool
{
return $this->options['legacy_score_only'] ?? static::DEFAULTS['legacy_score_only'];
$option = $this->options['legacy_score_only'] ?? null;
if ($option === null) {
$lastScore = Score::where('user_id', $this->getKey())->last();
if ($lastScore === null) {
$option = static::DEFAULTS['legacy_score_only'];
} else {
$option = $lastScore->isLegacy();
$this->setOption('legacy_score_only', $option);
$this->save();
}
}

return $option;
}

public function setLegacyScoreOnlyAttribute($value): void
Expand Down
2 changes: 1 addition & 1 deletion app/Providers/AppServiceProvider.php
Expand Up @@ -64,7 +64,7 @@ public function boot()
$GLOBALS['cfg']['datadog-helper']['prefix_web'].'.queue.run',
1,
[
'job' => $event->job->resolveName(),
'job' => $event->job->payload()['data']['commandName'],
'queue' => $event->job->getQueue(),
]
);
Expand Down
17 changes: 10 additions & 7 deletions app/Singletons/ChatFilters.php
Expand Up @@ -7,19 +7,22 @@

use App\Models\ChatFilter;
use App\Traits\Memoizes;
use Illuminate\Database\Eloquent\Collection;

class ChatFilters
{
use Memoizes;

public function all()
public function filter(string $text): string
{
return $this->memoize(__FUNCTION__, fn () => $this->fetch());
}
$replacements = $this->memoize(__FUNCTION__, function () {
$ret = [];
foreach (ChatFilter::all() as $entry) {
$ret[$entry->match] = $entry->replacement;
}

protected function fetch(): Collection
{
return ChatFilter::all();
return $ret;
});

return strtr($text, $replacements);
}
}
9 changes: 0 additions & 9 deletions app/Transformers/Multiplayer/RoomTransformer.php
Expand Up @@ -21,7 +21,6 @@ class RoomTransformer extends TransformerAbstract
'playlist',
'playlist_item_stats',
'recent_participants',
'scores',
];

public function transform(Room $room)
Expand Down Expand Up @@ -94,12 +93,4 @@ public function includePlaylistItemStats(Room $room)
{
return $this->primitive($room->playlistItemStats());
}

public function includeScores(Room $room)
{
return $this->collection(
$room->scores()->completed()->get(),
new ScoreTransformer()
);
}
}
3 changes: 3 additions & 0 deletions app/Transformers/ScoreTransformer.php
Expand Up @@ -24,6 +24,7 @@ class ScoreTransformer extends TransformerAbstract
// warning: the preload is actually for PlaylistItemUserHighScore, not for Score
const MULTIPLAYER_BASE_PRELOAD = [
'scoreLink.score',
'scoreLink.score.processHistory',
'scoreLink.user.country',
];

Expand All @@ -35,6 +36,7 @@ class ScoreTransformer extends TransformerAbstract
const USER_PROFILE_INCLUDES_PRELOAD = [
'beatmap',
'beatmap.beatmapset',
'processHistory',
// it's for user profile so the user is already available
// 'user',
];
Expand Down Expand Up @@ -102,6 +104,7 @@ public function transformSolo(MultiplayerScoreLink|ScoreModel|SoloScore $score)
if ($score instanceof SoloScore) {
$extraAttributes['ranked'] = $score->ranked;
$extraAttributes['preserve'] = $score->preserve;
$extraAttributes['processed'] = $score->legacy_score_id !== null || $score->processHistory !== null;
}

$hasReplay = $score->has_replay;
Expand Down

0 comments on commit 3a0aef0

Please sign in to comment.