rhythia-api 182.0.0 → 183.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.
Files changed (58) hide show
  1. package/.prettierrc.json +6 -6
  2. package/api/addCollectionMap.ts +82 -82
  3. package/api/approveMap.ts +78 -78
  4. package/api/chartPublicStats.ts +32 -32
  5. package/api/createBeatmap.ts +168 -156
  6. package/api/createBeatmapPage.ts +64 -64
  7. package/api/createClan.ts +81 -81
  8. package/api/createCollection.ts +58 -58
  9. package/api/deleteBeatmapPage.ts +77 -72
  10. package/api/deleteCollection.ts +59 -59
  11. package/api/deleteCollectionMap.ts +71 -71
  12. package/api/editAboutMe.ts +91 -91
  13. package/api/editClan.ts +90 -90
  14. package/api/editCollection.ts +77 -77
  15. package/api/editProfile.ts +123 -123
  16. package/api/getAvatarUploadUrl.ts +85 -85
  17. package/api/getBadgedUsers.ts +56 -56
  18. package/api/getBeatmapComments.ts +57 -57
  19. package/api/getBeatmapPage.ts +106 -106
  20. package/api/getBeatmapPageById.ts +99 -99
  21. package/api/getBeatmapStarRating.ts +53 -53
  22. package/api/getBeatmaps.ts +159 -159
  23. package/api/getClan.ts +77 -77
  24. package/api/getCollection.ts +130 -130
  25. package/api/getCollections.ts +128 -126
  26. package/api/getLeaderboard.ts +136 -136
  27. package/api/getMapUploadUrl.ts +93 -93
  28. package/api/getPassToken.ts +55 -55
  29. package/api/getProfile.ts +146 -146
  30. package/api/getPublicStats.ts +180 -180
  31. package/api/getRawStarRating.ts +57 -57
  32. package/api/getScore.ts +85 -85
  33. package/api/getTimestamp.ts +23 -23
  34. package/api/getUserScores.ts +175 -175
  35. package/api/nominateMap.ts +82 -69
  36. package/api/postBeatmapComment.ts +59 -59
  37. package/api/rankMapsArchive.ts +64 -64
  38. package/api/searchUsers.ts +56 -56
  39. package/api/setPasskey.ts +59 -59
  40. package/api/submitScore.ts +433 -433
  41. package/api/updateBeatmapPage.ts +229 -229
  42. package/handleApi.ts +20 -20
  43. package/index.html +2 -2
  44. package/index.ts +865 -864
  45. package/package.json +2 -2
  46. package/types/database.ts +39 -0
  47. package/utils/getUserBySession.ts +48 -48
  48. package/utils/requestUtils.ts +87 -87
  49. package/utils/security.ts +20 -20
  50. package/utils/star-calc/index.ts +72 -72
  51. package/utils/star-calc/osuUtils.ts +53 -53
  52. package/utils/star-calc/sspmParser.ts +398 -398
  53. package/utils/star-calc/sspmv1Parser.ts +165 -165
  54. package/utils/supabase.ts +13 -13
  55. package/utils/test +4 -4
  56. package/utils/validateToken.ts +7 -7
  57. package/vercel.json +12 -12
  58. package/package-lock.json +0 -8913
