Skip to content

Commit f64a87c

Browse files
authored
Merge pull request #11126 from nanaya/view-count-replays
Limit replay file downloads count
2 parents 43079fb + 42d8388 commit f64a87c

File tree

8 files changed

+151
-85
lines changed

8 files changed

+151
-85
lines changed

Diff for: app/Http/Controllers/ScoresController.php

+26-16
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77

88
use App\Models\Score\Best\Model as ScoreBest;
99
use App\Models\Solo\Score as SoloScore;
10-
use App\Models\UserCountryHistory;
1110
use App\Transformers\ScoreTransformer;
1211
use App\Transformers\UserCompactTransformer;
13-
use Carbon\CarbonImmutable;
1412

1513
class ScoresController extends Controller
1614
{
15+
const REPLAY_DOWNLOAD_COUNT_INTERVAL = 86400; // 1 day
16+
1717
public function __construct()
1818
{
1919
parent::__construct();
@@ -52,20 +52,30 @@ public function download($rulesetOrSoloId, $id = null)
5252
abort(404);
5353
}
5454

55-
if (\Auth::user()->getKey() !== $score->user_id) {
56-
$score->user->statistics($score->getMode(), true)->increment('replay_popularity');
57-
58-
$month = CarbonImmutable::now();
59-
$currentMonth = UserCountryHistory::formatDate($month);
60-
61-
$score->user->replaysWatchedCounts()
62-
->firstOrCreate(['year_month' => $currentMonth], ['count' => 0])
63-
->incrementInstance('count');
64-
65-
if ($score instanceof ScoreBest) {
66-
$score->replayViewCount()
67-
->firstOrCreate([], ['play_count' => 0])
68-
->incrementInstance('play_count');
55+
$currentUser = \Auth::user();
56+
if (
57+
!$currentUser->isRestricted()
58+
&& $currentUser->getKey() !== $score->user_id
59+
&& ($currentUser->token()?->client->password_client ?? false)
60+
) {
61+
$countLock = \Cache::lock(
62+
"view:score_replay:{$score->getKey()}:{$currentUser->getKey()}",
63+
static::REPLAY_DOWNLOAD_COUNT_INTERVAL,
64+
);
65+
66+
if ($countLock->get()) {
67+
$score->user->statistics($score->getMode(), true)->increment('replay_popularity');
68+
69+
$currentMonth = format_month_column(new \DateTime());
70+
$score->user->replaysWatchedCounts()
71+
->firstOrCreate(['year_month' => $currentMonth], ['count' => 0])
72+
->incrementInstance('count');
73+
74+
if ($score instanceof ScoreBest) {
75+
$score->replayViewCount()
76+
->firstOrCreate([], ['play_count' => 0])
77+
->incrementInstance('play_count');
78+
}
6979
}
7080
}
7181

Diff for: app/Libraries/User/CountryChangeTarget.php

+2-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
use App\Models\Tournament;
1111
use App\Models\TournamentRegistration;
1212
use App\Models\User;
13-
use App\Models\UserCountryHistory;
1413
use Carbon\CarbonImmutable;
1514

1615
class CountryChangeTarget
@@ -38,8 +37,8 @@ public static function get(User $user): ?string
3837
->userCountryHistory()
3938
->whereBetween('year_month', [
4039
// one year maximum range. Offset by 1 because the range is inclusive
41-
UserCountryHistory::formatDate($until->subMonths(11)),
42-
UserCountryHistory::formatDate($until),
40+
format_month_column($until->subMonths(11)),
41+
format_month_column($until),
4342
])->distinct()
4443
->orderBy('year_month', 'DESC')
4544
->limit($minMonths)

Diff for: app/Models/Solo/Score.php

+12-3
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
use App\Models\ScoreToken;
2020
use App\Models\Traits;
2121
use App\Models\User;
22+
use Illuminate\Contracts\Filesystem\Filesystem;
2223
use Illuminate\Database\Eloquent\Builder;
2324
use LaravelRedis;
24-
use Storage;
2525

2626
/**
2727
* @property float $accuracy
@@ -127,6 +127,16 @@ public static function extractParams(array $rawParams, ScoreToken|MultiplayerSco
127127
return $params;
128128
}
129129

130+
public static function replayFileDiskName(): string
131+
{
132+
return "{$GLOBALS['cfg']['osu']['score_replays']['storage']}-solo-replay";
133+
}
134+
135+
public static function replayFileStorage(): Filesystem
136+
{
137+
return \Storage::disk(static::replayFileDiskName());
138+
}
139+
130140
public function beatmap()
131141
{
132142
return $this->belongsTo(Beatmap::class, 'beatmap_id');
@@ -253,8 +263,7 @@ public function getMode(): string
253263

254264
public function getReplayFile(): ?string
255265
{
256-
return Storage::disk($GLOBALS['cfg']['osu']['score_replays']['storage'].'-solo-replay')
257-
->get($this->getKey());
266+
return static::replayFileStorage()->get($this->getKey());
258267
}
259268

260269
public function isLegacy(): bool

Diff for: app/Models/UserCountryHistory.php

+1-6
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,6 @@ class UserCountryHistory extends Model
2828
protected $primaryKeys = ['user_id', 'year_month', 'country_acronym'];
2929
protected $table = 'user_country_history';
3030

31-
public static function formatDate(\DateTimeInterface $date): string
32-
{
33-
return $date->format('ym');
34-
}
35-
3631
public function country(): BelongsTo
3732
{
3833
return $this->belongsTo(Country::class, 'country_acronym');
@@ -46,7 +41,7 @@ public function user(): BelongsTo
4641
public function setYearMonthAttribute(\DateTimeInterface|string $value): void
4742
{
4843
$this->attributes['year_month'] = $value instanceof \DateTimeInterface
49-
? static::formatDate($value)
44+
? format_month_column($value)
5045
: $value;
5146
}
5247
}

Diff for: app/helpers.php

+5
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,11 @@ function flag_url($countryCode)
395395
return "/assets/images/flags/{$baseFileName}.svg";
396396
}
397397

398+
function format_month_column(\DateTimeInterface $date): string
399+
{
400+
return $date->format('ym');
401+
}
402+
398403
function format_rank(?int $rank): string
399404
{
400405
return $rank !== null ? '#'.i18n_number_format($rank) : '-';

Diff for: database/factories/Solo/ScoreFactory.php

+9
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,15 @@ public function withData(array ...$overrides): static
4545
]);
4646
}
4747

48+
public function withReplay(): static
49+
{
50+
return $this
51+
->state(['has_replay' => true])
52+
->afterCreating(function ($score) {
53+
Score::replayFileStorage()->put($score->getKey(), 'placeholder replay file');
54+
});
55+
}
56+
4857
private function makeData(?array $overrides = null): callable
4958
{
5059
return fn (array $attr): array => array_map(

0 commit comments

Comments
 (0)