rhythia-api 241.0.0 → 243.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/createBeatmap.ts +57 -39
- package/api/editProfile.ts +4 -56
- package/api/editProfileFriend.ts +122 -0
- package/api/executeAdminOperation.ts +1030 -681
- package/api/getAvatarUploadUrl.ts +90 -85
- package/api/getBeatmapPage.ts +2 -0
- package/api/getBeatmapPageById.ts +2 -0
- package/api/getBeatmaps.ts +110 -197
- package/api/getCollection.ts +44 -31
- package/api/getFriends.ts +154 -0
- package/api/getMapUploadUrl.ts +90 -93
- package/api/getProfile.ts +195 -127
- package/api/getScore.ts +2 -0
- package/api/getVideoUploadUrl.ts +90 -85
- package/api/submitScoreInternal.ts +506 -461
- package/api/updateBeatmapPage.ts +6 -0
- package/beatmap-file-urls.json +29398 -0
- package/handleApi.ts +24 -21
- package/index.ts +183 -137
- package/package.json +5 -2
- package/queries/admin_delete_user.sql +42 -39
- package/queries/admin_remove_all_scores.sql +6 -3
- package/queries/admin_remove_score.sql +107 -0
- package/queries/admin_update_profile.sql +22 -0
- package/queries/get_beatmaps_v2.sql +48 -0
- package/queries/get_top_scores_for_beatmap3.sql +47 -38
- package/queries/profile_update_guards.sql +66 -0
- package/types/database.ts +1525 -1414
- package/utils/beatmapFiles.ts +102 -0
- package/utils/beatmapHash.ts +336 -0
- package/utils/beatmapTopScores.ts +68 -84
- package/utils/getUserBySession.ts +3 -1
- package/utils/profileUpdateValidation.ts +51 -0
- package/utils/redis.ts +24 -0
- package/utils/rhrReplay.ts +122 -0
- package/utils/star-calc/sspmParser.ts +294 -160
- package/worker.ts +195 -191
package/handleApi.ts
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
let
|
|
3
|
-
import { profanity, CensorType } from "@2toad/profanity";
|
|
4
|
-
export function setEnvironment(
|
|
5
|
-
stage: "development" | "testing" | "production"
|
|
6
|
-
) {
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
export function
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
let endpoint = "https://development.rhythia.com";
|
|
3
|
+
import { profanity, CensorType } from "@2toad/profanity";
|
|
4
|
+
export function setEnvironment(
|
|
5
|
+
stage: "development" | "testing" | "production"
|
|
6
|
+
) {
|
|
7
|
+
endpoint = `https://${stage}.rhythia.com`;
|
|
8
|
+
}
|
|
9
|
+
export function setEndpoint(value: string) {
|
|
10
|
+
endpoint = value;
|
|
11
|
+
}
|
|
12
|
+
export function handleApi<
|
|
13
|
+
T extends { url: string; input: z.ZodObject<any>; output: z.ZodObject<any> }
|
|
14
|
+
>(apiSchema: T) {
|
|
15
|
+
profanity.whitelist.addWords(["willy"]);
|
|
16
|
+
return async (input: T["input"]["_type"]): Promise<T["output"]["_type"]> => {
|
|
17
|
+
const response = await fetch(`${endpoint}${apiSchema.url}`, {
|
|
18
|
+
method: "POST",
|
|
19
|
+
body: JSON.stringify(input),
|
|
20
|
+
});
|
|
21
|
+
const output = await response.text();
|
|
22
|
+
return JSON.parse(profanity.censor(output));
|
|
23
|
+
};
|
|
24
|
+
}
|
package/index.ts
CHANGED
|
@@ -321,6 +321,25 @@ import { Schema as EditProfile } from "./api/editProfile"
|
|
|
321
321
|
export { Schema as SchemaEditProfile } from "./api/editProfile"
|
|
322
322
|
export const editProfile = handleApi({url:"/api/editProfile",...EditProfile})
|
|
323
323
|
|
|
324
|
+
// ./api/editProfileFriend.ts API
|
|
325
|
+
|
|
326
|
+
/*
|
|
327
|
+
export const Schema = {
|
|
328
|
+
input: z.strictObject({
|
|
329
|
+
session: z.string(),
|
|
330
|
+
profileId: z.number(),
|
|
331
|
+
action: z.enum(["add", "remove"]),
|
|
332
|
+
}),
|
|
333
|
+
output: z.strictObject({
|
|
334
|
+
error: z.string().optional(),
|
|
335
|
+
friend_count: z.number().optional(),
|
|
336
|
+
friend_state: friendStateSchema.optional(),
|
|
337
|
+
}),
|
|
338
|
+
};*/
|
|
339
|
+
import { Schema as EditProfileFriend } from "./api/editProfileFriend"
|
|
340
|
+
export { Schema as SchemaEditProfileFriend } from "./api/editProfileFriend"
|
|
341
|
+
export const editProfileFriend = handleApi({url:"/api/editProfileFriend",...EditProfileFriend})
|
|
342
|
+
|
|
324
343
|
// ./api/enhancedSearch.ts API
|
|
325
344
|
|
|
326
345
|
/*
|
|
@@ -373,18 +392,18 @@ export const executeAdminOperation = handleApi({url:"/api/executeAdminOperation"
|
|
|
373
392
|
// ./api/getAvatarUploadUrl.ts API
|
|
374
393
|
|
|
375
394
|
/*
|
|
376
|
-
export const Schema = {
|
|
377
|
-
input: z.strictObject({
|
|
378
|
-
session: z.string(),
|
|
379
|
-
contentLength: z.number(),
|
|
380
|
-
contentType: z.string(),
|
|
381
|
-
intrinsicToken: z.string(),
|
|
382
|
-
}),
|
|
383
|
-
output: z.strictObject({
|
|
384
|
-
error: z.string().optional(),
|
|
385
|
-
url: z.string().optional(),
|
|
386
|
-
objectKey: z.string().optional(),
|
|
387
|
-
}),
|
|
395
|
+
export const Schema = {
|
|
396
|
+
input: z.strictObject({
|
|
397
|
+
session: z.string(),
|
|
398
|
+
contentLength: z.number(),
|
|
399
|
+
contentType: z.string(),
|
|
400
|
+
intrinsicToken: z.string(),
|
|
401
|
+
}),
|
|
402
|
+
output: z.strictObject({
|
|
403
|
+
error: z.string().optional(),
|
|
404
|
+
url: z.string().optional(),
|
|
405
|
+
objectKey: z.string().optional(),
|
|
406
|
+
}),
|
|
388
407
|
};*/
|
|
389
408
|
import { Schema as GetAvatarUploadUrl } from "./api/getAvatarUploadUrl"
|
|
390
409
|
export { Schema as SchemaGetAvatarUploadUrl } from "./api/getAvatarUploadUrl"
|
|
@@ -522,6 +541,7 @@ export const Schema = {
|
|
|
522
541
|
description: z.string().nullable().optional(),
|
|
523
542
|
tags: z.string().nullable().optional(),
|
|
524
543
|
videoUrl: z.string().nullable().optional(),
|
|
544
|
+
mapHash: z.string().nullable().optional(),
|
|
525
545
|
vetos: z
|
|
526
546
|
.array(
|
|
527
547
|
z.object({
|
|
@@ -594,6 +614,7 @@ export const Schema = {
|
|
|
594
614
|
qualified: z.boolean().nullable().optional(),
|
|
595
615
|
qualifiedAt: z.string().nullable().optional(),
|
|
596
616
|
videoUrl: z.string().nullable(),
|
|
617
|
+
mapHash: z.string().nullable().optional(),
|
|
597
618
|
vetos: z
|
|
598
619
|
.array(
|
|
599
620
|
z.object({
|
|
@@ -617,50 +638,51 @@ export const getBeatmapPageById = handleApi({url:"/api/getBeatmapPageById",...Ge
|
|
|
617
638
|
// ./api/getBeatmaps.ts API
|
|
618
639
|
|
|
619
640
|
/*
|
|
620
|
-
export const Schema = {
|
|
621
|
-
input: z.strictObject({
|
|
622
|
-
session: z.string(),
|
|
623
|
-
textFilter: z.string().optional(),
|
|
624
|
-
authorFilter: z.string().optional(),
|
|
625
|
-
tagsFilter: z.string().optional(),
|
|
626
|
-
page: z.number().default(1),
|
|
627
|
-
maxStars: z.number().optional(),
|
|
628
|
-
minLength: z.number().optional(),
|
|
629
|
-
maxLength: z.number().optional(),
|
|
630
|
-
minStars: z.number().optional(),
|
|
631
|
-
creator: z.number().optional(),
|
|
632
|
-
status: z.string().optional(),
|
|
633
|
-
}),
|
|
634
|
-
output: z.object({
|
|
635
|
-
error: z.string().optional(),
|
|
636
|
-
total: z.number(),
|
|
637
|
-
viewPerPage: z.number(),
|
|
638
|
-
currentPage: z.number(),
|
|
639
|
-
beatmaps: z
|
|
640
|
-
.array(
|
|
641
|
-
z.object({
|
|
642
|
-
id: z.number(),
|
|
643
|
-
playcount: z.number().nullable().optional(),
|
|
644
|
-
created_at: z.string().nullable().optional(),
|
|
645
|
-
difficulty: z.number().nullable().optional(),
|
|
646
|
-
noteCount: z.number().nullable().optional(),
|
|
647
|
-
length: z.number().nullable().optional(),
|
|
648
|
-
title: z.string().nullable().optional(),
|
|
649
|
-
ranked: z.boolean().nullable().optional(),
|
|
650
|
-
beatmapFile: z.string().nullable().optional(),
|
|
651
|
-
image: z.string().nullable().optional(),
|
|
652
|
-
starRating: z.number().nullable().optional(),
|
|
653
|
-
owner: z.number().nullable().optional(),
|
|
654
|
-
ownerUsername: z.string().nullable().optional(),
|
|
655
|
-
ownerAvatar: z.string().nullable().optional(),
|
|
656
|
-
status: z.string().nullable().optional(),
|
|
657
|
-
qualified: z.boolean().nullable().optional(),
|
|
658
|
-
tags: z.string().nullable().optional(),
|
|
659
|
-
videoUrl: z.string().nullable().optional(),
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
641
|
+
export const Schema = {
|
|
642
|
+
input: z.strictObject({
|
|
643
|
+
session: z.string(),
|
|
644
|
+
textFilter: z.string().optional(),
|
|
645
|
+
authorFilter: z.string().optional(),
|
|
646
|
+
tagsFilter: z.string().optional(),
|
|
647
|
+
page: z.number().default(1),
|
|
648
|
+
maxStars: z.number().optional(),
|
|
649
|
+
minLength: z.number().optional(),
|
|
650
|
+
maxLength: z.number().optional(),
|
|
651
|
+
minStars: z.number().optional(),
|
|
652
|
+
creator: z.number().optional(),
|
|
653
|
+
status: z.string().optional(),
|
|
654
|
+
}),
|
|
655
|
+
output: z.object({
|
|
656
|
+
error: z.string().optional(),
|
|
657
|
+
total: z.number(),
|
|
658
|
+
viewPerPage: z.number(),
|
|
659
|
+
currentPage: z.number(),
|
|
660
|
+
beatmaps: z
|
|
661
|
+
.array(
|
|
662
|
+
z.object({
|
|
663
|
+
id: z.number(),
|
|
664
|
+
playcount: z.number().nullable().optional(),
|
|
665
|
+
created_at: z.string().nullable().optional(),
|
|
666
|
+
difficulty: z.number().nullable().optional(),
|
|
667
|
+
noteCount: z.number().nullable().optional(),
|
|
668
|
+
length: z.number().nullable().optional(),
|
|
669
|
+
title: z.string().nullable().optional(),
|
|
670
|
+
ranked: z.boolean().nullable().optional(),
|
|
671
|
+
beatmapFile: z.string().nullable().optional(),
|
|
672
|
+
image: z.string().nullable().optional(),
|
|
673
|
+
starRating: z.number().nullable().optional(),
|
|
674
|
+
owner: z.number().nullable().optional(),
|
|
675
|
+
ownerUsername: z.string().nullable().optional(),
|
|
676
|
+
ownerAvatar: z.string().nullable().optional(),
|
|
677
|
+
status: z.string().nullable().optional(),
|
|
678
|
+
qualified: z.boolean().nullable().optional(),
|
|
679
|
+
tags: z.string().nullable().optional(),
|
|
680
|
+
videoUrl: z.string().nullable().optional(),
|
|
681
|
+
mapHash: z.string().nullable().optional(),
|
|
682
|
+
})
|
|
683
|
+
)
|
|
684
|
+
.optional(),
|
|
685
|
+
}),
|
|
664
686
|
};*/
|
|
665
687
|
import { Schema as GetBeatmaps } from "./api/getBeatmaps"
|
|
666
688
|
export { Schema as SchemaGetBeatmaps } from "./api/getBeatmaps"
|
|
@@ -764,19 +786,22 @@ export const Schema = {
|
|
|
764
786
|
input: z.strictObject({
|
|
765
787
|
session: z.string(),
|
|
766
788
|
collection: z.number(),
|
|
789
|
+
page: z.number().optional().default(1),
|
|
790
|
+
itemsPerPage: z.number().optional().default(30),
|
|
767
791
|
}),
|
|
768
792
|
output: z.object({
|
|
769
|
-
collection: z.object({
|
|
770
|
-
title: z.string(),
|
|
771
|
-
description: z.string(),
|
|
772
|
-
owner: z.object({
|
|
773
|
-
id: z.number(),
|
|
774
|
-
username: z.string(),
|
|
775
|
-
avatar_url: z.string().nullable(),
|
|
776
|
-
}),
|
|
777
|
-
isList: z.boolean(),
|
|
778
|
-
|
|
779
|
-
|
|
793
|
+
collection: z.object({
|
|
794
|
+
title: z.string(),
|
|
795
|
+
description: z.string(),
|
|
796
|
+
owner: z.object({
|
|
797
|
+
id: z.number(),
|
|
798
|
+
username: z.string(),
|
|
799
|
+
avatar_url: z.string().nullable(),
|
|
800
|
+
}),
|
|
801
|
+
isList: z.boolean(),
|
|
802
|
+
beatmapCount: z.number(),
|
|
803
|
+
beatmaps: z.array(
|
|
804
|
+
z.object({
|
|
780
805
|
id: z.number(),
|
|
781
806
|
playcount: z.number().nullable().optional(),
|
|
782
807
|
created_at: z.string().nullable().optional(),
|
|
@@ -794,6 +819,7 @@ export const Schema = {
|
|
|
794
819
|
})
|
|
795
820
|
),
|
|
796
821
|
}),
|
|
822
|
+
totalPages: z.number(),
|
|
797
823
|
error: z.string().optional(),
|
|
798
824
|
}),
|
|
799
825
|
};*/
|
|
@@ -840,6 +866,22 @@ import { Schema as GetCollections } from "./api/getCollections"
|
|
|
840
866
|
export { Schema as SchemaGetCollections } from "./api/getCollections"
|
|
841
867
|
export const getCollections = handleApi({url:"/api/getCollections",...GetCollections})
|
|
842
868
|
|
|
869
|
+
// ./api/getFriends.ts API
|
|
870
|
+
|
|
871
|
+
/*
|
|
872
|
+
export const Schema = {
|
|
873
|
+
input: z.strictObject({
|
|
874
|
+
session: z.string(),
|
|
875
|
+
}),
|
|
876
|
+
output: z.strictObject({
|
|
877
|
+
error: z.string().optional(),
|
|
878
|
+
friends: z.array(friendUserSchema),
|
|
879
|
+
}),
|
|
880
|
+
};*/
|
|
881
|
+
import { Schema as GetFriends } from "./api/getFriends"
|
|
882
|
+
export { Schema as SchemaGetFriends } from "./api/getFriends"
|
|
883
|
+
export const getFriends = handleApi({url:"/api/getFriends",...GetFriends})
|
|
884
|
+
|
|
843
885
|
// ./api/getInventory.ts API
|
|
844
886
|
|
|
845
887
|
/*
|
|
@@ -904,19 +946,19 @@ export const getLeaderboard = handleApi({url:"/api/getLeaderboard",...GetLeaderb
|
|
|
904
946
|
// ./api/getMapUploadUrl.ts API
|
|
905
947
|
|
|
906
948
|
/*
|
|
907
|
-
export const Schema = {
|
|
908
|
-
input: z.strictObject({
|
|
909
|
-
mapName: z.string().optional(),
|
|
910
|
-
session: z.string(),
|
|
911
|
-
contentLength: z.number(),
|
|
912
|
-
contentType: z.string(),
|
|
913
|
-
intrinsicToken: z.string(),
|
|
914
|
-
}),
|
|
915
|
-
output: z.strictObject({
|
|
916
|
-
error: z.string().optional(),
|
|
917
|
-
url: z.string().optional(),
|
|
918
|
-
objectKey: z.string().optional(),
|
|
919
|
-
}),
|
|
949
|
+
export const Schema = {
|
|
950
|
+
input: z.strictObject({
|
|
951
|
+
mapName: z.string().optional(),
|
|
952
|
+
session: z.string(),
|
|
953
|
+
contentLength: z.number(),
|
|
954
|
+
contentType: z.string(),
|
|
955
|
+
intrinsicToken: z.string(),
|
|
956
|
+
}),
|
|
957
|
+
output: z.strictObject({
|
|
958
|
+
error: z.string().optional(),
|
|
959
|
+
url: z.string().optional(),
|
|
960
|
+
objectKey: z.string().optional(),
|
|
961
|
+
}),
|
|
920
962
|
};*/
|
|
921
963
|
import { Schema as GetMapUploadUrl } from "./api/getMapUploadUrl"
|
|
922
964
|
export { Schema as SchemaGetMapUploadUrl } from "./api/getMapUploadUrl"
|
|
@@ -967,26 +1009,26 @@ export const getPassToken = handleApi({url:"/api/getPassToken",...GetPassToken})
|
|
|
967
1009
|
/*
|
|
968
1010
|
export const Schema = {
|
|
969
1011
|
input: z.strictObject({
|
|
970
|
-
session: z.string(),
|
|
971
|
-
id: z.number().nullable().optional(),
|
|
972
|
-
}),
|
|
973
|
-
output: z.object({
|
|
974
|
-
error: z.string().optional(),
|
|
975
|
-
user: z
|
|
976
|
-
.object({
|
|
977
|
-
about_me: z.string().nullable(),
|
|
978
|
-
avatar_url: z.string().nullable(),
|
|
979
|
-
profile_image: z.string().nullable(),
|
|
980
|
-
badges: z.any().nullable(),
|
|
981
|
-
created_at: z.number().nullable(),
|
|
982
|
-
flag: z.string().nullable(),
|
|
983
|
-
id: z.number(),
|
|
984
|
-
uid: z.string().nullable(),
|
|
985
|
-
ban: z.string().nullable(),
|
|
986
|
-
username: z.string().nullable(),
|
|
987
|
-
verified: z.boolean().nullable(),
|
|
988
|
-
verificationDeadline: z.number().nullable(),
|
|
989
|
-
play_count: z.number().nullable(),
|
|
1012
|
+
session: z.string(),
|
|
1013
|
+
id: z.number().nullable().optional(),
|
|
1014
|
+
}),
|
|
1015
|
+
output: z.object({
|
|
1016
|
+
error: z.string().optional(),
|
|
1017
|
+
user: z
|
|
1018
|
+
.object({
|
|
1019
|
+
about_me: z.string().nullable(),
|
|
1020
|
+
avatar_url: z.string().nullable(),
|
|
1021
|
+
profile_image: z.string().nullable(),
|
|
1022
|
+
badges: z.any().nullable(),
|
|
1023
|
+
created_at: z.number().nullable(),
|
|
1024
|
+
flag: z.string().nullable(),
|
|
1025
|
+
id: z.number(),
|
|
1026
|
+
uid: z.string().nullable(),
|
|
1027
|
+
ban: z.string().nullable(),
|
|
1028
|
+
username: z.string().nullable(),
|
|
1029
|
+
verified: z.boolean().nullable(),
|
|
1030
|
+
verificationDeadline: z.number().nullable(),
|
|
1031
|
+
play_count: z.number().nullable(),
|
|
990
1032
|
skill_points: z.number().nullable(),
|
|
991
1033
|
squares_hit: z.number().nullable(),
|
|
992
1034
|
total_score: z.number().nullable(),
|
|
@@ -995,6 +1037,8 @@ export const Schema = {
|
|
|
995
1037
|
activity_status: z.enum(["active", "inactive"]),
|
|
996
1038
|
is_online: z.boolean(),
|
|
997
1039
|
last_active_timestamp: z.number().nullable(),
|
|
1040
|
+
friend_count: z.number(),
|
|
1041
|
+
friend_state: friendStateSchema,
|
|
998
1042
|
can_change_flag: z.boolean(),
|
|
999
1043
|
next_username_change_at: z.string().nullable(),
|
|
1000
1044
|
previous_usernames: z.array(
|
|
@@ -1008,11 +1052,11 @@ export const Schema = {
|
|
|
1008
1052
|
id: z.number(),
|
|
1009
1053
|
acronym: z.string(),
|
|
1010
1054
|
})
|
|
1011
|
-
.optional()
|
|
1012
|
-
.nullable(),
|
|
1013
|
-
})
|
|
1014
|
-
.optional(),
|
|
1015
|
-
}),
|
|
1055
|
+
.optional()
|
|
1056
|
+
.nullable(),
|
|
1057
|
+
})
|
|
1058
|
+
.optional(),
|
|
1059
|
+
}),
|
|
1016
1060
|
};*/
|
|
1017
1061
|
import { Schema as GetProfile } from "./api/getProfile"
|
|
1018
1062
|
export { Schema as SchemaGetProfile } from "./api/getProfile"
|
|
@@ -1124,6 +1168,7 @@ export const Schema = {
|
|
|
1124
1168
|
username: z.string().optional().nullable(),
|
|
1125
1169
|
speed: z.number().optional().nullable(),
|
|
1126
1170
|
spin: z.boolean().optional().nullable(),
|
|
1171
|
+
replay_url: z.string().optional().nullable(),
|
|
1127
1172
|
})
|
|
1128
1173
|
.optional(),
|
|
1129
1174
|
}),
|
|
@@ -1284,18 +1329,18 @@ export const getVerified = handleApi({url:"/api/getVerified",...GetVerified})
|
|
|
1284
1329
|
// ./api/getVideoUploadUrl.ts API
|
|
1285
1330
|
|
|
1286
1331
|
/*
|
|
1287
|
-
export const Schema = {
|
|
1288
|
-
input: z.strictObject({
|
|
1289
|
-
session: z.string(),
|
|
1290
|
-
contentLength: z.number(),
|
|
1291
|
-
contentType: z.string(),
|
|
1292
|
-
intrinsicToken: z.string(),
|
|
1293
|
-
}),
|
|
1294
|
-
output: z.strictObject({
|
|
1295
|
-
error: z.string().optional(),
|
|
1296
|
-
url: z.string().optional(),
|
|
1297
|
-
objectKey: z.string().optional(),
|
|
1298
|
-
}),
|
|
1332
|
+
export const Schema = {
|
|
1333
|
+
input: z.strictObject({
|
|
1334
|
+
session: z.string(),
|
|
1335
|
+
contentLength: z.number(),
|
|
1336
|
+
contentType: z.string(),
|
|
1337
|
+
intrinsicToken: z.string(),
|
|
1338
|
+
}),
|
|
1339
|
+
output: z.strictObject({
|
|
1340
|
+
error: z.string().optional(),
|
|
1341
|
+
url: z.string().optional(),
|
|
1342
|
+
objectKey: z.string().optional(),
|
|
1343
|
+
}),
|
|
1299
1344
|
};*/
|
|
1300
1345
|
import { Schema as GetVideoUploadUrl } from "./api/getVideoUploadUrl"
|
|
1301
1346
|
export { Schema as SchemaGetVideoUploadUrl } from "./api/getVideoUploadUrl"
|
|
@@ -1442,26 +1487,27 @@ export const submitScore = handleApi({url:"/api/submitScore",...SubmitScore})
|
|
|
1442
1487
|
// ./api/submitScoreInternal.ts API
|
|
1443
1488
|
|
|
1444
1489
|
/*
|
|
1445
|
-
export const Schema = {
|
|
1446
|
-
input: z.strictObject({
|
|
1447
|
-
session: z.string(),
|
|
1448
|
-
secret: z.string(),
|
|
1449
|
-
token: z.string(),
|
|
1450
|
-
data: z.strictObject({
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1490
|
+
export const Schema = {
|
|
1491
|
+
input: z.strictObject({
|
|
1492
|
+
session: z.string(),
|
|
1493
|
+
secret: z.string(),
|
|
1494
|
+
token: z.string(),
|
|
1495
|
+
data: z.strictObject({
|
|
1496
|
+
beatmapHash: z.string().optional().nullable(),
|
|
1497
|
+
onlineMapId: z.number(),
|
|
1498
|
+
misses: z.number(),
|
|
1499
|
+
hits: z.number(),
|
|
1500
|
+
speed: z.number(),
|
|
1501
|
+
mods: z.array(z.string()),
|
|
1502
|
+
spin: z.boolean(),
|
|
1503
|
+
replayBytes: z.string().nullable().optional(),
|
|
1504
|
+
pauses: z.number().nullable().optional(),
|
|
1505
|
+
failTime: z.number().nullable().optional(),
|
|
1506
|
+
}),
|
|
1507
|
+
}),
|
|
1508
|
+
output: z.object({
|
|
1509
|
+
error: z.string().optional(),
|
|
1510
|
+
}),
|
|
1465
1511
|
};*/
|
|
1466
1512
|
import { Schema as SubmitScoreInternal } from "./api/submitScoreInternal"
|
|
1467
1513
|
export { Schema as SchemaSubmitScoreInternal } from "./api/submitScoreInternal"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rhythia-api",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "243.0.0",
|
|
4
4
|
"main": "index.ts",
|
|
5
5
|
"author": "online-contributors-cunev",
|
|
6
6
|
"scripts": {
|
|
@@ -10,7 +10,10 @@
|
|
|
10
10
|
"test": "tsx ./scripts/test.ts",
|
|
11
11
|
"cache:clear-user-scores": "bun run scripts/clear-user-score-cache.ts",
|
|
12
12
|
"db:optimize-user-scores": "bun run scripts/optimize-user-scores-indexes.ts",
|
|
13
|
+
"db:add-beatmap-page-map-hash": "node --experimental-transform-types scripts/add-beatmap-page-map-hash.ts",
|
|
14
|
+
"db:backfill-beatmap-page-map-hashes": "node --experimental-transform-types scripts/backfill-beatmap-page-map-hashes.ts",
|
|
13
15
|
"db:create-profile-flags": "node scripts/create-profile-flags-table.ts",
|
|
16
|
+
"db:create-profile-friends": "node scripts/create-profile-friends-table.ts",
|
|
14
17
|
"db:create-profile-reports": "node scripts/create-profile-reports-table.ts",
|
|
15
18
|
"query-pull": "bun run scripts/pull-queries.ts",
|
|
16
19
|
"query-push": "bun run scripts/deploy-queries.ts",
|
|
@@ -27,7 +30,7 @@
|
|
|
27
30
|
"@supabase/supabase-js": "^2.45.1",
|
|
28
31
|
"@types/bun": "^1.1.6",
|
|
29
32
|
"@types/lodash": "^4.17.7",
|
|
30
|
-
"@types/node": "^
|
|
33
|
+
"@types/node": "^25.6.0",
|
|
31
34
|
"@types/pg": "^8.15.5",
|
|
32
35
|
"@types/validator": "^13.12.2",
|
|
33
36
|
"bad-words": "^4.0.0",
|
|
@@ -1,39 +1,42 @@
|
|
|
1
|
-
CREATE OR REPLACE FUNCTION public.admin_delete_user(user_id integer)
|
|
2
|
-
RETURNS boolean
|
|
3
|
-
LANGUAGE plpgsql
|
|
4
|
-
SECURITY DEFINER
|
|
5
|
-
AS $function$
|
|
6
|
-
DECLARE
|
|
7
|
-
success BOOLEAN;
|
|
8
|
-
BEGIN
|
|
9
|
-
-- Delete scores first due to foreign key constraints
|
|
10
|
-
DELETE FROM public.scores WHERE "userId" = user_id;
|
|
11
|
-
|
|
12
|
-
-- Delete beatmapPageComments
|
|
13
|
-
DELETE FROM public."beatmapPageComments" WHERE owner = user_id;
|
|
14
|
-
|
|
15
|
-
-- Delete beatmapPages owned by user
|
|
16
|
-
DELETE FROM public."beatmapPages" WHERE owner = user_id;
|
|
17
|
-
|
|
18
|
-
-- Delete collections owned by user
|
|
19
|
-
DELETE FROM public."beatmapCollections" WHERE owner = user_id;
|
|
20
|
-
|
|
21
|
-
-- Delete collection relations related to user's collections
|
|
22
|
-
-- (this is handled by cascade if you have it set up)
|
|
23
|
-
|
|
24
|
-
-- Delete passkeys
|
|
25
|
-
DELETE FROM public.passkeys WHERE id = user_id;
|
|
26
|
-
|
|
27
|
-
-- Delete
|
|
28
|
-
DELETE FROM public.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
--
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
1
|
+
CREATE OR REPLACE FUNCTION public.admin_delete_user(user_id integer)
|
|
2
|
+
RETURNS boolean
|
|
3
|
+
LANGUAGE plpgsql
|
|
4
|
+
SECURITY DEFINER
|
|
5
|
+
AS $function$
|
|
6
|
+
DECLARE
|
|
7
|
+
success BOOLEAN;
|
|
8
|
+
BEGIN
|
|
9
|
+
-- Delete scores first due to foreign key constraints
|
|
10
|
+
DELETE FROM public.scores WHERE "userId" = user_id;
|
|
11
|
+
|
|
12
|
+
-- Delete beatmapPageComments
|
|
13
|
+
DELETE FROM public."beatmapPageComments" WHERE owner = user_id;
|
|
14
|
+
|
|
15
|
+
-- Delete beatmapPages owned by user
|
|
16
|
+
DELETE FROM public."beatmapPages" WHERE owner = user_id;
|
|
17
|
+
|
|
18
|
+
-- Delete collections owned by user
|
|
19
|
+
DELETE FROM public."beatmapCollections" WHERE owner = user_id;
|
|
20
|
+
|
|
21
|
+
-- Delete collection relations related to user's collections
|
|
22
|
+
-- (this is handled by cascade if you have it set up)
|
|
23
|
+
|
|
24
|
+
-- Delete passkeys
|
|
25
|
+
DELETE FROM public.passkeys WHERE id = user_id;
|
|
26
|
+
|
|
27
|
+
-- Delete user HWID records
|
|
28
|
+
DELETE FROM public.user_hwids WHERE id = user_id;
|
|
29
|
+
|
|
30
|
+
-- Delete profile activity
|
|
31
|
+
DELETE FROM public."profileActivities"
|
|
32
|
+
WHERE uid = (SELECT uid FROM public.profiles WHERE id = user_id);
|
|
33
|
+
|
|
34
|
+
-- Finally, delete the profile
|
|
35
|
+
DELETE FROM public.profiles WHERE id = user_id;
|
|
36
|
+
|
|
37
|
+
-- Check if deletion was successful
|
|
38
|
+
success := NOT EXISTS (SELECT 1 FROM public.profiles WHERE id = user_id);
|
|
39
|
+
|
|
40
|
+
RETURN success;
|
|
41
|
+
END;
|
|
42
|
+
$function$
|
|
@@ -5,9 +5,12 @@ CREATE OR REPLACE FUNCTION public.admin_remove_all_scores(user_id integer)
|
|
|
5
5
|
AS $function$
|
|
6
6
|
DECLARE
|
|
7
7
|
deleted_count INTEGER;
|
|
8
|
-
BEGIN
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
BEGIN
|
|
9
|
+
DELETE FROM public.leaderboard_map_user
|
|
10
|
+
WHERE "userId" = user_id;
|
|
11
|
+
|
|
12
|
+
-- Delete all scores for this user and count them
|
|
13
|
+
WITH deleted AS (
|
|
11
14
|
DELETE FROM public.scores
|
|
12
15
|
WHERE "userId" = user_id
|
|
13
16
|
RETURNING *
|