rhythia-api 167.0.0 → 169.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/editProfile.ts +1 -0
- package/api/getPublicStats.ts +1 -1
- package/api/submitScore.ts +149 -1
- package/index.ts +2 -0
- package/package.json +1 -1
- package/types/database.ts +30 -0
- package/utils/requestUtils.ts +11 -0
package/api/editProfile.ts
CHANGED
package/api/getPublicStats.ts
CHANGED
|
@@ -125,7 +125,7 @@ export async function handler(data: (typeof Schema)["input"]["_type"]) {
|
|
|
125
125
|
const countOnline = await supabase
|
|
126
126
|
.from("profileActivities")
|
|
127
127
|
.select("*", { count: "exact", head: true })
|
|
128
|
-
.
|
|
128
|
+
.gt("last_activity", Date.now() - 1800000);
|
|
129
129
|
|
|
130
130
|
return NextResponse.json({
|
|
131
131
|
beatmaps: countBeatmapsQuery.count,
|
package/api/submitScore.ts
CHANGED
|
@@ -21,6 +21,7 @@ export const Schema = {
|
|
|
21
21
|
mods: z.array(z.string()),
|
|
22
22
|
additionalData: z.any(),
|
|
23
23
|
spin: z.boolean(),
|
|
24
|
+
virtualStars: z.number(),
|
|
24
25
|
}),
|
|
25
26
|
}),
|
|
26
27
|
output: z.object({
|
|
@@ -75,6 +76,7 @@ export async function handler({
|
|
|
75
76
|
mods: data.mods,
|
|
76
77
|
additionalData: data.additionalData,
|
|
77
78
|
spin: data.spin,
|
|
79
|
+
virtualStars: data.virtualStars,
|
|
78
80
|
})
|
|
79
81
|
) {
|
|
80
82
|
return NextResponse.json(
|
|
@@ -87,6 +89,18 @@ export async function handler({
|
|
|
87
89
|
|
|
88
90
|
const user = (await getUserBySession(session)) as User;
|
|
89
91
|
|
|
92
|
+
let { data: leversData } = await supabase
|
|
93
|
+
.from("levers")
|
|
94
|
+
.select("*")
|
|
95
|
+
.eq("id", 1)
|
|
96
|
+
.single();
|
|
97
|
+
|
|
98
|
+
if (leversData && leversData.disable_scores) {
|
|
99
|
+
return NextResponse.json({
|
|
100
|
+
error: "Scores are temporarily disabled",
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
90
104
|
let { data: userData, error: userError } = await supabase
|
|
91
105
|
.from("profiles")
|
|
92
106
|
.select("*")
|
|
@@ -172,7 +186,10 @@ export async function handler({
|
|
|
172
186
|
multiplierMod *= Math.pow(0.95, data.misses);
|
|
173
187
|
}
|
|
174
188
|
|
|
175
|
-
if (
|
|
189
|
+
if (
|
|
190
|
+
beatmaps.starRating &&
|
|
191
|
+
Math.abs(beatmaps.starRating - data.virtualStars) < 0.01
|
|
192
|
+
) {
|
|
176
193
|
awarded_sp = calculatePerformancePoints(
|
|
177
194
|
data.speed * beatmaps.starRating * multiplierMod,
|
|
178
195
|
accurracy
|
|
@@ -250,6 +267,28 @@ export async function handler({
|
|
|
250
267
|
});
|
|
251
268
|
console.log("p3");
|
|
252
269
|
|
|
270
|
+
if (awarded_sp > 99 && userData.ban == "cool") {
|
|
271
|
+
await postToWebhooks({
|
|
272
|
+
rp: Math.round(awarded_sp * 100) / 100,
|
|
273
|
+
username: userData.username || "",
|
|
274
|
+
userid: userData.id,
|
|
275
|
+
avatar: userData.avatar_url || "",
|
|
276
|
+
mapimage: beatmaps.imageLarge || "",
|
|
277
|
+
spin: data.spin,
|
|
278
|
+
speed: data.speed,
|
|
279
|
+
accuracy: accurracy,
|
|
280
|
+
mapname: beatmaps.title || "",
|
|
281
|
+
mapid: beatmapPages.id || 0,
|
|
282
|
+
misses: data.misses || 0,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (Math.abs((beatmaps.starRating || 0) - data.virtualStars) > 0.01) {
|
|
287
|
+
return NextResponse.json({
|
|
288
|
+
error: "Map mismatch, no RP points were awarded, please report the bug.",
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
|
|
253
292
|
return NextResponse.json({});
|
|
254
293
|
}
|
|
255
294
|
|
|
@@ -270,3 +309,112 @@ export function weightCalculate(hashMap: Record<string, number>) {
|
|
|
270
309
|
}
|
|
271
310
|
return totalSp;
|
|
272
311
|
}
|
|
312
|
+
|
|
313
|
+
const webHookTemplate = {
|
|
314
|
+
content: null,
|
|
315
|
+
embeds: [
|
|
316
|
+
{
|
|
317
|
+
title: "Captain Lou Albano - Do the Mario",
|
|
318
|
+
url: "https://www.rhythia.com/maps/4469",
|
|
319
|
+
color: 9633967,
|
|
320
|
+
fields: [
|
|
321
|
+
{
|
|
322
|
+
name: "Rhythm Points",
|
|
323
|
+
value: "424 RP",
|
|
324
|
+
inline: true,
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
name: "Accuracy",
|
|
328
|
+
value: "100%",
|
|
329
|
+
inline: true,
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
name: "Speed",
|
|
333
|
+
value: "1.45x",
|
|
334
|
+
inline: true,
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
name: "Playstyle",
|
|
338
|
+
value: "Spin",
|
|
339
|
+
inline: true,
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
name: "Misses",
|
|
343
|
+
value: "0",
|
|
344
|
+
inline: true,
|
|
345
|
+
},
|
|
346
|
+
],
|
|
347
|
+
author: {
|
|
348
|
+
name: "cunev",
|
|
349
|
+
url: "https://www.rhythia.com/player/0",
|
|
350
|
+
icon_url:
|
|
351
|
+
"https://static.rhythia.com/user-avatar-1735149648551-a2a8cfbe-af5d-46e8-a19a-be2339c1679a",
|
|
352
|
+
},
|
|
353
|
+
footer: {
|
|
354
|
+
text: "Sun, 22 Dec 2024 22:40:17 GMT",
|
|
355
|
+
},
|
|
356
|
+
thumbnail: {
|
|
357
|
+
url: "https://static.rhythia.com/beatmap-img-1735223264605-eliuka_dj_sharpnel_-_we_luv_lamalarge",
|
|
358
|
+
},
|
|
359
|
+
},
|
|
360
|
+
],
|
|
361
|
+
attachments: [],
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
export async function postToWebhooks({
|
|
365
|
+
rp,
|
|
366
|
+
username,
|
|
367
|
+
userid,
|
|
368
|
+
avatar,
|
|
369
|
+
mapimage,
|
|
370
|
+
spin,
|
|
371
|
+
speed,
|
|
372
|
+
accuracy,
|
|
373
|
+
mapname,
|
|
374
|
+
mapid,
|
|
375
|
+
misses,
|
|
376
|
+
}: {
|
|
377
|
+
rp: number;
|
|
378
|
+
username: string;
|
|
379
|
+
userid: number;
|
|
380
|
+
avatar: string;
|
|
381
|
+
mapimage: string;
|
|
382
|
+
spin: boolean;
|
|
383
|
+
speed: number;
|
|
384
|
+
accuracy: number;
|
|
385
|
+
mapname: string;
|
|
386
|
+
mapid: number;
|
|
387
|
+
misses: number;
|
|
388
|
+
}) {
|
|
389
|
+
const webHooks = await supabase.from("discordWebhooks").select("*");
|
|
390
|
+
|
|
391
|
+
if (!webHooks.data) return;
|
|
392
|
+
|
|
393
|
+
for (const webhook of webHooks.data) {
|
|
394
|
+
const webhookUrl = webhook.webhook_link;
|
|
395
|
+
|
|
396
|
+
const embed = webHookTemplate.embeds[0];
|
|
397
|
+
embed.title = mapname;
|
|
398
|
+
embed.url = `https://www.rhythia.com/maps/${mapid}`;
|
|
399
|
+
embed.fields[0].value = `${rp} RP`;
|
|
400
|
+
embed.fields[1].value = `${Math.round(accuracy * 10000) / 100}%`;
|
|
401
|
+
embed.fields[2].value = `${speed}x`;
|
|
402
|
+
embed.fields[3].value = spin ? "Spin" : "Lock";
|
|
403
|
+
embed.fields[4].value = `${misses} misses`;
|
|
404
|
+
embed.author.name = username;
|
|
405
|
+
embed.author.url = `https://www.rhythia.com/player/${userid}`;
|
|
406
|
+
embed.author.icon_url = avatar;
|
|
407
|
+
embed.thumbnail.url = mapimage;
|
|
408
|
+
if (mapimage.includes("backfill")) {
|
|
409
|
+
embed.thumbnail.url = "https://www.rhythia.com/unkimg.png";
|
|
410
|
+
}
|
|
411
|
+
embed.footer.text = new Date().toUTCString();
|
|
412
|
+
await fetch(webhookUrl, {
|
|
413
|
+
method: "POST",
|
|
414
|
+
headers: {
|
|
415
|
+
"Content-Type": "application/json",
|
|
416
|
+
},
|
|
417
|
+
body: JSON.stringify(webHookTemplate),
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
}
|
package/index.ts
CHANGED
|
@@ -92,6 +92,7 @@ export const Schema = {
|
|
|
92
92
|
session: z.string(),
|
|
93
93
|
data: z.object({
|
|
94
94
|
avatar_url: z.string().optional(),
|
|
95
|
+
profile_image: z.string().optional(),
|
|
95
96
|
username: z.string().optional(),
|
|
96
97
|
}),
|
|
97
98
|
}),
|
|
@@ -705,6 +706,7 @@ export const Schema = {
|
|
|
705
706
|
mods: z.array(z.string()),
|
|
706
707
|
additionalData: z.any(),
|
|
707
708
|
spin: z.boolean(),
|
|
709
|
+
virtualStars: z.number(),
|
|
708
710
|
}),
|
|
709
711
|
}),
|
|
710
712
|
output: z.object({
|
package/package.json
CHANGED
package/types/database.ts
CHANGED
|
@@ -153,6 +153,36 @@ export type Database = {
|
|
|
153
153
|
}
|
|
154
154
|
Relationships: []
|
|
155
155
|
}
|
|
156
|
+
discordWebhooks: {
|
|
157
|
+
Row: {
|
|
158
|
+
id: number
|
|
159
|
+
webhook_link: string
|
|
160
|
+
}
|
|
161
|
+
Insert: {
|
|
162
|
+
id?: number
|
|
163
|
+
webhook_link?: string
|
|
164
|
+
}
|
|
165
|
+
Update: {
|
|
166
|
+
id?: number
|
|
167
|
+
webhook_link?: string
|
|
168
|
+
}
|
|
169
|
+
Relationships: []
|
|
170
|
+
}
|
|
171
|
+
levers: {
|
|
172
|
+
Row: {
|
|
173
|
+
disable_scores: boolean
|
|
174
|
+
id: number
|
|
175
|
+
}
|
|
176
|
+
Insert: {
|
|
177
|
+
disable_scores?: boolean
|
|
178
|
+
id?: number
|
|
179
|
+
}
|
|
180
|
+
Update: {
|
|
181
|
+
disable_scores?: boolean
|
|
182
|
+
id?: number
|
|
183
|
+
}
|
|
184
|
+
Relationships: []
|
|
185
|
+
}
|
|
156
186
|
passkeys: {
|
|
157
187
|
Row: {
|
|
158
188
|
email: string
|
package/utils/requestUtils.ts
CHANGED
|
@@ -22,6 +22,17 @@ export async function protectedApi({
|
|
|
22
22
|
try {
|
|
23
23
|
const toParse = await request.json();
|
|
24
24
|
const data = schema.input.parse(toParse);
|
|
25
|
+
|
|
26
|
+
const dataClone = structuredClone(data);
|
|
27
|
+
if (dataClone) {
|
|
28
|
+
if (dataClone["token"]) {
|
|
29
|
+
dataClone["token"] = "********";
|
|
30
|
+
}
|
|
31
|
+
Object.keys(dataClone).forEach((key) => {
|
|
32
|
+
console.log("KEY: ", key, dataClone[key]);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
25
36
|
setActivity(data);
|
|
26
37
|
if (authorization) {
|
|
27
38
|
const authorizationResponse = await authorization(data);
|