Compare commits
10 Commits
feature/ca
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 38e997cba2 | |||
|
|
792b203255 | ||
|
|
d6d5953a44 | ||
|
|
d0c4964caa | ||
|
|
9d33c64949 | ||
|
|
aadada2084 | ||
|
|
559124460d | ||
|
|
eb7f9e1e23 | ||
|
|
69829518a1 | ||
|
|
e0a7cbbfcb |
@ -141,6 +141,7 @@ data class ReplayData(
|
|||||||
val beatmap_count_sliders: Int?,
|
val beatmap_count_sliders: Int?,
|
||||||
val beatmap_count_spinners: Int?,
|
val beatmap_count_spinners: Int?,
|
||||||
val score: Int,
|
val score: Int,
|
||||||
|
val mods_bitwise: Int,
|
||||||
val mods: List<String>,
|
val mods: List<String>,
|
||||||
val rank: String?,
|
val rank: String?,
|
||||||
val ur: Double?,
|
val ur: Double?,
|
||||||
|
|||||||
@ -0,0 +1,22 @@
|
|||||||
|
package com.nisemoe.nise.controller
|
||||||
|
|
||||||
|
import org.springframework.http.ResponseEntity
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping
|
||||||
|
import org.springframework.web.bind.annotation.RestController
|
||||||
|
|
||||||
|
data class HealthResponse(
|
||||||
|
val healthy: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
|
val healthResponse = HealthResponse(
|
||||||
|
healthy = true,
|
||||||
|
)
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
class HealthController {
|
||||||
|
@GetMapping("/health")
|
||||||
|
fun healthCheck(): ResponseEntity<HealthResponse> {
|
||||||
|
return ResponseEntity.ok(healthResponse)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package com.nisemoe.nise.controller
|
||||||
|
|
||||||
|
import org.springframework.http.ResponseEntity
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping
|
||||||
|
import org.springframework.web.bind.annotation.RestController
|
||||||
|
|
||||||
|
data class VersionResponse(
|
||||||
|
val version: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
val versionResponse = VersionResponse(
|
||||||
|
version = "v20250213",
|
||||||
|
)
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
class VersionController {
|
||||||
|
@GetMapping("/version")
|
||||||
|
fun getVersion(): ResponseEntity<VersionResponse> = ResponseEntity.ok(versionResponse)
|
||||||
|
}
|
||||||
@ -177,6 +177,8 @@ class ScoreService(
|
|||||||
val hitDistribution = this.getHitDistribution(scoreId = result.get(SCORES.ID, Int::class.java))
|
val hitDistribution = this.getHitDistribution(scoreId = result.get(SCORES.ID, Int::class.java))
|
||||||
val charts = this.getCharts(result)
|
val charts = this.getCharts(result)
|
||||||
|
|
||||||
|
val mods = result.get(SCORES.MODS, Int::class.java)
|
||||||
|
|
||||||
val replayData = ReplayData(
|
val replayData = ReplayData(
|
||||||
replay_id = replayId,
|
replay_id = replayId,
|
||||||
user_id = result.get(SCORES.USER_ID, Int::class.java),
|
user_id = result.get(SCORES.USER_ID, Int::class.java),
|
||||||
@ -204,7 +206,8 @@ class ScoreService(
|
|||||||
ur = result.get(SCORES.UR, Double::class.java),
|
ur = result.get(SCORES.UR, Double::class.java),
|
||||||
adjusted_ur = result.get(SCORES.ADJUSTED_UR, Double::class.java),
|
adjusted_ur = result.get(SCORES.ADJUSTED_UR, Double::class.java),
|
||||||
score = result.get(SCORES.SCORE, Int::class.java),
|
score = result.get(SCORES.SCORE, Int::class.java),
|
||||||
mods = Mod.parseModCombination(result.get(SCORES.MODS, Int::class.java)),
|
mods_bitwise = mods,
|
||||||
|
mods = Mod.parseModCombination(mods),
|
||||||
rank = result.get(SCORES.RANK, String::class.java),
|
rank = result.get(SCORES.RANK, String::class.java),
|
||||||
snaps = result.get(SCORES.SNAPS, Int::class.java),
|
snaps = result.get(SCORES.SNAPS, Int::class.java),
|
||||||
hits = result.get(SCORES.EDGE_HITS, Int::class.java),
|
hits = result.get(SCORES.EDGE_HITS, Int::class.java),
|
||||||
@ -232,7 +235,7 @@ class ScoreService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getDefaultCondition(): Condition {
|
fun getDefaultCondition(): Condition {
|
||||||
return SCORES.UR.lessOrEqual(25.0)
|
return SCORES.UR.lessOrEqual(35.0)
|
||||||
.and(SCORES.IS_BANNED.eq(false))
|
.and(SCORES.IS_BANNED.eq(false))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -76,6 +76,8 @@ class UserScoreService(
|
|||||||
val hitDistribution = this.getHitDistribution(result.get(USER_SCORES.JUDGEMENTS, ByteArray::class.java))
|
val hitDistribution = this.getHitDistribution(result.get(USER_SCORES.JUDGEMENTS, ByteArray::class.java))
|
||||||
val charts = this.scoreService.getCharts(result)
|
val charts = this.scoreService.getCharts(result)
|
||||||
|
|
||||||
|
val mods = result.get(USER_SCORES.MODS, Int::class.java)
|
||||||
|
|
||||||
val replayData = ReplayData(
|
val replayData = ReplayData(
|
||||||
replay_id = result.get(USER_SCORES.ONLINE_SCORE_ID, Long::class.java),
|
replay_id = result.get(USER_SCORES.ONLINE_SCORE_ID, Long::class.java),
|
||||||
username = result.get(USER_SCORES.PLAYER_NAME, String::class.java),
|
username = result.get(USER_SCORES.PLAYER_NAME, String::class.java),
|
||||||
@ -100,7 +102,8 @@ class UserScoreService(
|
|||||||
ur = result.get(USER_SCORES.UR, Double::class.java),
|
ur = result.get(USER_SCORES.UR, Double::class.java),
|
||||||
adjusted_ur = result.get(USER_SCORES.ADJUSTED_UR, Double::class.java),
|
adjusted_ur = result.get(USER_SCORES.ADJUSTED_UR, Double::class.java),
|
||||||
score = result.get(USER_SCORES.TOTAL_SCORE, Int::class.java),
|
score = result.get(USER_SCORES.TOTAL_SCORE, Int::class.java),
|
||||||
mods = Mod.parseModCombination(result.get(USER_SCORES.MODS, Int::class.java)),
|
mods_bitwise = mods,
|
||||||
|
mods = Mod.parseModCombination(mods),
|
||||||
snaps = result.get(USER_SCORES.SNAPS, Int::class.java),
|
snaps = result.get(USER_SCORES.SNAPS, Int::class.java),
|
||||||
hits = result.get(USER_SCORES.EDGE_HITS, Int::class.java),
|
hits = result.get(USER_SCORES.EDGE_HITS, Int::class.java),
|
||||||
perfect = result.get(USER_SCORES.PERFECT, Boolean::class.java),
|
perfect = result.get(USER_SCORES.PERFECT, Boolean::class.java),
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
FROM nginx:1.27.0
|
FROM nginx:1.27.0-alpine
|
||||||
|
|
||||||
RUN rm -rf /usr/share/nginx/html/*
|
RUN rm -rf /usr/share/nginx/html/*
|
||||||
|
|
||||||
|
|||||||
@ -34,5 +34,5 @@
|
|||||||
|
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
<div class="text-center version">
|
<div class="text-center version">
|
||||||
v20241105
|
v20250213
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -25,26 +25,29 @@ export class TextReportService {
|
|||||||
report += `Profile: https://osu.ppy.sh/users/${userDetails.user_id}\n`;
|
report += `Profile: https://osu.ppy.sh/users/${userDetails.user_id}\n`;
|
||||||
|
|
||||||
for (const suspiciousScore of suspiciousScores) {
|
for (const suspiciousScore of suspiciousScores) {
|
||||||
report += `\n${this.getRelaxReport(suspiciousScore)}\n`;
|
report += `\n\n${this.getRelaxReport(suspiciousScore)}\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const similarReplay of similarReplays) {
|
for (const similarReplay of similarReplays) {
|
||||||
report += `\n${this.getStealingReport(similarReplay)}\n`;
|
report += `\n\n${this.getStealingReport(similarReplay)}\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
report += `\nGenerated on ${site} - [${userDetails.username} on ${site}](${environment.webUrl}/u/${userDetails.user_id})`;
|
report += `\n\nGenerated on ${site} - [${userDetails.username} on ${site}](${environment.webUrl}/u/${userDetails.user_id})`;
|
||||||
|
|
||||||
return report;
|
return report;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static getRelaxReport(suspiciousScore: SuspiciousScore): string {
|
private static getRelaxReport(suspiciousScore: SuspiciousScore): string {
|
||||||
return `[Replay on ${suspiciousScore.beatmap_title}](https://osu.ppy.sh/scores/osu/${suspiciousScore.replay_id})
|
return `[Replay on ${suspiciousScore.beatmap_title}](https://osu.ppy.sh/scores/osu/${suspiciousScore.replay_id})
|
||||||
|
|
||||||
cvUR: ${suspiciousScore.ur.toFixed(2)} according to Circleguard`;
|
cvUR: ${suspiciousScore.ur.toFixed(2)} according to Circleguard`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static getStealingReport(similarReplay: SimilarReplay): string {
|
private static getStealingReport(similarReplay: SimilarReplay): string {
|
||||||
return `[${similarReplay.username_2}'s replay (cheated)](https://osu.ppy.sh/scores/osu/${similarReplay.replay_id_2})
|
return `[${similarReplay.username_2}'s replay (cheated)](https://osu.ppy.sh/scores/osu/${similarReplay.replay_id_2})
|
||||||
|
|
||||||
[${similarReplay.username_1}'s replay (original)](https://osu.ppy.sh/scores/osu/${similarReplay.replay_id_1})
|
[${similarReplay.username_1}'s replay (original)](https://osu.ppy.sh/scores/osu/${similarReplay.replay_id_1})
|
||||||
|
|
||||||
${similarReplay.similarity.toFixed(2)} similarity according to Circleguard`;
|
${similarReplay.similarity.toFixed(2)} similarity according to Circleguard`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<div class="main term">
|
<div class="main term">
|
||||||
<h1><span class="board">/sus/</span> - Suspicious Scores</h1>
|
<h1><span class="board">/sus/</span> - Suspicious Scores</h1>
|
||||||
<div class="alert mb-2">
|
<div class="alert mb-2">
|
||||||
This includes all replays with <25 cvUR. Low values can indicate cheating but always manually review users and
|
This includes all replays with <35 cvUR. Low values can indicate cheating but always manually review users and
|
||||||
replays before making judgements.
|
replays before making judgements.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -24,7 +24,7 @@
|
|||||||
<input class="form-control" type="number" id="maxPP" [(ngModel)]="this.filterManager.filters.maxPP" (input)="filterScores()"
|
<input class="form-control" type="number" id="maxPP" [(ngModel)]="this.filterManager.filters.maxPP" (input)="filterScores()"
|
||||||
[readOnly]="this.isUrlFilters" [disabled]="this.isUrlFilters">
|
[readOnly]="this.isUrlFilters" [disabled]="this.isUrlFilters">
|
||||||
</p>
|
</p>
|
||||||
|
`
|
||||||
<!-- Min cvUR -->
|
<!-- Min cvUR -->
|
||||||
<p>
|
<p>
|
||||||
<label for="minUR" class="form-label">Min cvUR</label>
|
<label for="minUR" class="form-label">Min cvUR</label>
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
version: '3'
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
|
||||||
caddy-main:
|
caddy-main:
|
||||||
@ -11,10 +9,17 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "443:443"
|
- "443:443"
|
||||||
- "80:80"
|
- "80:80"
|
||||||
|
depends_on:
|
||||||
|
- nise-nginx
|
||||||
|
|
||||||
# Shared services which are used by others
|
# Shared services which are used by others
|
||||||
|
redis:
|
||||||
|
image: redis:alpine
|
||||||
|
container_name: redis
|
||||||
|
restart: always
|
||||||
|
|
||||||
postgres:
|
postgres:
|
||||||
image: groonga/pgroonga:3.1.6-alpine-15
|
image: postgres:alpine
|
||||||
container_name: postgres
|
container_name: postgres
|
||||||
restart: always
|
restart: always
|
||||||
environment:
|
environment:
|
||||||
@ -22,47 +27,6 @@ services:
|
|||||||
POSTGRES_PASSWORD: ${DB_PASS}
|
POSTGRES_PASSWORD: ${DB_PASS}
|
||||||
volumes:
|
volumes:
|
||||||
- postgres-data:/var/lib/postgresql/data
|
- postgres-data:/var/lib/postgresql/data
|
||||||
command: >
|
|
||||||
-c shared_buffers=6GB
|
|
||||||
-c effective_cache_size=12GB
|
|
||||||
-c work_mem=64MB
|
|
||||||
-c maintenance_work_mem=2GB
|
|
||||||
-c checkpoint_completion_target=0.9
|
|
||||||
-c checkpoint_timeout=15min
|
|
||||||
-c max_wal_size=2GB
|
|
||||||
-c wal_buffers=16MB
|
|
||||||
-c max_connections=100
|
|
||||||
-c max_worker_processes=8
|
|
||||||
-c max_parallel_workers_per_gather=4
|
|
||||||
-c max_parallel_workers=8
|
|
||||||
-c effective_io_concurrency=40
|
|
||||||
shm_size: '128mb'
|
|
||||||
|
|
||||||
redis:
|
|
||||||
image: redis:alpine
|
|
||||||
container_name: redis
|
|
||||||
restart: always
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
|
|
||||||
gitea:
|
|
||||||
image: gitea/gitea
|
|
||||||
container_name: gitea
|
|
||||||
restart: always
|
|
||||||
environment:
|
|
||||||
USER_UID: 1336
|
|
||||||
USER_GID: 1336
|
|
||||||
GITEA__database__DB_TYPE: postgres
|
|
||||||
GITEA__database__HOST: ${DB_HOST}:5432
|
|
||||||
GITEA__database__NAME: gitea
|
|
||||||
GITEA__database__USER: ${DB_USER}
|
|
||||||
GITEA__database__PASSWD: ${DB_PASS}
|
|
||||||
depends_on:
|
|
||||||
- postgres
|
|
||||||
- redis
|
|
||||||
volumes:
|
|
||||||
- ./gitea-data/app.ini:/data/gitea/conf/app.ini
|
|
||||||
- gitea-data:/data
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
@ -72,19 +36,31 @@ services:
|
|||||||
restart: always
|
restart: always
|
||||||
volumes:
|
volumes:
|
||||||
- ./nise-data/nginx.conf:/etc/nginx/nginx.conf:ro
|
- ./nise-data/nginx.conf:/etc/nginx/nginx.conf:ro
|
||||||
|
depends_on:
|
||||||
|
- nise-backend
|
||||||
|
- nise-frontend
|
||||||
|
|
||||||
|
nise-circleguard:
|
||||||
|
image: code.stedos.dev/stedos/nise-circleguard:latest
|
||||||
|
container_name: nise-circleguard
|
||||||
|
environment:
|
||||||
|
OSU_API_KEY: ${OSU_API_KEY}
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./nise-data/beatmaps:/app/dbs
|
||||||
|
|
||||||
nise-backend:
|
nise-backend:
|
||||||
image: git.nise.moe/nuff/nise-backend:latest
|
image: code.stedos.dev/stedos/nise-backend:latest
|
||||||
container_name: nise-backend
|
container_name: nise-backend
|
||||||
environment:
|
environment:
|
||||||
SPRING_PROFILES_ACTIVE: postgres,discord,import:scores,import:users,fix:scores
|
SPRING_PROFILES_ACTIVE: postgres,import:scores,import:users,fix:scores
|
||||||
# App configuration
|
# App configuration
|
||||||
OLD_SCORES_PAGE_SIZE: 1000
|
OLD_SCORES_PAGE_SIZE: 1000
|
||||||
# Postgres
|
# Postgres
|
||||||
POSTGRES_HOST: ${DB_HOST}
|
POSTGRES_HOST: ${DB_HOST}
|
||||||
POSTGRES_USER: ${DB_USER}
|
POSTGRES_USER: ${DB_USER}
|
||||||
POSTGRES_PASS: ${DB_PASS}
|
POSTGRES_PASS: ${DB_PASS}
|
||||||
POSTGRES_DB: nise
|
POSTGRES_DB: ${DB_NAME}
|
||||||
# redis
|
# redis
|
||||||
REDIS_DB: 4
|
REDIS_DB: 4
|
||||||
# Discord
|
# Discord
|
||||||
@ -94,69 +70,36 @@ services:
|
|||||||
OSU_API_KEY: ${OSU_API_KEY}
|
OSU_API_KEY: ${OSU_API_KEY}
|
||||||
OSU_CLIENT_ID: ${OSU_CLIENT_ID}
|
OSU_CLIENT_ID: ${OSU_CLIENT_ID}
|
||||||
OSU_CLIENT_SECRET: ${OSU_CLIENT_SECRET}
|
OSU_CLIENT_SECRET: ${OSU_CLIENT_SECRET}
|
||||||
OSU_CALLBACK: "https://nise.moe/api/login/oauth2/code/osu"
|
OSU_CALLBACK: "https://nise.stedos.dev/api/login/oauth2/code/osu"
|
||||||
# Metabase
|
# Metabase
|
||||||
METABASE_API_KEY: ${METABASE_API_KEY}
|
METABASE_API_KEY: ${METABASE_API_KEY}
|
||||||
# Internal API
|
# Internal API
|
||||||
CIRCLEGUARD_API_URL: http://nise-circleguard:5000
|
CIRCLEGUARD_API_URL: http://nise-circleguard:5000
|
||||||
# Auth
|
# Auth
|
||||||
ORIGIN: "https://nise.moe"
|
ORIGIN: "https://nise.stedos.dev"
|
||||||
REPLAY_ORIGIN: "https://replay.nise.moe"
|
REPLAY_ORIGIN: "https://replay.nise.moe"
|
||||||
COOKIE_SECURE: false
|
COOKIE_SECURE: false
|
||||||
BEATMAPS_PATH: "/app/dbs"
|
BEATMAPS_PATH: "/app/dbs"
|
||||||
|
# Replay cache
|
||||||
|
REPLAY_CACHE_ENABLED: ${REPLAY_CACHE_ENABLED}
|
||||||
|
REPLAY_CACHE_HOST: ${REPLAY_CACHE_HOST}
|
||||||
|
REPLAY_CACHE_PORT: ${REPLAY_CACHE_PORT}
|
||||||
|
REPLAY_CACHE_DB: ${REPLAY_CACHE_DB}
|
||||||
|
REPLAY_CACHE_USER: ${REPLAY_CACHE_USER}
|
||||||
|
REPLAY_CACHE_PASS: ${REPLAY_CACHE_PASS}
|
||||||
restart: always
|
restart: always
|
||||||
volumes:
|
volumes:
|
||||||
- ./nise-data/beatmaps:/app/dbs
|
- ./nise-data/beatmaps:/app/dbs
|
||||||
depends_on:
|
depends_on:
|
||||||
- postgres
|
- postgres
|
||||||
- redis
|
- redis
|
||||||
|
- nise-circleguard
|
||||||
|
|
||||||
nise-circleguard:
|
nise-frontend:
|
||||||
image: git.nise.moe/nuff/nise-circleguard:latest
|
image: code.stedos.dev/stedos/nise-frontend:latest
|
||||||
container_name: nise-circleguard
|
container_name: nise-frontend
|
||||||
environment:
|
|
||||||
OSU_API_KEY: ${OSU_API_KEY}
|
|
||||||
restart: always
|
|
||||||
volumes:
|
|
||||||
- ./nise-data/beatmaps:/app/dbs
|
|
||||||
|
|
||||||
nise-frontend2:
|
|
||||||
image: git.nise.moe/nuff/nise-frontend:latest
|
|
||||||
container_name: nise-frontend2
|
|
||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
nise-replay-viewer:
|
|
||||||
image: git.nise.moe/nuff/nise-replay-viewer:latest
|
|
||||||
container_name: nise-replay-viewer
|
|
||||||
restart: always
|
|
||||||
|
|
||||||
nise-discord:
|
|
||||||
image: git.nise.moe/nuff/nise-discord:latest
|
|
||||||
container_name: nise-discord
|
|
||||||
environment:
|
|
||||||
DISCORD_TOKEN: ${DISCORD_TOKEN}
|
|
||||||
REACTION_CHANNEL_ID: ${REACTION_CHANNEL_ID}
|
|
||||||
REACTION_EMOJI_ID: ${REACTION_EMOJI_ID}
|
|
||||||
restart: always
|
|
||||||
|
|
||||||
nise-metabase:
|
|
||||||
image: metabase/metabase:latest
|
|
||||||
container_name: nise-metabase
|
|
||||||
volumes:
|
|
||||||
- /dev/urandom:/dev/random:ro
|
|
||||||
environment:
|
|
||||||
MB_DB_TYPE: postgres
|
|
||||||
MB_DB_DBNAME: metabase
|
|
||||||
MB_DB_PORT: 5432
|
|
||||||
MB_DB_USER: ${DB_METABASE_USER}
|
|
||||||
MB_DB_PASS: ${DB_METABASE_PASS}
|
|
||||||
MB_DB_HOST: postgres
|
|
||||||
healthcheck:
|
|
||||||
test: curl --fail -I http://localhost:3000/api/health || exit 1
|
|
||||||
interval: 15s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 5
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
postgres-data:
|
postgres-data:
|
||||||
gitea-data:
|
|
||||||
Loading…
Reference in New Issue
Block a user