Skip to content

Commit

Permalink
Small adjustments & fix Comment's user_id not being marked as pos…
Browse files Browse the repository at this point in the history
…sibly null

The documentation given by osu does NOT say it can be null btw, guess they forgot about this rare case
  • Loading branch information
TTTaevas committed Apr 16, 2024
1 parent 19028cf commit 16f003e
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 26 deletions.
4 changes: 4 additions & 0 deletions lib/beatmap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ export namespace Beatmap {
}

export interface WithBeatmapsetChecksumMaxcombo extends WithBeatmapset, WithChecksum {
/**
* @privateRemarks I had a single instance of this being null, on beatmap 2124608, specifically on the dev server (it's okay on osu server)
* For the sake of convenience, I cross my fingers that I won't regret not marking this as potentially null
*/
max_combo: number
}

Expand Down
32 changes: 16 additions & 16 deletions lib/comment.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
import { API, Beatmapset, Changelog, NewsPost, User } from "./index.js"
import { getId } from "./misc.js"

/** Remove so-called "Deleted Items" / items that lack an id, add a "deleted_commentable_meta" and make it the number of removed objects */
function removeDeletedItems<T extends Comment.Bundle>(bundle: T): T {
const commentable_meta = bundle.commentable_meta.filter((c) => c.id)
bundle.deleted_commentable_meta = bundle.commentable_meta.length - commentable_meta.length
bundle.commentable_meta = commentable_meta
return bundle
}

