Skip to content

Commit

Permalink
Merge branch 'master' into post-preview-ts
Browse files Browse the repository at this point in the history
  • Loading branch information
notbakaneko authored Dec 16, 2024
2 parents ffa709b + 9c9b766 commit 4ab8fc2
Show file tree
Hide file tree
Showing 540 changed files with 6,097 additions and 2,338 deletions.
21 changes: 6 additions & 15 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ CLIENT_CHECK_VERSION=false
# SEARCH_MINIMUM_LENGTH=2

# BEATMAPS_DIFFICULTY_CACHE_SERVER_URL=http://localhost:5001
# BEATMAPS_OWNERS_MAX=10
# BEATMAPSET_DISCUSSION_KUDOSU_PER_USER=10
# BEATMAPSET_GUEST_ADVANCED_SEARCH=0
# BEATMAPSET_MAXIMUM_DISQUALIFIED_RANK_PENALTY_DAYS=7
Expand All @@ -189,21 +190,6 @@ CLIENT_CHECK_VERSION=false
# ES_CLIENT_CONNECT_TIMEOUT=0.5
# ES_SEARCH_TIMEOUT=5s

# TOURNAMENT_BANNER_CURRENT_ID=
# Image path/url for tournament supporter banner.
# Will be appended with country abbreviation and `.jpg`. `@2x` version is also required (prepended before `.jpg`).
# Example:
# prefix: https://assets.ppy.sh/tournament-banners/official/twc2018_
# image path: https://assets.ppy.sh/tournament-banners/official/twc2018_JP.jpg
# image path @2x: https://assets.ppy.sh/tournament-banners/official/[email protected]
# TOURNAMENT_BANNER_CURRENT_PREFIX=

# TOURNAMENT_BANNER_PREVIOUS_ID=
# Same as `_CURRENT_PREFIX`.
# TOURNAMENT_BANNER_PREVIOUS_PREFIX=
# Winning country code
# TOURNAMENT_BANNER_PREVIOUS_WINNER_ID=

# {prefix}{filename}.png with {filename} the achievement slug as stored in database.
# USER_ACHIEVEMENT_ICON_PREFIX=https://assets.ppy.sh/user-achievements/

Expand Down Expand Up @@ -244,6 +230,7 @@ CLIENT_CHECK_VERSION=false
# USER_PROFILE_SCORES_NOTICE=

# MULTIPLAYER_MAX_ATTEMPTS_LIMIT=128
# MULTIPLAYER_ROOM_CLOSE_GRACE_PERIOD_MINUTES=5

# NOTIFICATION_QUEUE=notification
# NOTIFICATION_REDIS_HOST=127.0.0.1
Expand Down Expand Up @@ -303,6 +290,7 @@ CLIENT_CHECK_VERSION=false
# SCORES_EXPERIMENTAL_RANK_AS_EXTRA=false
# SCORES_PROCESSING_QUEUE=osu-queue:score-statistics
# SCORES_SUBMISSION_ENABLED=1
# SCORE_INDEX_MAX_ID_DISTANCE=10_000_000

# BANCHO_BOT_USER_ID=

Expand Down Expand Up @@ -332,3 +320,6 @@ CLIENT_CHECK_VERSION=false

# COUNTRY_PERFORMANCE_USER_COUNT=1000
# COUNTRY_PERFORMANCE_WEIGHTING_FACTOR=0.99

# TAGS_CACHE_DURATION=60
# BEATMAP_TAGS_CACHE_DURATION=60
11 changes: 11 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,17 @@ jobs:
key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }}
restore-keys: ${{ runner.os }}-composer-

- name: Get current date
id: current-date
run: echo "today=$(date '+%Y%m%d')" >> "$GITHUB_OUTPUT"

- name: Cache ip2asn
uses: actions/cache@v4
with:
path: database/ip2asn/
key: ip2asn-${{ steps.current-date.outputs.today }}
restore-keys: ip2asn-

- run: ./build.sh

- name: Setup indices
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.development
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ COPY chromium /usr/bin/

WORKDIR /app

RUN groupadd osuweb && useradd -g osuweb osuweb
RUN groupadd osuweb && useradd -g osuweb -d /app/.docker osuweb

ENTRYPOINT ["/app/docker/development/entrypoint.sh"]
CMD ["octane"]
31 changes: 31 additions & 0 deletions app/Console/Commands/BeatmapsMigrateOwners.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

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

namespace App\Console\Commands;

use App\Models\Beatmap;
use Illuminate\Console\Command;

