rhythia-api 125.0.0 → 127.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api/approveMap.ts +5 -1
- package/api/createBeatmap.ts +11 -2
- package/api/getBadgedUsers.ts +70 -0
- package/api/getBeatmaps.ts +3 -0
- package/api/nominateMap.ts +5 -1
- package/api/submitScore.ts +19 -0
- package/index.ts +5 -0
- package/package.json +2 -1
package/api/approveMap.ts
CHANGED
|
@@ -42,7 +42,7 @@ export async function handler(data: (typeof Schema)["input"]["_type"]) {
|
|
|
42
42
|
|
|
43
43
|
const { data: mapData, error } = await supabase
|
|
44
44
|
.from("beatmapPages")
|
|
45
|
-
.select("id,nominations")
|
|
45
|
+
.select("id,nominations,owner")
|
|
46
46
|
.eq("id", data.mapId)
|
|
47
47
|
.single();
|
|
48
48
|
|
|
@@ -50,6 +50,10 @@ export async function handler(data: (typeof Schema)["input"]["_type"]) {
|
|
|
50
50
|
return NextResponse.json({ error: "Bad map" });
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
if (mapData.owner == queryUserData.id) {
|
|
54
|
+
return NextResponse.json({ error: "Can't approve own map" });
|
|
55
|
+
}
|
|
56
|
+
|
|
53
57
|
if ((mapData.nominations as number[])!.length < 2) {
|
|
54
58
|
return NextResponse.json({
|
|
55
59
|
error: "Maps can get approved only if they have 2 approvals",
|
package/api/createBeatmap.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { SSPMParser } from "../utils/star-calc/sspmParser";
|
|
|
5
5
|
import { supabase } from "../utils/supabase";
|
|
6
6
|
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
|
|
7
7
|
import { rateMap } from "../utils/star-calc";
|
|
8
|
-
|
|
8
|
+
import sharp from "sharp";
|
|
9
9
|
const s3Client = new S3Client({
|
|
10
10
|
region: "auto",
|
|
11
11
|
endpoint: "https://s3.eu-central-003.backblazeb2.com",
|
|
@@ -52,10 +52,19 @@ export async function handler({
|
|
|
52
52
|
sum.update(Buffer.from(bytes));
|
|
53
53
|
const digested = sum.digest("hex");
|
|
54
54
|
const imgkey = `beatmap-img-${Date.now()}-${digested}`;
|
|
55
|
+
|
|
56
|
+
let buffer = Buffer.from([]);
|
|
57
|
+
try {
|
|
58
|
+
buffer = await sharp(parsedData.cover)
|
|
59
|
+
.resize(250)
|
|
60
|
+
.jpeg({ mozjpeg: true })
|
|
61
|
+
.toBuffer();
|
|
62
|
+
} catch (error) {}
|
|
63
|
+
|
|
55
64
|
const command = new PutObjectCommand({
|
|
56
65
|
Bucket: "rhthia-avatars",
|
|
57
66
|
Key: imgkey,
|
|
58
|
-
Body:
|
|
67
|
+
Body: buffer,
|
|
59
68
|
ContentType: "image/jpeg",
|
|
60
69
|
});
|
|
61
70
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import z from "zod";
|
|
3
|
+
import { getUser, protectedApi } from "../utils/requestUtils";
|
|
4
|
+
import { supabase } from "../utils/supabase";
|
|
5
|
+
|
|
6
|
+
export const Schema = {
|
|
7
|
+
input: z.strictObject({
|
|
8
|
+
badge: z.string(),
|
|
9
|
+
}),
|
|
10
|
+
output: z.object({
|
|
11
|
+
error: z.string().optional(),
|
|
12
|
+
total: z.number(),
|
|
13
|
+
leaderboard: z
|
|
14
|
+
.array(
|
|
15
|
+
z.object({
|
|
16
|
+
flag: z.string().nullable(),
|
|
17
|
+
id: z.number(),
|
|
18
|
+
username: z.string().nullable(),
|
|
19
|
+
play_count: z.number().nullable(),
|
|
20
|
+
skill_points: z.number().nullable(),
|
|
21
|
+
total_score: z.number().nullable(),
|
|
22
|
+
})
|
|
23
|
+
)
|
|
24
|
+
.optional(),
|
|
25
|
+
}),
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export async function POST(request: Request): Promise<NextResponse> {
|
|
29
|
+
return protectedApi({
|
|
30
|
+
request,
|
|
31
|
+
schema: Schema,
|
|
32
|
+
authorization: () => {},
|
|
33
|
+
activity: handler,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function handler(
|
|
38
|
+
data: (typeof Schema)["input"]["_type"]
|
|
39
|
+
): Promise<NextResponse<(typeof Schema)["output"]["_type"]>> {
|
|
40
|
+
const result = await getLeaderboard(data.badge);
|
|
41
|
+
return NextResponse.json(result);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function getLeaderboard(badge: string) {
|
|
45
|
+
const countQuery = await supabase
|
|
46
|
+
.from("profiles")
|
|
47
|
+
.select("ban", { count: "exact", head: true })
|
|
48
|
+
.neq("ban", "excluded")
|
|
49
|
+
.ilike("badges", `%${badge}%`);
|
|
50
|
+
|
|
51
|
+
let { data: queryData, error } = await supabase
|
|
52
|
+
.from("profiles")
|
|
53
|
+
.select("*")
|
|
54
|
+
.neq("ban", "excluded")
|
|
55
|
+
.ilike("badges", `%${badge}%`)
|
|
56
|
+
.order("skill_points", { ascending: false })
|
|
57
|
+
.range(0, 200);
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
total: countQuery.count || 0,
|
|
61
|
+
leaderboard: queryData?.map((user) => ({
|
|
62
|
+
flag: user.flag,
|
|
63
|
+
id: user.id,
|
|
64
|
+
play_count: user.play_count,
|
|
65
|
+
skill_points: user.skill_points,
|
|
66
|
+
total_score: user.total_score,
|
|
67
|
+
username: user.username,
|
|
68
|
+
})),
|
|
69
|
+
};
|
|
70
|
+
}
|
package/api/getBeatmaps.ts
CHANGED
|
@@ -35,6 +35,7 @@ export const Schema = {
|
|
|
35
35
|
owner: z.number().nullable().optional(),
|
|
36
36
|
ownerUsername: z.string().nullable().optional(),
|
|
37
37
|
ownerAvatar: z.string().nullable().optional(),
|
|
38
|
+
status: z.string().nullable().optional(),
|
|
38
39
|
})
|
|
39
40
|
)
|
|
40
41
|
.optional(),
|
|
@@ -73,6 +74,7 @@ export async function getBeatmaps(data: (typeof Schema)["input"]["_type"]) {
|
|
|
73
74
|
owner,
|
|
74
75
|
created_at,
|
|
75
76
|
id,
|
|
77
|
+
status,
|
|
76
78
|
beatmaps!inner(
|
|
77
79
|
playcount,
|
|
78
80
|
ranked,
|
|
@@ -124,6 +126,7 @@ export async function getBeatmaps(data: (typeof Schema)["input"]["_type"]) {
|
|
|
124
126
|
image: beatmapPage.beatmaps?.image,
|
|
125
127
|
starRating: beatmapPage.beatmaps?.starRating,
|
|
126
128
|
owner: beatmapPage.owner,
|
|
129
|
+
status: beatmapPage.status,
|
|
127
130
|
ownerUsername: beatmapPage.profiles?.username,
|
|
128
131
|
})),
|
|
129
132
|
};
|
package/api/nominateMap.ts
CHANGED
|
@@ -42,7 +42,7 @@ export async function handler(data: (typeof Schema)["input"]["_type"]) {
|
|
|
42
42
|
|
|
43
43
|
const { data: mapData, error } = await supabase
|
|
44
44
|
.from("beatmapPages")
|
|
45
|
-
.select("id,nominations")
|
|
45
|
+
.select("id,nominations,owner")
|
|
46
46
|
.eq("id", data.mapId)
|
|
47
47
|
.single();
|
|
48
48
|
|
|
@@ -50,6 +50,10 @@ export async function handler(data: (typeof Schema)["input"]["_type"]) {
|
|
|
50
50
|
return NextResponse.json({ error: "Bad map" });
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
if (mapData.owner == queryUserData.id) {
|
|
54
|
+
return NextResponse.json({ error: "Can't nominate own map" });
|
|
55
|
+
}
|
|
56
|
+
|
|
53
57
|
if ((mapData.nominations as number[]).includes(queryUserData.id)) {
|
|
54
58
|
return NextResponse.json({ error: "Already nominated" });
|
|
55
59
|
}
|
package/api/submitScore.ts
CHANGED
|
@@ -64,6 +64,21 @@ export async function handler({
|
|
|
64
64
|
.eq("beatmapHash", data.mapHash)
|
|
65
65
|
.single();
|
|
66
66
|
|
|
67
|
+
let { data: beatmapPages, error: bpError } = await supabase
|
|
68
|
+
.from("beatmapPages")
|
|
69
|
+
.select("*")
|
|
70
|
+
.eq("latestBeatmapHash", data.mapHash)
|
|
71
|
+
.single();
|
|
72
|
+
|
|
73
|
+
if (!beatmapPages) {
|
|
74
|
+
return NextResponse.json(
|
|
75
|
+
{
|
|
76
|
+
error: "Map not submitted",
|
|
77
|
+
},
|
|
78
|
+
{ status: 500 }
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
67
82
|
let newPlaycount = 1;
|
|
68
83
|
|
|
69
84
|
if (beatmaps) {
|
|
@@ -79,6 +94,10 @@ export async function handler({
|
|
|
79
94
|
length: data.mapLength,
|
|
80
95
|
});
|
|
81
96
|
|
|
97
|
+
if (beatmapPages.status !== "RANKED") {
|
|
98
|
+
data.sspp = 0;
|
|
99
|
+
}
|
|
100
|
+
|
|
82
101
|
console.log("p1");
|
|
83
102
|
await supabase.from("scores").upsert({
|
|
84
103
|
beatmapHash: data.mapHash,
|
package/index.ts
CHANGED
|
@@ -30,6 +30,11 @@ import { Schema as GetAvatarUploadUrl } from "./api/getAvatarUploadUrl"
|
|
|
30
30
|
export { Schema as SchemaGetAvatarUploadUrl } from "./api/getAvatarUploadUrl"
|
|
31
31
|
export const getAvatarUploadUrl = handleApi({url:"/api/getAvatarUploadUrl",...GetAvatarUploadUrl})
|
|
32
32
|
|
|
33
|
+
// ./api/getBadgedUsers.ts API
|
|
34
|
+
import { Schema as GetBadgedUsers } from "./api/getBadgedUsers"
|
|
35
|
+
export { Schema as SchemaGetBadgedUsers } from "./api/getBadgedUsers"
|
|
36
|
+
export const getBadgedUsers = handleApi({url:"/api/getBadgedUsers",...GetBadgedUsers})
|
|
37
|
+
|
|
33
38
|
// ./api/getBeatmapPage.ts API
|
|
34
39
|
import { Schema as GetBeatmapPage } from "./api/getBeatmapPage"
|
|
35
40
|
export { Schema as SchemaGetBeatmapPage } from "./api/getBeatmapPage"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rhythia-api",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "127.0.0",
|
|
4
4
|
"main": "index.ts",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"update": "bun ./scripts/update.ts",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"next": "^14.2.5",
|
|
33
33
|
"osu-parsers": "^4.1.7",
|
|
34
34
|
"osu-standard-stable": "^5.0.0",
|
|
35
|
+
"sharp": "^0.33.5",
|
|
35
36
|
"simple-git": "^3.25.0",
|
|
36
37
|
"supabase": "^1.204.3",
|
|
37
38
|
"tsx": "^4.17.0",
|