package/.prettierrc.json CHANGED
@@ -1,6 +1,6 @@
1
- {
2
- "trailingComma": "es5",
3
- "tabWidth": 2,
4
- "semi": true,
5
- "singleQuote": false
6
- }
1
+ {
2
+ "trailingComma": "es5",
3
+ "tabWidth": 2,
4
+ "semi": true,
5
+ "singleQuote": false
6
+ }
@@ -1,82 +1,82 @@
1
- import { NextResponse } from "next/server";
2
- import z from "zod";
3
- import { protectedApi, validUser } from "../utils/requestUtils";
4
- import { supabase } from "../utils/supabase";
5
- import { getUserBySession } from "../utils/getUserBySession";
6
- import { User } from "@supabase/supabase-js";
7
-
8
- export const Schema = {
9
- input: z.strictObject({
10
- session: z.string(),
11
- collection: z.number(),
12
- beatmapPage: z.number(),
13
- }),
14
- output: z.object({
15
- error: z.string().optional(),
16
- }),
17
- };
18
-
19
- export async function POST(request: Request) {
20
- return protectedApi({
21
- request,
22
- schema: Schema,
23
- authorization: validUser,
24
- activity: handler,
25
- });
26
- }
27
-
28
- export async function handler(data: (typeof Schema)["input"]["_type"]) {
29
- const user = (await getUserBySession(data.session)) as User;
30
- let { data: queryUserData, error: userError } = await supabase
31
- .from("profiles")
32
- .select("*")
33
- .eq("uid", user.id)
34
- .single();
35
-
36
- if (!queryUserData) {
37
- return NextResponse.json({ error: "Can't find user" });
38
- }
39
-
40
- let { data: queryCollectionRelation, error: collectionRelationError } =
41
- await supabase
42
- .from("collectionRelations")
43
- .select("*")
44
- .eq("collection", data.collection)
45
- .eq("beatmapPage", data.beatmapPage)
46
- .single();
47
-
48
- if (queryCollectionRelation) {
49
- return NextResponse.json({ error: "Map already in collection" });
50
- }
51
-
52
- let { data: queryCollectionData, error: collectionError } = await supabase
53
- .from("beatmapCollections")
54
- .select("*")
55
- .eq("id", data.collection)
56
- .single();
57
-
58
- let { data: queryBeatmapData, error: beatmapData } = await supabase
59
- .from("beatmapPages")
60
- .select("*")
61
- .eq("id", data.beatmapPage)
62
- .single();
63
-
64
- if (!queryCollectionData) {
65
- return NextResponse.json({ error: "Can't find collection" });
66
- }
67
-
68
- if (!queryBeatmapData) {
69
- return NextResponse.json({ error: "Can't find beatmap page" });
70
- }
71
-
72
- if (queryCollectionData.owner !== queryUserData.id) {
73
- return NextResponse.json({ error: "You can't update foreign collections" });
74
- }
75
-
76
- await supabase.from("collectionRelations").insert({
77
- collection: data.collection,
78
- beatmapPage: data.beatmapPage,
79
- });
80
-
81
- return NextResponse.json({});
82
- }
1
+ import { NextResponse } from "next/server";
2
+ import z from "zod";
3
+ import { protectedApi, validUser } from "../utils/requestUtils";
4
+ import { supabase } from "../utils/supabase";
5
+ import { getUserBySession } from "../utils/getUserBySession";
6
+ import { User } from "@supabase/supabase-js";
7
+
8
+ export const Schema = {
9
+ input: z.strictObject({
10
+ session: z.string(),
11
+ collection: z.number(),
12
+ beatmapPage: z.number(),
13
+ }),
14
+ output: z.object({
15
+ error: z.string().optional(),
16
+ }),
17
+ };
18
+
19
+ export async function POST(request: Request) {
20
+ return protectedApi({
21
+ request,
22
+ schema: Schema,
23
+ authorization: validUser,
24
+ activity: handler,
25
+ });
26
+ }
27
+
28
+ export async function handler(data: (typeof Schema)["input"]["_type"]) {
29
+ const user = (await getUserBySession(data.session)) as User;
30
+ let { data: queryUserData, error: userError } = await supabase
31
+ .from("profiles")
32
+ .select("*")
33
+ .eq("uid", user.id)
34
+ .single();
35
+
36
+ if (!queryUserData) {
37
+ return NextResponse.json({ error: "Can't find user" });
38
+ }
39
+
40
+ let { data: queryCollectionRelation, error: collectionRelationError } =
41
+ await supabase
42
+ .from("collectionRelations")
43
+ .select("*")
44
+ .eq("collection", data.collection)
45
+ .eq("beatmapPage", data.beatmapPage)
46
+ .single();
47
+
48
+ if (queryCollectionRelation) {
49
+ return NextResponse.json({ error: "Map already in collection" });
50
+ }
51
+
52
+ let { data: queryCollectionData, error: collectionError } = await supabase
53
+ .from("beatmapCollections")
54
+ .select("*")
55
+ .eq("id", data.collection)
56
+ .single();
57
+
58
+ let { data: queryBeatmapData, error: beatmapData } = await supabase
59
+ .from("beatmapPages")
60
+ .select("*")
61
+ .eq("id", data.beatmapPage)
62
+ .single();
63
+
64
+ if (!queryCollectionData) {
65
+ return NextResponse.json({ error: "Can't find collection" });
66
+ }
67
+
68
+ if (!queryBeatmapData) {
69
+ return NextResponse.json({ error: "Can't find beatmap page" });
70
+ }
71
+
72
+ if (queryCollectionData.owner !== queryUserData.id) {
73
+ return NextResponse.json({ error: "You can't update foreign collections" });
74
+ }
75
+
76
+ await supabase.from("collectionRelations").insert({
77
+ collection: data.collection,
78
+ beatmapPage: data.beatmapPage,
79
+ });
80
+
81
+ return NextResponse.json({});
82
+ }
package/api/approveMap.ts CHANGED
@@ -1,78 +1,78 @@
1
- import { NextResponse } from "next/server";
2
- import z from "zod";
3
- import { protectedApi, validUser } from "../utils/requestUtils";
4
- import { supabase } from "../utils/supabase";
5
- import { getUserBySession } from "../utils/getUserBySession";
6
- import { User } from "@supabase/supabase-js";
7
-
8
- export const Schema = {
9
- input: z.strictObject({
10
- session: z.string(),
11
- mapId: z.number(),
12
- }),
13
- output: z.object({
14
- error: z.string().optional(),
15
- }),
16
- };
17
-
18
- export async function POST(request: Request) {
19
- return protectedApi({
20
- request,
21
- schema: Schema,
22
- authorization: validUser,
23
- activity: handler,
24
- });
25
- }
26
-
27
- export async function handler(data: (typeof Schema)["input"]["_type"]) {
28
- const user = (await getUserBySession(data.session)) as User;
29
- let { data: queryUserData, error: userError } = await supabase
30
- .from("profiles")
31
- .select("*")
32
- .eq("uid", user.id)
33
- .single();
34
-
35
- if (!queryUserData) {
36
- return NextResponse.json({ error: "Can't find user" });
37
- }
38
-
39
- const tags = (queryUserData?.badges || []) as string[];
40
-
41
- if (!tags.includes("MMT")) {
42
- return NextResponse.json({ error: "Only MMTs can approve maps!" });
43
- }
44
-
45
- const { data: mapData, error } = await supabase
46
- .from("beatmapPages")
47
- .select("id,nominations,owner")
48
- .eq("id", data.mapId)
49
- .single();
50
-
51
- if (!mapData) {
52
- return NextResponse.json({ error: "Bad map" });
53
- }
54
-
55
- if (mapData.owner == queryUserData.id) {
56
- return NextResponse.json({ error: "Can't approve own map" });
57
- }
58
-
59
- if ((mapData.nominations as number[])!.length < 2) {
60
- return NextResponse.json({
61
- error: "Maps can get approved only if they have 2 nominations",
62
- });
63
- }
64
-
65
- if ((mapData.nominations as number[]).includes(queryUserData.id)) {
66
- return NextResponse.json({
67
- error: "Can't nominate and approve",
68
- });
69
- }
70
-
71
- await supabase.from("beatmapPages").upsert({
72
- id: data.mapId,
73
- status: "RANKED",
74
- ranked_at: Date.now(),
75
- });
76
-
77
- return NextResponse.json({});
78
- }
1
+ import { NextResponse } from "next/server";
2
+ import z from "zod";
3
+ import { protectedApi, validUser } from "../utils/requestUtils";
4
+ import { supabase } from "../utils/supabase";
5
+ import { getUserBySession } from "../utils/getUserBySession";
6
+ import { User } from "@supabase/supabase-js";
7
+
8
+ export const Schema = {
9
+ input: z.strictObject({
10
+ session: z.string(),
11
+ mapId: z.number(),
12
+ }),
13
+ output: z.object({
14
+ error: z.string().optional(),
15
+ }),
16
+ };
17
+
18
+ export async function POST(request: Request) {
19
+ return protectedApi({
20
+ request,
21
+ schema: Schema,
22
+ authorization: validUser,
23
+ activity: handler,
24
+ });
25
+ }
26
+
27
+ export async function handler(data: (typeof Schema)["input"]["_type"]) {
28
+ const user = (await getUserBySession(data.session)) as User;
29
+ let { data: queryUserData, error: userError } = await supabase
30
+ .from("profiles")
31
+ .select("*")
32
+ .eq("uid", user.id)
33
+ .single();
34
+
35
+ if (!queryUserData) {
36
+ return NextResponse.json({ error: "Can't find user" });
37
+ }
38
+
39
+ const tags = (queryUserData?.badges || []) as string[];
40
+
41
+ if (!tags.includes("MMT")) {
42
+ return NextResponse.json({ error: "Only MMTs can approve maps!" });
43
+ }
44
+
45
+ const { data: mapData, error } = await supabase
46
+ .from("beatmapPages")
47
+ .select("id,nominations,owner")
48
+ .eq("id", data.mapId)
49
+ .single();
50
+
51
+ if (!mapData) {
52
+ return NextResponse.json({ error: "Bad map" });
53
+ }
54
+
55
+ if (mapData.owner == queryUserData.id) {
56
+ return NextResponse.json({ error: "Can't approve own map" });
57
+ }
58
+
59
+ if ((mapData.nominations as number[])!.length < 2) {
60
+ return NextResponse.json({
61
+ error: "Maps can get approved only if they have 2 nominations",
62
+ });
63
+ }
64
+
65
+ if ((mapData.nominations as number[]).includes(queryUserData.id)) {
66
+ return NextResponse.json({
67
+ error: "Can't nominate and approve",
68
+ });
69
+ }
70
+
71
+ await supabase.from("beatmapPages").upsert({
72
+ id: data.mapId,
73
+ status: "RANKED",
74
+ ranked_at: Date.now(),
75
+ });
76
+
77
+ return NextResponse.json({});
78
+ }
@@ -1,32 +1,32 @@
1
- import { NextResponse } from "next/server";
2
- import z from "zod";
3
- import { protectedApi } from "../utils/requestUtils";
4
- import { supabase } from "../utils/supabase";
5
-
6
- export const Schema = {
7
- input: z.strictObject({}),
8
- output: z.object({}),
9
- };
10
-
11
- export async function POST(request: Request) {
12
- return protectedApi({
13
- request,
14
- schema: Schema,
15
- authorization: () => {},
16
- activity: handler,
17
- });
18
- }
19
-
20
- export async function handler(data: (typeof Schema)["input"]["_type"]) {
21
- // 30 minutes activity
22
- const countOnline = await supabase
23
- .from("profileActivities")
24
- .select("*", { count: "exact", head: true })
25
- .gt("last_activity", Date.now() - 1800000);
26
-
27
- await supabase.from("chartedValues").insert({
28
- type: "online_players",
29
- value: countOnline.count,
30
- });
31
- return NextResponse.json({});
32
- }
1
+ import { NextResponse } from "next/server";
2
+ import z from "zod";
3
+ import { protectedApi } from "../utils/requestUtils";
4
+ import { supabase } from "../utils/supabase";
5
+
6
+ export const Schema = {
7
+ input: z.strictObject({}),
8
+ output: z.object({}),
9
+ };
10
+
11
+ export async function POST(request: Request) {
12
+ return protectedApi({
13
+ request,
14
+ schema: Schema,
15
+ authorization: () => {},
16
+ activity: handler,
17
+ });
18
+ }
19
+
20
+ export async function handler(data: (typeof Schema)["input"]["_type"]) {
21
+ // 30 minutes activity
22
+ const countOnline = await supabase
23
+ .from("profileActivities")
24
+ .select("*", { count: "exact", head: true })
25
+ .gt("last_activity", Date.now() - 1800000);
26
+
27
+ await supabase.from("chartedValues").insert({
28
+ type: "online_players",
29
+ value: countOnline.count,
30
+ });
31
+ return NextResponse.json({});
32
+ }