class BeatmapsMigrateOwners extends Command
{
protected $signature = 'beatmaps:migrate-owners';

protected $description = 'Migrates beatmap owners to new table.';

public function handle()
{
$progress = $this->output->createProgressBar();

Beatmap::chunkById(1000, function ($beatmaps) use ($progress) {
foreach ($beatmaps as $beatmap) {
$beatmap->beatmapOwners()->firstOrCreate(['user_id' => $beatmap->user_id]);
$progress->advance();
}
});

$progress->finish();
$this->line('');
}
}
12 changes: 0 additions & 12 deletions app/Http/Controllers/BeatmapDiscussionsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,18 +117,6 @@ public function index()
return ext_view('beatmap_discussions.index', compact('json', 'search', 'paginator'));
}

public function mediaUrl()
{
$url = presence(get_string(request('url')));

if (!isset($url)) {
return response('Missing url parameter', 422);
}

// Tell browser not to request url for a while.
return redirect(proxy_media($url))->header('Cache-Control', 'max-age=600');
}

public function restore($id)
{
$discussion = BeatmapDiscussion::whereNotNull('deleted_at')->findOrFail($id);
Expand Down
71 changes: 71 additions & 0 deletions app/Http/Controllers/BeatmapTagsController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

// Copyright (c) ppy Pty Ltd <[email protected]>. 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\Http\Controllers;

use App\Models\Beatmap;
use App\Models\BeatmapTag;
use App\Models\Tag;

class BeatmapTagsController extends Controller
{
public function __construct()
{
parent::__construct();

$this->middleware('auth', [
'only' => [
'store',
'destroy',
],
]);

$this->middleware('require-scopes:public', ['only' => 'index']);
}

public function index($beatmapId)
{
$topBeatmapTags = cache_remember_mutexed(
"beatmap_tags:{$beatmapId}",
$GLOBALS['cfg']['osu']['tags']['beatmap_tags_cache_duration'],
[],
fn () => Tag::topTags($beatmapId),
);

return [
'beatmap_tags' => $topBeatmapTags,
];
}

public function destroy($beatmapId, $tagId)
{
BeatmapTag::where('tag_id', $tagId)
->where('beatmap_id', $beatmapId)
->where('user_id', \Auth::user()->getKey())
->delete();

return response()->noContent();
}

public function store($beatmapId)
{
$tagId = get_int(request('tag_id'));

$beatmap = Beatmap::findOrFail($beatmapId);
priv_check('BeatmapTagStore', $beatmap)->ensureCan();

$tag = Tag::findOrFail($tagId);

$user = \Auth::user();

$tag
->beatmapTags()
->firstOrCreate(['beatmap_id' => $beatmapId, 'user_id' => $user->getKey()]);

return response()->noContent();
}
}
30 changes: 6 additions & 24 deletions app/Http/Controllers/BeatmapsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@

use App\Enums\Ruleset;
use App\Exceptions\InvariantException;
use App\Jobs\Notifications\BeatmapOwnerChange;
use App\Libraries\BeatmapDifficultyAttributes;
use App\Libraries\Beatmapset\ChangeBeatmapOwners;
use App\Libraries\Score\BeatmapScores;
use App\Libraries\Score\UserRank;
use App\Libraries\Search\ScoreSearch;
use App\Libraries\Search\ScoreSearchParams;
use App\Models\Beatmap;
use App\Models\BeatmapsetEvent;
use App\Models\User;
use App\Transformers\BeatmapTransformer;
use App\Transformers\ScoreTransformer;
Expand All @@ -25,7 +24,7 @@
class BeatmapsController extends Controller
{
const DEFAULT_API_INCLUDES = ['beatmapset.ratings', 'failtimes', 'max_combo'];
const DEFAULT_SCORE_INCLUDES = ['user', 'user.country', 'user.cover'];
const DEFAULT_SCORE_INCLUDES = ['user', 'user.country', 'user.cover', 'user.team'];

public function __construct()
{
Expand Down Expand Up @@ -75,7 +74,7 @@ private static function beatmapScores(string $id, ?string $scoreTransformerType,
'type' => $type,
'user' => $currentUser,
]);
$scores = $esFetch->all()->loadMissing(['beatmap', 'user.country', 'processHistory']);
$scores = $esFetch->all()->loadMissing(['beatmap', 'user.country', 'user.team', 'processHistory']);
$userScore = $esFetch->userBest();
$scoreTransformer = new ScoreTransformer($scoreTransformerType);

Expand Down Expand Up @@ -381,26 +380,9 @@ public function soloScores($id)
public function updateOwner($id)
{
$beatmap = Beatmap::findOrFail($id);
$currentUser = auth()->user();
$newUserIds = get_arr(request('user_ids'), 'get_int');

priv_check('BeatmapUpdateOwner', $beatmap->beatmapset)->ensureCan();

$newUserId = get_int(request('beatmap.user_id'));

$beatmap->getConnection()->transaction(function () use ($beatmap, $currentUser, $newUserId) {
$beatmap->setOwner($newUserId);

BeatmapsetEvent::log(BeatmapsetEvent::BEATMAP_OWNER_CHANGE, $currentUser, $beatmap->beatmapset, [
'beatmap_id' => $beatmap->getKey(),
'beatmap_version' => $beatmap->version,
'new_user_id' => $beatmap->user_id,
'new_user_username' => $beatmap->user->username,
])->saveOrExplode();
});

if ($beatmap->user_id !== $currentUser->getKey()) {
(new BeatmapOwnerChange($beatmap, $currentUser))->dispatch();
}
(new ChangeBeatmapOwners($beatmap, $newUserIds ?? [], \Auth::user()))->handle();

return $beatmap->beatmapset->defaultDiscussionJson();
}
Expand Down Expand Up @@ -459,7 +441,7 @@ public function userScore($beatmapId, $userId)
'score' => json_item(
$score,
new ScoreTransformer(),
['beatmap', ...static::DEFAULT_SCORE_INCLUDES]
['beatmap.owners', ...static::DEFAULT_SCORE_INCLUDES]
),
];
}
Expand Down
3 changes: 3 additions & 0 deletions app/Http/Controllers/BeatmapsetsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ private function showJson($beatmapset)
"{$beatmapRelation}.baseDifficultyRatings",
"{$beatmapRelation}.baseMaxCombo",
"{$beatmapRelation}.failtimes",
"{$beatmapRelation}.beatmapOwners.user",
'genre',
'language',
'user',
Expand All @@ -402,8 +403,10 @@ private function showJson($beatmapset)
'beatmaps',
'beatmaps.failtimes',
'beatmaps.max_combo',
'beatmaps.owners',
'converts',
'converts.failtimes',
'converts.owners',
'current_nominations',
'current_user_attributes',
'description',
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Controllers/Chat/Channels/MessagesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public function index($channelId)
'until:int',
], ['null_missing' => true]);