export interface Comment {
id: number
parent_id: number | null
user_id: User["id"]
/**
* @remarks Is null if the author of the comment from the old comment system has no associated osu! user, presumably
* @privateRemarks Example is comment 178966 from beatmapset 349238
*/
user_id: User["id"] | null
pinned: boolean
replies_count: number
votes_count: number
Expand Down Expand Up @@ -79,13 +91,7 @@ export namespace Comment {
* @param comment The comment in question
*/
export async function getOne(this: API, comment: Comment["id"] | Comment): Promise<Bundle> {
const bundle = await this.request("get", `comments/${getId(comment)}`) as Bundle
// Remove so-called "Deleted Items" / items that lack an id, add a "deleted_commentable_meta" and make it the number of removed objects
const commentable_meta = bundle.commentable_meta.filter((c) => c.id)
bundle.deleted_commentable_meta = bundle.commentable_meta.length - commentable_meta.length
bundle.commentable_meta = commentable_meta

return bundle
return removeDeletedItems(await this.request("get", `comments/${getId(comment)}`))
}

/**
Expand All @@ -99,15 +105,9 @@ export namespace Comment {
const after = sort?.after ? String(getId(sort.after)) : undefined
const parent_id = parent ? String(getId(parent)) : undefined

const bundle = await this.request("get", "comments", {
return removeDeletedItems(await this.request("get", "comments", {
after, commentable_type: from?.type, commentable_id: from?.id,
cursor: sort?.cursor, parent_id, sort: sort?.type
})
// Remove so-called "Deleted Items" / items that lack an id, add a "deleted_commentable_meta" and make it the number of removed objects
const commentable_meta = bundle.commentable_meta.filter((c: any) => c.id)
bundle.deleted_commentable_meta = bundle.commentable_meta.length - commentable_meta.length
bundle.commentable_meta = commentable_meta

return bundle
}))
}
}
2 changes: 1 addition & 1 deletion lib/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export namespace Event {
/**
* Get everything note-worthy that happened on osu! recently!
* @param sort "id_asc" to have the oldest recent event first, "id_desc" to have the newest instead (defaults to **id_desc**)
* @param cursor_string Use a response's `cursor_string` with the same parameters to get the next "page" of results, so `posts` in this instance!
* @param cursor_string Use a response's `cursor_string` with the same parameters to get the next "page" of results, so `events` in this instance!
*/
export async function getMultiple(this: API, sort: "id_desc" | "id_asc" = "id_desc", cursor_string?: string):
Promise<{events: Event.Any[], cursor_string: string | null}> {
Expand Down
22 changes: 13 additions & 9 deletions lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ export class APIError {
export class API {
// ACCESS TOKEN STUFF

/** The key that allows you to talk with the API */
access_token: string = ""

/** Should always be "Bearer" */
Expand Down Expand Up @@ -145,11 +146,14 @@ export class API {
this.updateRefreshTimeout() // because the refresh token may be specified last
}

/** If true, upon failing a request due to a 401, it will use the `refresh_token` if it exists (defaults to **true**) */
/** If true, upon failing a request due to a 401, it will use the {@link API.refresh_token} if it exists (defaults to **true**) */
refresh_on_401: boolean = true

private _refresh_on_expires: boolean = true
/** If true, the application will silently use the `refresh_token` right before the `access_token` expires, as determined by `expires` (defaults to **true**) */
/**
* If true, the application will silently use the {@link API.refresh_token} right before the {@link API.access_token} expires,
* as determined by {@link API.expires} (defaults to **true**)
*/
get refresh_on_expires(): boolean {
return this._refresh_on_expires
}
Expand All @@ -163,7 +167,7 @@ export class API {
return this._refresh_timeout
}
set refresh_timeout(timeout: NodeJS.Timeout) {
// if a previous refresh_timeout already exists, clear it
// if a previous one already exists, clear it
if (this._refresh_timeout) {
clearTimeout(this._refresh_timeout)
}
Expand All @@ -186,7 +190,7 @@ export class API {
server: string = "https://osu.ppy.sh"
/** The osu! user id of the user who went through the Authorization Code Grant */
user?: User["id"]
/** The scopes your application have, assuming it acts as a user */
/** The {@link Scope}s your application has, assuming it acts as a user */
scopes?: Scope[]


Expand All @@ -209,9 +213,9 @@ export class API {
delay: number
/** How many retries maximum before throwing an {@link APIError} (defaults to **5**) */
maximum_amount: number
/** Should it retry a request upon successfully refreshing the token due to `refresh_on_401` being `true`? (defaults to **true**) */
/** Should it retry a request upon successfully refreshing the token due to {@link API.refresh_on_401} being `true`? (defaults to **true**) */
on_automatic_refresh: boolean
/** Should it retry a request if that request failed because it has been aborted by the `timeout`? (defaults to **false**) */
/** Should it retry a request if that request failed because it has been aborted by the {@link API.timeout}? (defaults to **false**) */
on_timeout: boolean
/** Upon failing a request and receiving a response, because of which received status code should the request be retried? (defaults to **[429]**) */
on_status_codes: number[]
Expand All @@ -226,7 +230,7 @@ export class API {


/**
* **Please use {@link API.createAsync} instead of the default constructor** if you don't have at least an `access_token`!
* **Please use {@link API.createAsync} instead of the default constructor** if you don't have at least an {@link API.access_token}!
* An API object without an `access_token` is pretty much useless!
*/
constructor(properties: Partial<API>) {
Expand All @@ -250,7 +254,7 @@ export class API {
user?: {
/** The Application Callback URL; Where the User has been redirected to after saying "okay" to your application doing stuff */
redirect_uri: string,
/** The code that appeared as a GET argument when they got redirected to the Application Callback URl (`redirect_url`) */
/** The code that appeared as a GET argument when they got redirected to the Application Callback URL (`redirect_uri`) */
code: string
},
verbose?: "none" | "errors" | "all",
Expand All @@ -274,7 +278,7 @@ export class API {
/**
* Get a websocket to get WebSocket events from!
* @param server Where the "notification websocket/server" is
* (defaults to **the api's `server`'s protocol and a maximum of 1 subdomain being replaced by "wss://notify."** (so usually `wss://notify.ppy.sh`))
* (defaults to **the {@link API.server}'s protocol and a maximum of 1 subdomain being replaced by "wss://notify."** (so usually `wss://notify.ppy.sh`))
*/
public generateWebSocket(server: string = `${this.server.replace(/^\w*:\/\/(?:[A-Za-z0-9]+[.](?=[A-Za-z0-9]+[.]([A-Za-z0-9]+)$))?/g, "wss://notify.")}`):
WebSocket {
Expand Down

0 comments on commit 16f003e

Please sign in to comment.