Skip to content

Commit

Permalink
Merge branch 'master' into room-management-lio
Browse files Browse the repository at this point in the history
  • Loading branch information
nanaya authored Jan 23, 2025
2 parents 5ba7ff3 + 83e7f98 commit 15e4794
Show file tree
Hide file tree
Showing 58 changed files with 1,592 additions and 875 deletions.
104 changes: 51 additions & 53 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ module.exports = {
'typescript-sort-keys',
],
rules: {
'@stylistic/member-delimiter-style': 'error',
'@stylistic/type-annotation-spacing': 'error',
'@typescript-eslint/array-type': [
'error',
{
Expand All @@ -41,20 +43,6 @@ module.exports = {
},
],
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/indent': [
'error',
2,
{
FunctionDeclaration: {
parameters: 'first',
},
FunctionExpression: {
parameters: 'first',
},
SwitchCase: 1,
},
],
'@typescript-eslint/member-delimiter-style': 'error',
'@typescript-eslint/member-ordering': [
'error',
{
Expand Down Expand Up @@ -101,17 +89,17 @@ module.exports = {
'@typescript-eslint/no-unsafe-member-access': 'warn',
'@typescript-eslint/no-unsafe-return': 'warn',
'@typescript-eslint/no-unused-expressions': 'error',
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', ignoreRestSiblings: true }],
'@typescript-eslint/no-unused-vars': [
'error', {
argsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
ignoreRestSiblings: true,
},
],
'@typescript-eslint/no-use-before-define': 'off',
'@typescript-eslint/object-curly-spacing': ['error', 'always'],
'@typescript-eslint/prefer-for-of': 'error',
'@typescript-eslint/prefer-function-type': 'error',
'@typescript-eslint/prefer-readonly': 'error',
'@typescript-eslint/quotes': [
'error',
'single',
{ avoidEscape: true },
],
'@typescript-eslint/restrict-template-expressions': [
'error',
{
Expand All @@ -121,21 +109,17 @@ module.exports = {
allowNumber: true,
},
],
'@typescript-eslint/semi': ['error', 'always'],
// TODO: make more strict.
'@typescript-eslint/strict-boolean-expressions': [
'error',
{
allowNullableBoolean: true,
},
],
'@typescript-eslint/type-annotation-spacing': 'error',
'@typescript-eslint/unified-signatures': 'error',
'dot-notation': 'off',
'no-invalid-this': 'off',
'no-shadow': 'off',
'object-curly-spacing': 'off',
quotes: 'off',
'react-hooks/exhaustive-deps': 'error',
'react/jsx-boolean-value': 'error',
'react/jsx-curly-spacing': 'error',
Expand Down Expand Up @@ -190,22 +174,57 @@ module.exports = {
sourceType: 'module',
},
plugins: [
'@stylistic',
'eslint-plugin-jsdoc',
'eslint-plugin-import',
],
rules: {
'@stylistic/arrow-parens': 'error',
'@stylistic/arrow-spacing': 'error',
'@stylistic/brace-style': 'error',
'@stylistic/comma-dangle': ['error', 'always-multiline'],
'@stylistic/eol-last': 'error',
'@stylistic/indent': [
'error',
2,
{
FunctionDeclaration: {
parameters: 'first',
},
FunctionExpression: {
parameters: 'first',
},
SwitchCase: 1,
},
],
'@stylistic/max-len': 'off',
'@stylistic/new-parens': 'error',
'@stylistic/no-multiple-empty-lines': 'error',
'@stylistic/no-trailing-spaces': 'error',
'@stylistic/object-curly-spacing': ['error', 'always'],
'@stylistic/quote-props': ['error', 'as-needed'],
'@stylistic/quotes': [
'error',
'single',
{ avoidEscape: true },
],
'@stylistic/semi': ['error', 'always'],
'@stylistic/space-before-function-paren': [
'error',
{
anonymous: 'never',
asyncArrow: 'always',
named: 'never',
},
],
'@stylistic/spaced-comment': 'error',
'arrow-body-style': 'error',
'arrow-parens': 'error',
'arrow-spacing': 'error',
'brace-style': 'error',
'comma-dangle': ['error', 'always-multiline'],
complexity: 'off',
curly: ['error', 'multi-line'],
'dot-notation': 'error',
'eol-last': 'error',
eqeqeq: ['error', 'smart'],
'guard-for-in': 'error',
'id-blacklist': [
'id-denylist': [
'error',
'any',
'Number',
Expand All @@ -221,43 +240,22 @@ module.exports = {
'import/order': ['error', { alphabetize: { order: 'asc' } }],
'jsdoc/check-alignment': 'error',
'jsdoc/check-indentation': 'error',
'jsdoc/newline-after-description': 'error',
'jsdoc/tag-lines': ['error', 'never', { startLines: 1 }],
'max-classes-per-file': 'error',
'max-len': 'off',
'new-parens': 'error',
'no-bitwise': 'error',
'no-caller': 'error',
'no-console': ['error', { allow: ['error', 'warn'] }],
'no-empty-function': 'error',
'no-eval': 'error',
'no-invalid-this': 'error',
'no-multiple-empty-lines': 'error',
'no-new-wrappers': 'error',
'no-shadow': ['error', { hoist: 'all' }],
'no-throw-literal': 'error',
'no-trailing-spaces': 'error',
'no-undef-init': 'error',
'no-unsafe-finally': 'error',
'object-curly-spacing': ['error', 'always'],
'object-shorthand': 'error',
'one-var': ['error', 'never'],
'quote-props': ['error', 'as-needed'],
quotes: [
'error',
'single',
{ avoidEscape: true },
],
radix: 'error',
semi: ['error', 'always'],
'sort-keys': ['error', 'asc', { caseSensitive: false }],
'space-before-function-paren': [
'error',
{
anonymous: 'never',
asyncArrow: 'always',
named: 'never',
},
],
'spaced-comment': 'error',
},
};
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ jobs:
- name: Install js dependencies
run: yarn --frozen-lockfile

- run: 'yarn lint --max-warnings 87 > /dev/null'
- run: 'yarn lint --max-warnings 86 > /dev/null'

- run: yarn pretty

Expand Down
57 changes: 32 additions & 25 deletions app/Models/ChangelogEntry.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ class ChangelogEntry extends Model

public static function convertLegacy($changelog)
{
$message = $changelog->message;
$splitMessage = static::splitMessage($message);
$title = $splitMessage[0];
$splitMessage = static::splitMessage($changelog->message);
$title = presence($splitMessage[0]);
$message = $splitMessage[1];

if ($title === null) {
$title = $splitMessage[1];
Expand All @@ -65,6 +65,13 @@ public static function convertLegacy($changelog)
]);
}

public static function getDisplayMessage(?string $origMessage): string
{
$split = static::splitMessage($origMessage);

return $split[1] === null ? '' : $split[0];
}

public static function guessCategory($data)
{
static $ignored = [
Expand Down Expand Up @@ -125,7 +132,7 @@ public static function importFromGithub($data)
'category' => static::guessCategory($data),
'created_at' => Carbon::parse($data['pull_request']['merged_at']),
'github_pull_request_id' => $data['pull_request']['number'],
'message' => $data['pull_request']['body'],
'message' => static::getDisplayMessage($data['pull_request']['body']),
'private' => static::isPrivate($data),
'title' => $data['pull_request']['title'],
'type' => static::guessType($data),
Expand Down Expand Up @@ -180,21 +187,30 @@ public static function placeholder()
]);
}

public static function splitMessage($message)
/**
* Returns array of message split by thematic break (`---`)
*
* The array length is always two.
* If the message is empty, both values will be null.
* If there's no thematic break, the second value will be null.
*/
public static function splitMessage($message): array
{
if (!present($message)) {
return [null, null];
}

static $separator = "\n\n---\n";
// prepended with \n\n just in case the message starts with ---\n (blank first part).
$message = "\n\n".trim(str_replace("\r\n", "\n", $message));
$splitPos = null_if_false(strpos($message, $separator)) ?? strlen($message);

return [
presence(trim(substr($message, 0, $splitPos))),
presence(trim(substr($message, $splitPos + strlen($separator)))),
];
// Surround with newlines to handle separator at the start/end.
$message = "\n\n".trim(strtr($message, ["\r\n" => "\n"]))."\n";
$splitPos = strpos($message, $separator);

return $splitPos === false
? [trim($message), null]
: [
trim(substr($message, 0, $splitPos)),
trim(substr($message, $splitPos + strlen($separator))),
];
}

public function builds()
Expand Down Expand Up @@ -253,21 +269,12 @@ public function githubUrl()
}
}

public function publicMessageHtml()
public function messageHtml(): ?string
{
return $this->memoize(__FUNCTION__, function () {
$message = $this->publicMessage();
$message = $this->message;

if ($message !== null) {
return markdown($message, 'changelog_entry');
}
});
}

public function publicMessage()
{
return $this->memoize(__FUNCTION__, function () {
return static::splitMessage($this->message)[1];
return present($message) ? markdown($message, 'changelog_entry') : null;
});
}
}
31 changes: 15 additions & 16 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -317,24 +317,23 @@ public function getAuthPassword()

public function usernameChangeCost()
{
$changesToDate = $this->usernameChangeHistory()
->whereIn('type', ['support', 'paid'])
->count();
$tier = min($this->usernameChangeHistory()->paid()->count(), 5);

switch ($changesToDate) {
case 0:
return 0;
case 1:
return 8;
case 2:
return 16;
case 3:
return 32;
case 4:
return 64;
default:
return 100;
if ($tier > 1) {
$lastChange = $this->usernameChangeHistory()->paid()->last()?->timestamp;
if ($lastChange !== null) {
$tier = max($tier - $lastChange->diffInYears(Carbon::now(), false), 1);
}
}

return match ($tier) {
0 => 0,
1 => 8,
2 => 16,
3 => 32,
4 => 64,
default => 100,
};
}

public function revertUsername($type = 'revert'): UsernameChangeHistory
Expand Down
5 changes: 5 additions & 0 deletions app/Models/UsernameChangeHistory.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ class UsernameChangeHistory extends Model
protected $table = 'osu_username_change_history';
protected $primaryKey = 'change_id';

public function scopePaid($query)
{
$query->whereIn('type', ['support', 'paid']); // changed by support counts as paid.
}

public function scopeVisible($query)
{
$query->whereIn('type', ['support', 'paid', 'admin']);
Expand Down
4 changes: 2 additions & 2 deletions app/Transformers/ChangelogEntryTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ public function includeGithubUser(ChangelogEntry $entry)

public function includeMessage(ChangelogEntry $entry)
{
return $this->primitive($entry->publicMessage());
return $this->primitive($entry->message);
}

public function includeMessageHtml(ChangelogEntry $entry)
{
return $this->primitive($entry->publicMessageHtml());
return $this->primitive($entry->messageHtml());
}
}
31 changes: 31 additions & 0 deletions database/factories/UsernameChangeHistoryFactory.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.

declare(strict_types=1);

namespace Database\Factories;

use App\Models\User;
use App\Models\UsernameChangeHistory;
use Carbon\Carbon;

class UsernameChangeHistoryFactory extends Factory
{
protected $model = UsernameChangeHistory::class;

public function definition(): array
{
return [
'timestamp' => Carbon::now(),
'type' => 'paid',
'user_id' => User::factory(),

// depend on user_id; the username will be incorrect when factorying multiple names at once,
// so they should be handled separately if realistic name changes are wanted.
'username' => fn (array $attr) => User::find($attr['user_id'])->username,
'username_last' => fn (array $attr) => "{$attr['username']}_prev",
];
}
}
Loading

0 comments on commit 15e4794

Please sign in to comment.