$limit = clamp($limit ?? 50, 1, 50);
$limit = \Number::clamp($limit ?? 50, 1, 50);
$user = auth()->user();

$channel = Channel::findOrFail($channelId);
Expand Down
47 changes: 26 additions & 21 deletions app/Http/Controllers/Chat/ChatController.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,39 +89,44 @@ public function ack()
* @bodyParam uuid string client-side message identifier which will be sent back in response and websocket json. Example: some-uuid-string
*
* @response {
* "channel": [
* {
* "channel_id": 1234,
* "current_user_attributes": {
* "can_message": true,
* "can_message_error": null,
* "last_read_id": 9150005005
* },
* "name": "peppy",
* "description": "",
* "type": "PM",
* "last_read_id": 9150005005,
* "last_message_id": 9150005005
* }
* ],
* "channel": {
* "channel_id": 1234,
* "description": "",
* "icon": "https://a.ppy.sh/102?1500537068"
* "message_length_limit": 450,
* "moderated": false,
* "name": "peppy",
* "type": "PM",
* "uuid": null,
* "last_message_id": 9150005005,
* "users": [
* 101,
* 102
* ]
* },
* "message": {
* "message_id": 9150005005,
* "sender_id": 102,
* "channel_id": 1234,
* "timestamp": "2018-07-06T06:33:42+00:00",
* "content": "i can haz featured artist plz?",
* "is_action": false,
* "message_id": 9150005005,
* "sender_id": 102,
* "timestamp": "2024-12-23T01:23:45+00:00",
* "type": "plain",
* "uuid": "some-uuid-string",
* "sender": {
* "id": 102,
* "username": "nekodex",
* "profile_colour": "#333333",
* "avatar_url": "https://a.ppy.sh/102?1500537068",
* "country_code": "AU",
* "default_group": "default",
* "id": 102,
* "is_active": true,
* "is_bot": false,
* "is_deleted": false,
* "is_online": true,
* "is_supporter": true
* "last_visit": "2024-12-23T01:23:45+00:00",
* "pm_friends_only": false,
* "profile_colour": "#333333",
* "username": "nekodex",
* }
* },
* "new_channel_id": 1234,
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Controllers/ContestEntriesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public function judgeVote($id)

foreach ($entry->contest->scoringCategories as $category) {
$score = $scoresByCategoryId[$category->getKey()];
$value = clamp($score['value'], 0, $category->max_value);
$value = \Number::clamp($score['value'], 0, $category->max_value);

$vote->scores()->firstOrNew([
'contest_judge_vote_id' => $vote->getKey(),
Expand Down
Loading

0 comments on commit 4ab8fc2

Please sign in to comment.