Skip to content

Commit

Permalink
Add forum tests, change getRoomLeaderboard() to return user_score
Browse files Browse the repository at this point in the history
  • Loading branch information
TTTaevas committed Mar 31, 2024
1 parent f4b7789 commit 7c29a02
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 34 deletions.
1 change: 1 addition & 0 deletions lib/forum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ export namespace Forum {
* @param topic The topic or the id of the topic you're making your reply in
* @param text Your reply! Your message!
* @returns The reply you've made, as a Forum.Post!
* @remarks Replying when the last post was made by the authorized user will likely cause the server to return a 403
*/
export async function reply(this: API, topic: Topic["id"] | Topic, text: string): Promise<Post> {
return await this.request("post", `forums/topics/${getId(topic)}/reply`, {body: text})
Expand Down
2 changes: 1 addition & 1 deletion lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@ export class API {
readonly getRooms = Multiplayer.Room.getMultiple

/** {@inheritDoc Multiplayer.Room.getOne} @group Multiplayer Functions */
readonly getRoomLeaderboard = Multiplayer.Room.getLeaderboard
readonly getRoomLeaderboard = Multiplayer.Room.Leader.getMultiple

/** {@inheritDoc Multiplayer.Room.getOne} @group Multiplayer Functions */
readonly getPlaylistItemScores = Multiplayer.Room.PlaylistItem.getScores
Expand Down
40 changes: 23 additions & 17 deletions lib/multiplayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export namespace Multiplayer {
max_attempts: number | null
name: string
participant_count: number
playlist: Multiplayer.Room.PlaylistItem[]
playlist: Room.PlaylistItem[]
queue_mode: string
recent_participants: User[]
starts_at: Date
Expand Down Expand Up @@ -99,11 +99,27 @@ export namespace Multiplayer {
user: User.WithCountry
}

export namespace Leader {
export interface WithPosition extends Leader {
position: number
}

/**
* Get the room stats of all the users of that room!
* @scope {@link Scope"public"}
* @param room The room or the id of the room in question
* @returns An object with the leaderboard, and the score and position of the authorized user under `user_score`
*/
export async function getMultiple(this: API, room: number | Room): Promise<{leaderboard: Leader[], user_score: Leader.WithPosition | null}> {
return await this.request("get", `rooms/${getId(room)}/leaderboard`)
}
}

/**
* Get data about a lazer multiplayer room (realtime or playlists)!
* @param room The room or the id of the room, can be found at the end of its URL (after `/multiplayer/rooms/`)
*/
export async function getOne(this: API, room: number | Multiplayer.Room): Promise<Multiplayer.Room> {
export async function getOne(this: API, room: number | Room): Promise<Room> {
return await this.request("get", `rooms/${getId(room)}`)
}

Expand All @@ -116,19 +132,9 @@ export namespace Multiplayer {
* @param sort Sort (where most recent is first) by creation date or end date, defaults to the creation date
*/
export async function getMultiple(this: API, type: "playlists" | "realtime", mode: "active" | "all" | "ended" | "participated" | "owned",
limit: number = 10, sort: "ended" | "created" = "created"): Promise<Multiplayer.Room[]> {
limit: number = 10, sort: "ended" | "created" = "created"): Promise<Room[]> {
return await this.request("get", "rooms", {type_group: type, mode, limit, sort})
}

/**
* Get the room stats of all the users of that room!
* @scope {@link Scope"public"}
* @param room The room or the id of the room in question
*/
export async function getLeaderboard(this: API, room: number | Multiplayer.Room): Promise<Multiplayer.Room.Leader[]> {
const response = await this.request("get", `rooms/${getId(room)}/leaderboard`)
return response.leaderboard
}
}

/** @obtainableFrom {@link API.getMatch} */
Expand Down Expand Up @@ -177,8 +183,8 @@ export namespace Multiplayer {
* Get data of a multiplayer lobby from the stable (non-lazer) client that have URLs with `community/matches` or `mp`
* @param match The id of a match can be found at the end of its URL
*/
export async function getOne(this: API, match: Match.Info["id"] | Match.Info): Promise<Multiplayer.Match> {
const response = await this.request("get", `matches/${getId(match)}`) as Multiplayer.Match
export async function getOne(this: API, match: Info["id"] | Info): Promise<Match> {
const response = await this.request("get", `matches/${getId(match)}`) as Match
// Fix `events[i].game.scores[e].perfect` being a number instead of a boolean
for (let i = 0; i < response.events.length; i++) {
for (let e = 0; e < Number(response.events[i].game?.scores.length); e++) {
Expand All @@ -198,12 +204,12 @@ export namespace Multiplayer {
* @remarks You can use this argument differently to get all matches before/after (depending of `query.sort`) a certain match,
* by adding +1/-1 to its id! So if you want all matches after match_id 10 with sorting is_desc, just have this argument be 10 + 1, or 11!
*/
first_match_in_array?: Match.Info["id"] | Match.Info
first_match_in_array?: Info["id"] | Info
/** The maximum amount of elements returned in the array (defaults to **50**) */
limit?: number
/** "id_desc" has the biggest id (most recent start_time) at the beginning of the array, "id_asc" is the opposite (defaults to **id_desc**) */
sort?: "id_desc" | "id_asc"
}): Promise<Multiplayer.Match.Info[]> {
}): Promise<Info[]> {
// `first_match_in_array` is a cool way to use the endpoint's cursor
const cursor = query?.first_match_in_array ? {match_id: getId(query.first_match_in_array) + (query?.sort === "id_asc" ? -1 : 1)} : undefined
const response = await this.request("get", "matches", {cursor, limit: query?.limit, sort: query?.sort})
Expand Down
33 changes: 21 additions & 12 deletions lib/tests/test_authorized.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ function validate(object: unknown, schemaName: string): boolean {
const testChat = async (): Promise<boolean> => {
let okay = true
console.log("\n===> CHAT")
if (server === "https://osu.ppy.sh") console.warn("⚠️ DOING THE TESTS ON THE ACTUAL OSU SERVER")

const a = await attempt(api.getChatChannels)
if (!isOk(a, !a || (validate(a, "Chat.Channel")))) okay = false
Expand Down Expand Up @@ -127,15 +126,23 @@ const testChat = async (): Promise<boolean> => {
return okay
}

// const testForum = async (): Promise<boolean> => {
// let okay = true
// console.log("\n===> FORUM")

// const a = await attempt(api.getSpotlights)
// if (!isOk(a, !a || (a.length >= 132 && validate(a, "Spotlight")))) okay = false
const testForum = async (): Promise<boolean> => {
let okay = true
console.log("\n===> FORUM")
const a = await attempt(api.createForumTopic, 85, "osu-api-v2-js test post", `Please ignore this forum post
It was automatically made for the sole purpose of testing [url=https://github.com/TTTaevas/osu-api-v2-js]osu-api-v2-js[/url]`,
{title: "test poll", options: ["yes", "maybe", "no"], length_days: 14, vote_change: true})
if (!isOk(a, !a || (validate(a.topic, "Forum.Topic") && validate(a.post, "Forum.Post")))) okay = false

if (a) {
const b = await attempt(api.editForumTopicTitle, a.topic, "osu-api-v2-js test post!")
if (!isOk(b, !b || (b.title === "osu-api-v2-js test post!" && validate(b, "Forum.Topic")))) okay = false
const c = await attempt(api.editForumPost, a.post, a.post.body.raw + " <3")
if (!isOk(c, !c || (c.body.raw === a.post.body.raw + " <3" && validate(c, "Forum.Post")))) okay = false
}

// return okay
// }
return okay
}

const testMultiplayer = async (): Promise<boolean> => {
let okay = true
Expand All @@ -148,11 +155,11 @@ const testMultiplayer = async (): Promise<boolean> => {

if (a1 && a1.length) {
const b1 = await attempt(api.getRoomLeaderboard, a1[0])
if (!isOk(b1, !b1 || (validate(b1, "Multiplayer.Room.Leader")))) okay = false
if (!isOk(b1, !b1 || (validate(b1.leaderboard, "Multiplayer.Room.Leader")))) okay = false
}
if (a2 && a2.length) {
const b2 = await attempt(api.getRoomLeaderboard, a2[0])
if (!isOk(b2, !b2 || (validate(b2, "Multiplayer.Room.Leader")))) okay = false
if (!isOk(b2, !b2 || (validate(b2.leaderboard, "Multiplayer.Room.Leader")))) okay = false
}

return okay
Expand Down Expand Up @@ -185,6 +192,8 @@ const testUser = async (): Promise<boolean> => {
}

const test = async (id: number | string | undefined, secret: string | undefined, redirect_uri: string | undefined): Promise<void> => {
if (server === "https://osu.ppy.sh") console.warn("⚠️ DOING THE TESTS ON THE ACTUAL OSU SERVER")

if (id === undefined) {throw new Error("no ID env var")}
if (secret === undefined) {throw new Error("no SECRET env var")}
if (redirect_uri === undefined) {throw new Error("no REDIRECT_URI env var")}
Expand All @@ -197,7 +206,7 @@ const test = async (id: number | string | undefined, secret: string | undefined,

const tests = [
testChat,
// testForum,
testForum,
testMultiplayer,
testScore,
testUser
Expand Down
2 changes: 1 addition & 1 deletion lib/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ export namespace User {
export async function getMultiple(this: API, users: Array<User["id"] | User>): Promise<User.WithCountryCoverGroupsStatisticsrulesets[]> {
const ids = users.map((user) => getId(user))
const response = await this.request("get", "users", {ids})
return response.users
return response.users // It's the only property
}

/**
Expand Down
6 changes: 3 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==

"@types/node@*", "@types/node@^20.8.10":
version "20.11.30"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.30.tgz#9c33467fc23167a347e73834f788f4b9f399d66f"
integrity sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==
version "20.12.2"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.2.tgz#9facdd11102f38b21b4ebedd9d7999663343d72e"
integrity sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==
dependencies:
undici-types "~5.26.4"

Expand Down

0 comments on commit 7c29a02

Please sign in to comment.