From 9138fd118adc306de9ee8b5ea3e2cc19a76e29a8 Mon Sep 17 00:00:00 2001 From: Taevas <67872932+TTTaevas@users.noreply.github.com> Date: Wed, 22 Nov 2023 18:12:54 +0100 Subject: [PATCH] Some code cleaning --- docs/assets/navigation.js | 2 +- docs/assets/search.js | 2 +- docs/classes/API.html | 138 +++++++----- docs/classes/APIError.html | 4 +- docs/enums/RankStatus.html | 4 +- docs/enums/Rulesets.html | 4 +- docs/functions/generateAuthorizationURL.html | 2 +- docs/index.html | 99 ++++++++- docs/interfaces/Beatmap.html | 5 +- .../BeatmapDifficultyAttributes.html | 5 +- .../BeatmapDifficultyAttributesFruits.html | 4 +- .../BeatmapDifficultyAttributesMania.html | 6 +- .../BeatmapDifficultyAttributesOsu.html | 4 +- .../BeatmapDifficultyAttributesTaiko.html | 4 +- docs/interfaces/BeatmapExtended.html | 4 +- .../BeatmapExtendedWithFailtimes.html | 4 +- ...tendedWithFailtimesBeatmapsetextended.html | 4 +- docs/interfaces/BeatmapPack.html | 8 +- docs/interfaces/BeatmapPlaycount.html | 7 + docs/interfaces/BeatmapUserScore.html | 4 +- docs/interfaces/BeatmapWithBeatmapset.html | 4 +- ...BeatmapWithBeatmapsetChecksumMaxcombo.html | 4 +- docs/interfaces/Beatmapset.html | 16 +- docs/interfaces/BeatmapsetExtended.html | 18 +- docs/interfaces/BeatmapsetExtendedPlus.html | 26 +-- ...BeatmapsetExtendedWithBeatmapExtended.html | 42 ++++ ...elogBuildWithChangelogentriesVersions.html | 10 +- .../ChangelogBuildWithUpdatestreams.html | 10 +- ...uildWithUpdatestreamsChangelogentries.html | 10 +- docs/interfaces/Event.html | 3 + docs/interfaces/EventAchievement.html | 9 + docs/interfaces/EventBeatmap.html | 7 + docs/interfaces/EventBeatmapPlaycount.html | 9 + docs/interfaces/EventBeatmapset.html | 7 + docs/interfaces/EventBeatmapsetApprove.html | 11 + docs/interfaces/EventBeatmapsetDelete.html | 8 + docs/interfaces/EventBeatmapsetRevive.html | 10 + docs/interfaces/EventBeatmapsetUpdate.html | 10 + docs/interfaces/EventBeatmapsetUpload.html | 10 + docs/interfaces/EventRank.html | 15 ++ docs/interfaces/EventRankLost.html | 11 + docs/interfaces/EventUser.html | 5 + docs/interfaces/EventUserSupportAgain.html | 6 + docs/interfaces/EventUserSupportFirst.html | 6 + docs/interfaces/EventUserSupportGift.html | 6 + docs/interfaces/EventUsernameChange.html | 6 + docs/interfaces/KudosuHistory.html | 5 +- docs/interfaces/Leader.html | 4 +- docs/interfaces/Match.html | 6 +- docs/interfaces/MatchInfo.html | 4 +- docs/interfaces/MultiplayerScore.html | 6 +- docs/interfaces/MultiplayerScores.html | 8 +- docs/interfaces/PlaylistItem.html | 8 +- docs/interfaces/Rankings.html | 6 +- docs/interfaces/RankingsCountry.html | 8 +- docs/interfaces/RankingsSpotlight.html | 4 +- docs/interfaces/Room.html | 6 +- docs/interfaces/Score.html | 14 +- docs/interfaces/ScoreWithMatch.html | 14 +- docs/interfaces/ScoreWithUser.html | 14 +- docs/interfaces/ScoreWithUserBeatmap.html | 14 +- .../ScoreWithUserBeatmapBeatmapset.html | 14 +- docs/interfaces/SearchResultUser.html | 6 + docs/interfaces/SearchResultWiki.html | 6 + docs/interfaces/Spotlight.html | 6 +- .../SpotlightWithParticipantcount.html | 6 +- docs/interfaces/UpdateStream.html | 4 +- docs/interfaces/User.html | 6 +- docs/interfaces/UserExtended.html | 10 +- .../UserExtendedWithStatisticsrulesets.html | 10 +- docs/interfaces/UserStatistics.html | 9 +- .../UserStatisticsWithCountryrank.html | 8 +- docs/interfaces/UserStatisticsWithUser.html | 8 +- docs/interfaces/UserWithCountry.html | 4 +- docs/interfaces/UserWithCountryCover.html | 4 +- ...thCountryCoverGroupsStatisticsSupport.html | 4 +- ...hCountryCoverGroupsStatisticsrulesets.html | 4 +- docs/interfaces/UserWithKudosu.html | 4 +- docs/interfaces/WikiPage.html | 14 ++ docs/modules.html | 24 +- docs/types/Mod.html | 2 +- docs/types/ProfileBanner.html | 2 +- docs/types/Scope.html | 2 +- lib/beatmap.ts | 2 +- lib/index.ts | 210 ++++++++---------- lib/tests/test.ts | 98 ++++---- lib/user.ts | 3 + package.json | 2 +- 88 files changed, 766 insertions(+), 420 deletions(-) create mode 100644 docs/interfaces/BeatmapPlaycount.html create mode 100644 docs/interfaces/BeatmapsetExtendedWithBeatmapExtended.html create mode 100644 docs/interfaces/Event.html create mode 100644 docs/interfaces/EventAchievement.html create mode 100644 docs/interfaces/EventBeatmap.html create mode 100644 docs/interfaces/EventBeatmapPlaycount.html create mode 100644 docs/interfaces/EventBeatmapset.html create mode 100644 docs/interfaces/EventBeatmapsetApprove.html create mode 100644 docs/interfaces/EventBeatmapsetDelete.html create mode 100644 docs/interfaces/EventBeatmapsetRevive.html create mode 100644 docs/interfaces/EventBeatmapsetUpdate.html create mode 100644 docs/interfaces/EventBeatmapsetUpload.html create mode 100644 docs/interfaces/EventRank.html create mode 100644 docs/interfaces/EventRankLost.html create mode 100644 docs/interfaces/EventUser.html create mode 100644 docs/interfaces/EventUserSupportAgain.html create mode 100644 docs/interfaces/EventUserSupportFirst.html create mode 100644 docs/interfaces/EventUserSupportGift.html create mode 100644 docs/interfaces/EventUsernameChange.html create mode 100644 docs/interfaces/SearchResultUser.html create mode 100644 docs/interfaces/SearchResultWiki.html create mode 100644 docs/interfaces/WikiPage.html diff --git a/docs/assets/navigation.js b/docs/assets/navigation.js index d00a5ee..a8a7b93 100644 --- a/docs/assets/navigation.js +++ b/docs/assets/navigation.js @@ -1 +1 @@ -window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAA6WXT3PTMBDFv0vOHUo7tEBvSWihQztkGgIHhoPqbGJNbMkjrZgEpt8dyW7jP5HXUnrVvvd7krVSlF//RghbHF2NHpjYzJGh0aOTUcEwtWMgTK5P68qbFPPMljdcLEdXH55OarfJQAMeep/H+53j2W1tSjKmNehTO9h2nJ13PNdKSeU1lhXKPQGGOStqMxcIasUS63+ute3nF5eH9k98teKJyXA3RlT80SBoCunTHxlzowzH6LDKdWTkPROcxSaWpiMDv2kTG2ctR4Z9Z3wjY+NKU0Dg9RZBLGFJ8V80EbifHNMbxjPkOd14XsOxQc81e6QhYlkDiIDJzFiyoZJcPQCz0KDmiVRAsfaiAKBbWb0gitpWRqOnKSQbbfJ7tk1k/kh2K+0MiB5YStj8rSqk9RuyOOgsM2Tfd6QUfJoysYZMrieGZ2W37kdA2PMO+gcozaXwB4bb4yaxKJbMXjSogOWhyS3PK+K6KzgmvsugpvPVLKU2X7hGqXbesJaCQt0BW4LyMqoSZb5nmKReb1kZtN6Klf9s7qskwv7E8CJjO+qa6opigP59PFBRyJnVZXYXbhFyL60poEDuXcnF2j+ll2IIYCqNbTB/13Q0Ibh5ITHj69R/Bx6oSKSU/m/kCpSxf/cHt7wUuLPY38ptSRDM/SjSLKcIRlFvcJ8wFjzwQ0ZbyDCyOYKaYi9yE5gxhTzhBROYuBalsT4HFVVdx/PyOvaSmwIS1Lf9Q7vu6uQzoCkIBbnP4P6R2kuGJ1od/PfswfttQ6G1ozegloTDymdCdSkpe6UEsDuOuChyAw+lQ/DGXHqpDU0Ebir/EDPtCmPBn5U0ha7XOzdFIZX/1EX4XzuNwRYOBYRMpHpIkVGVhHxYyMZxxl3hXhGye4Dffnx/dnHefDsoueIZTJgQzU2u/K3iEMne4AV0CeXgkNO+RkHZS29sMJWK/7WfUIrFw10NWxmRuEF92qdtZ1y+e/r9H1yhTxVJEwAA" \ No newline at end of file +window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAA6WYyW7bMBCG38XnoGmCJm1zc9YGTVAjbppD0QMjjy3CEilwMeIWefeSkh0tJoekc+X8/zfcNBrp97+Rghc1Ohs9ELacKqK0HB2MKqJyMwZMl/KwjXzIVVmY8JKy2ejsy+tB69YFSFC73s243zme3LamrCBSgjw0g33H0fHAcyUEF05jHcHc50BUSarWTJkCMSeZ8W9iffvxyemu/ZLO5zTThVqPlRL0WSuQGNKl3zPNtdBUJSdrXHumvCeMktSMtWnPhD+kTk1nLHsm+0nokqemq00RCa9eFLAZzDD+VpOAe6Iqvya0ULTEL57TsG+iTcw80pCwrAAiYjITki2xTDYegynIOuOaKZS1FUUAHyWIacYFYMA3UQTQblW7Qxi1r0xGX+SQLaUu78lLxstn9PrjzojUgaXEzd+oYp6ljiwNOik0+iANpGnwzhYmLsLhxFJf5IQtoOCLc02L2vw2AszULpC/QEjKmXut8fa0STxWM2KKphJAytjMPc870g1XsE/6IQObztUKPBWmjgSt4yynsIISpXREQSDW8XQFsSC8jDqVsWhfpRhoEnDjqhJ85S7QbmkC/BIK8x6LYTfKBPQDrGjctBtlArq52THoRpmELjhxlzanMoi2Xx9+nI1GIe64RC7WVhFE2Ve5H2OjUYipriou1HhBKMNxXWUK+poKbMFDZQr6hs7jyFYYBWakhKbA4txWh2G/6xmX+huViou1E9hTYKg7IDPPgTchzHxPVJY7vXUkaL1lc3dX9hZFEeZrhVam/GIN6lCUAnS/RndUGNK+HQpzCrcKSietK8BA9vmlbOGe0jYYA7iw7yrPrRloYnDTiquCLnL387KjQpGcu/fIBjCj//SDR14LbCvkv8p9SRTMW0N7imgU1ty4hKngQGOCW9BkQESWP4A0j4x/TwaiWOATXdIg0IpQIHp9o67tm8hu0YQIRTNaEab87SPqwFI1vcq07ted5K4ABfkOI3QANo5+3XUFsSC7Dfb3qymDNJNi50erB++2hZK2Dm+CVhIPq78jm7IpfP0c6khLhR7grjQE78zFS+1oEnAX5mvDP9OhMBV8I7iuZLveTVsWnc/jf+80glc4FhAzkabVQ1M1Egxm6+SEeLrTbRDtnXinHqh1ZRslPqwAH79+Pjo57rZHgs9pAeeEse4tafy9YIhkXlIVDAn1YMi5AIM3VXOsVc4F/WvOgLPHh7sWNtcss4Py0Kft5zj99PrnP7pjxCR3GgAA" \ No newline at end of file diff --git a/docs/assets/search.js b/docs/assets/search.js index e74c9be..b86affa 100644 --- a/docs/assets/search.js +++ b/docs/assets/search.js @@ -1 +1 @@ -window.searchData = "data:application/octet-stream;base64,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"; \ No newline at end of file +window.searchData = "data:application/octet-stream;base64,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"; \ No newline at end of file diff --git a/docs/classes/API.html b/docs/classes/API.html index 44d9587..668a59b 100644 --- a/docs/classes/API.html +++ b/docs/classes/API.html @@ -1,5 +1,5 @@ API | osu-api-v2-js

You can create an API instance using its createAsync function!

-

Hierarchy

  • API

Constructors

Hierarchy

  • API

Constructors

  • Use the API's createAsync instead of the default constructor if you don't have at least an access_token! createAsync should always be your way of creating API instances!!

    -

    Parameters

    • Optional client: {
          id: number;
          secret: string;
      }
      • id: number
      • secret: string
    • Optional token_type: string
    • Optional expires: Date
    • Optional access_token: string
    • Optional scopes: Scope[]
    • Optional refresh_token: string
    • Optional user: number
    • verbose: "all" | "none" | "errors" = "none"
    • server: string = "https://osu.ppy.sh"

    Returns API

Properties

access_token: string
client: {
    id: number;
    secret: string;
}

Type declaration

  • id: number
  • secret: string
expires: Date
refresh_token?: string

Valid for an unknown amount of time, allows you to get a new token without going through the Authorization Code Grant! +

Parameters

  • Optional client: {
        id: number;
        secret: string;
    }
    • id: number
    • secret: string
  • Optional token_type: string
  • Optional expires: Date
  • Optional access_token: string
  • Optional scopes: Scope[]
  • Optional refresh_token: string
  • Optional user: number
  • verbose: "all" | "none" | "errors" = "none"
  • server: string = "https://osu.ppy.sh"

Returns API

Properties

access_token: string
client: {
    id: number;
    secret: string;
}

Type declaration

  • id: number
  • secret: string
expires: Date
refresh_token?: string

Valid for an unknown amount of time, allows you to get a new token without going through the Authorization Code Grant! Use the API's refreshToken function to do that

-
scopes: Scope[]
server: string

(default https://osu.ppy.sh) The base url of the server where the requests should land

+
scopes: Scope[]
server: string

(default https://osu.ppy.sh) The base url of the server where the requests should land

Remarks

For tokens, requests will be sent to the oauth/token route, other requests will be sent to the api/v2 route

-
token_type: string

Should always be "Bearer"

-
user?: number

The osu! user id of the user who went through the Authorization Code Grant

-
verbose: "all" | "none" | "errors"

(default none) Which events should be logged

-

Methods

token_type: string

Should always be "Bearer"

+
user?: number

The osu! user id of the user who went through the Authorization Code Grant

+
verbose: "all" | "none" | "errors"

(default none) Which events should be logged

+

Methods

Returns Promise<BeatmapExtendedWithFailtimesBeatmapsetextended>

  • Get various data about the difficulty of a beatmap!

    +
  • Optional mods: number | string[] | Mod[]

    (defaults to No Mod) (will ignore mod settings) Can be a bitset of mods, an array of mod acronyms ("DT" for DoubleTime), or an array of Mods

    +
  • Optional ruleset: Rulesets

    (defaults to the ruleset the beatmap was intended for) Useful to specify if the beatmap is a convert

    +

Returns Promise<BeatmapDifficultyAttributes | BeatmapDifficultyAttributesOsu | BeatmapDifficultyAttributesTaiko | BeatmapDifficultyAttributesFruits | BeatmapDifficultyAttributesMania>

Remarks

You may want to use getBeatmapDifficultyAttributesOsu (or Taiko or whatever) instead for better type safety

+

Returns Promise<BeatmapDifficultyAttributesFruits>

Returns Promise<BeatmapDifficultyAttributesMania>

Returns Promise<BeatmapDifficultyAttributesOsu>

Returns Promise<ScoreWithUser[]>

Returns Promise<Score[]>

Returns Promise<BeatmapExtended[]>

Returns Promise<BeatmapsetExtendedPlus>

Returns Promise<ChangelogBuildWithChangelogentriesVersions>

Returns Promise<ChangelogBuildWithUpdatestreamsChangelogentries[]>

Returns Promise<RankingsCountry>

Returns Promise<Match>

Returns Promise<Rankings>

Returns Promise<Room>

Returns Promise<RankingsSpotlight>

Returns Promise<UserExtended>

Returns Promise<(EventAchievement | EventBeatmapsetApprove | EventBeatmapsetRevive | EventBeatmapsetUpdate | EventBeatmapsetUpload | EventRank | EventRankLost | EventUserSupportAgain | EventUserSupportFirst | EventUserSupportGift | EventUsernameChange)[]>

Returns Promise<ScoreWithUserBeatmapBeatmapset[]>

Returns Promise<UserWithCountryCoverGroupsStatisticsrulesets[]>

Generated using TypeDoc

\ No newline at end of file +

Generated using TypeDoc

\ No newline at end of file diff --git a/docs/classes/APIError.html b/docs/classes/APIError.html index 6083f3a..9477672 100644 --- a/docs/classes/APIError.html +++ b/docs/classes/APIError.html @@ -1,5 +1,5 @@ APIError | osu-api-v2-js

Class APIError

If the API throws an error, it should always be an APIError!

-

Hierarchy

  • APIError

Constructors

Hierarchy

  • APIError

Constructors

Properties

endpoint message parameters @@ -8,4 +8,4 @@
  • server: string

    The server to which the request was sent

  • endpoint: string

    The type of resource that was requested from the server

  • parameters: string

    The filters that were used to specify what resource was wanted

    -
  • Returns APIError

    Properties

    endpoint: string
    message: string
    parameters: string
    server: string

    Generated using TypeDoc

    \ No newline at end of file +

    Returns APIError

    Properties

    endpoint: string
    message: string
    parameters: string
    server: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/enums/RankStatus.html b/docs/enums/RankStatus.html index dddc0ee..019b6bf 100644 --- a/docs/enums/RankStatus.html +++ b/docs/enums/RankStatus.html @@ -1,8 +1,8 @@ -RankStatus | osu-api-v2-js

    Enumeration RankStatus

    Enumeration Members

    Approved +RankStatus | osu-api-v2-js

    Generated using TypeDoc

    \ No newline at end of file +

    Enumeration Members

    Approved: 2
    Graveyard: -2
    Loved: 4
    Pending: 0
    Qualified: 3
    Ranked: 1
    Wip: -1

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/enums/Rulesets.html b/docs/enums/Rulesets.html index 7bf1a6b..d89b8af 100644 --- a/docs/enums/Rulesets.html +++ b/docs/enums/Rulesets.html @@ -1,5 +1,5 @@ -Rulesets | osu-api-v2-js

    Enumeration Rulesets

    Enumeration Members

    fruits +Rulesets | osu-api-v2-js

    Generated using TypeDoc

    \ No newline at end of file +

    Enumeration Members

    fruits: 2
    mania: 3
    osu: 0
    taiko: 1

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/functions/generateAuthorizationURL.html b/docs/functions/generateAuthorizationURL.html index 5316ac4..dc6cef5 100644 --- a/docs/functions/generateAuthorizationURL.html +++ b/docs/functions/generateAuthorizationURL.html @@ -3,4 +3,4 @@
  • redirect_uri: string

    The specified Application Callback URL, aka where the user will be redirected upon clicking the button to authorize

  • scopes: Scope[]

    What you want to do with/as the user

  • Returns string

    The link people should click on

    -

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/index.html b/docs/index.html index b2b12f1..d5e2d97 100644 --- a/docs/index.html +++ b/docs/index.html @@ -5,6 +5,101 @@

    Make sure to add "type": "module" to your package.json!

    To use (import) the package in your project and start interacting with the API, you may do something like that:

    -
    // TypeScript
    import * as osu from "osu-api-v2-js"

    async function logUserTopPlayBeatmap(username: string) {
    // Because of how the API server works, it's more convenient to use `osu.API.createAsync()` instead of `new osu.API()`!
    // In a proper application, you'd use this function as soon as the app starts so you can use that object everywhere
    const api = await osu.API.createAsync({id: "<client_id>", "<client_secret>"})

    const user = await api.getUser({username}) // We need to get the id of the user in order to request what we want
    const score = (await api.getUserScores(user, "best", 1, osu.Rulesets.osu))[0] // Specifying the Ruleset is optional
    const beatmapDifficulty = await api.getBeatmapDifficultyAttributesOsu(score.beatmap, score.mods) // Specifying the mods so the SR is adapted to them

    let x = `${score.beatmapset.artist} - ${score.beatmapset.title} [${score.beatmap.version}]`
    let y = `+${score.mods.toString()} (${beatmapDifficulty.star_rating.toFixed(2)}*)`
    console.log(`${username}'s top play is on: ${x} ${y}`)
    // Doomsday fanboy's top play is on: xi - FREEDOM DiVE [FOUR DIMENSIONS] +HR (8.07*)
    }

    logUserTopPlayBeatmap("Doomsday fanboy") +
    // TypeScript
    import * as osu from "osu-api-v2-js"

    async function logUserTopPlayBeatmap(username: string) {
    // Because of how the API server works, it's more convenient to use `osu.API.createAsync()` instead of `new osu.API()`!
    // In a proper application, you'd use this function as soon as the app starts so you can use that object everywhere
    // (or if it acts as a user, you'd use this function at the end of the authorization flow)
    const api = await osu.API.createAsync({id: "<client_id>", "<client_secret>"})

    const user = await api.getUser({username}) // We need to get the id of the user in order to request what we want
    const score = (await api.getUserScores(user, "best", 1, osu.Rulesets.osu))[0] // Specifying the Ruleset is optional
    const beatmapDifficulty = await api.getBeatmapDifficultyAttributesOsu(score.beatmap, score.mods) // Specifying the mods so the SR is adapted to them

    let x = `${score.beatmapset.artist} - ${score.beatmapset.title} [${score.beatmap.version}]`
    let y = `+${score.mods.toString()} (${beatmapDifficulty.star_rating.toFixed(2)}*)`
    console.log(`${username}'s top play is on: ${x} ${y}`)
    // Doomsday fanboy's top play is on: xi - FREEDOM DiVE [FOUR DIMENSIONS] +HR (8.07*)
    }

    logUserTopPlayBeatmap("Doomsday fanboy")
    -

    Generated using TypeDoc

    \ No newline at end of file +

    Implemented endpoints

    Beatmap Packs

    +

    Beatmaps

    +

    Beatmapset Discussions

    +

    Beatmapsets

    +

    Changelog

    +

    Chat

    +

    Comments

    +

    Events

    +

    Forum

    +

    Home

    +

    Multiplayer

    +

    News

    +

    Ranking

    +

    Users

    +

    Wiki

    +

    Misc Undocumented Stuff

    +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/Beatmap.html b/docs/interfaces/Beatmap.html index b8d548d..2e5c0e6 100644 --- a/docs/interfaces/Beatmap.html +++ b/docs/interfaces/Beatmap.html @@ -1,4 +1,5 @@ -Beatmap | osu-api-v2-js

    Interface Beatmap

    Hierarchy

    Properties

    beatmapset_id +Beatmap | osu-api-v2-js

    Interface Beatmap

    Expected from BeatmapPlaycount

    +

    Hierarchy

    Properties

    beatmapset_id: number
    difficulty_rating: number
    id: number
    mode: string
    status: string
    total_length: number
    user_id: number
    version: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    beatmapset_id: number
    difficulty_rating: number
    id: number
    mode: string
    status: string
    total_length: number
    user_id: number
    version: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/BeatmapDifficultyAttributes.html b/docs/interfaces/BeatmapDifficultyAttributes.html index fc3242e..c14e563 100644 --- a/docs/interfaces/BeatmapDifficultyAttributes.html +++ b/docs/interfaces/BeatmapDifficultyAttributes.html @@ -1,3 +1,4 @@ -BeatmapDifficultyAttributes | osu-api-v2-js

    Interface BeatmapDifficultyAttributes

    Hierarchy

    Properties

    max_combo +BeatmapDifficultyAttributes | osu-api-v2-js

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    max_combo: number
    star_rating: number

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/BeatmapDifficultyAttributesFruits.html b/docs/interfaces/BeatmapDifficultyAttributesFruits.html index b259e71..d9ca85e 100644 --- a/docs/interfaces/BeatmapDifficultyAttributesFruits.html +++ b/docs/interfaces/BeatmapDifficultyAttributesFruits.html @@ -1,5 +1,5 @@ BeatmapDifficultyAttributesFruits | osu-api-v2-js

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    approach_rate: number
    max_combo: number
    star_rating: number

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/BeatmapDifficultyAttributesMania.html b/docs/interfaces/BeatmapDifficultyAttributesMania.html index 2051527..275a2ce 100644 --- a/docs/interfaces/BeatmapDifficultyAttributesMania.html +++ b/docs/interfaces/BeatmapDifficultyAttributesMania.html @@ -1,7 +1,7 @@ BeatmapDifficultyAttributesMania | osu-api-v2-js

    Interface BeatmapDifficultyAttributesMania

    Expected from api.getBeatmapDifficultyAttributesMania()

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    great_hit_window: number
    max_combo: number
    score_multiplier?: number

    Remarks

    (2023-11-20) Doesn't exist anymore?

    -
    star_rating: number

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    great_hit_window: number
    max_combo: number
    score_multiplier?: number

    Remarks

    (2023-11-20) Doesn't exist anymore?

    +
    star_rating: number

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/BeatmapDifficultyAttributesOsu.html b/docs/interfaces/BeatmapDifficultyAttributesOsu.html index 0552176..3308b46 100644 --- a/docs/interfaces/BeatmapDifficultyAttributesOsu.html +++ b/docs/interfaces/BeatmapDifficultyAttributesOsu.html @@ -1,5 +1,5 @@ BeatmapDifficultyAttributesOsu | osu-api-v2-js

    Interface BeatmapDifficultyAttributesOsu

    Expected from api.getBeatmapDifficultyAttributesOsu()

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    aim_difficulty: number
    approach_rate: number
    flashlight_difficulty: number
    max_combo: number
    overall_difficulty: number
    slider_factor: number
    speed_difficulty: number
    speed_note_count: number
    star_rating: number

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    aim_difficulty: number
    approach_rate: number
    flashlight_difficulty: number
    max_combo: number
    overall_difficulty: number
    slider_factor: number
    speed_difficulty: number
    speed_note_count: number
    star_rating: number

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/BeatmapDifficultyAttributesTaiko.html b/docs/interfaces/BeatmapDifficultyAttributesTaiko.html index 004f6b3..dcbdc7e 100644 --- a/docs/interfaces/BeatmapDifficultyAttributesTaiko.html +++ b/docs/interfaces/BeatmapDifficultyAttributesTaiko.html @@ -1,9 +1,9 @@ BeatmapDifficultyAttributesTaiko | osu-api-v2-js

    Interface BeatmapDifficultyAttributesTaiko

    Expected from api.getBeatmapDifficultyAttributesTaiko()

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    colour_difficulty: number
    great_hit_window: number
    max_combo: number
    peak_difficulty: number
    rhythm_difficulty: number
    stamina_difficulty: number
    star_rating: number

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    colour_difficulty: number
    great_hit_window: number
    max_combo: number
    peak_difficulty: number
    rhythm_difficulty: number
    stamina_difficulty: number
    star_rating: number

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/BeatmapExtended.html b/docs/interfaces/BeatmapExtended.html index a84af39..75c8d6d 100644 --- a/docs/interfaces/BeatmapExtended.html +++ b/docs/interfaces/BeatmapExtended.html @@ -1,5 +1,5 @@ BeatmapExtended | osu-api-v2-js

    Interface BeatmapExtended

    Expected from ScoreWithUserBeatmapBeatmapset

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    Properties

    accuracy: number
    ar: number
    beatmapset_id: number
    bpm: number
    checksum: string
    convert: boolean
    count_circles: number
    count_sliders: number
    count_spinners: number
    cs: number
    deleted_at: null | Date
    difficulty_rating: number
    drain: number
    hit_length: number
    id: number
    is_scoreable: boolean
    last_updated: Date
    mode: string
    mode_int: number
    passcount: number
    playcount: number
    ranked: RankStatus
    status: string
    total_length: number
    url: string
    user_id: number
    version: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    accuracy: number
    ar: number
    beatmapset_id: number
    bpm: number
    checksum: string
    convert: boolean
    count_circles: number
    count_sliders: number
    count_spinners: number
    cs: number
    deleted_at: null | Date
    difficulty_rating: number
    drain: number
    hit_length: number
    id: number
    is_scoreable: boolean
    last_updated: Date
    mode: string
    mode_int: number
    passcount: number
    playcount: number
    ranked: RankStatus
    status: string
    total_length: number
    url: string
    user_id: number
    version: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/BeatmapExtendedWithFailtimes.html b/docs/interfaces/BeatmapExtendedWithFailtimes.html index baa187f..61d823b 100644 --- a/docs/interfaces/BeatmapExtendedWithFailtimes.html +++ b/docs/interfaces/BeatmapExtendedWithFailtimes.html @@ -1,5 +1,5 @@ BeatmapExtendedWithFailtimes | osu-api-v2-js

    Interface BeatmapExtendedWithFailtimes

    Expected from BeatmapsetExtendedPlus

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    Properties

    accuracy: number
    ar: number
    beatmapset_id: number
    bpm: number
    checksum: string
    convert: boolean
    count_circles: number
    count_sliders: number
    count_spinners: number
    cs: number
    deleted_at: null | Date
    difficulty_rating: number
    drain: number
    failtimes: {
        exit: number[];
        fail: number[];
    }

    Type declaration

    • exit: number[]
    • fail: number[]
    hit_length: number
    id: number
    is_scoreable: boolean
    last_updated: Date
    mode: string
    mode_int: number
    passcount: number
    playcount: number
    ranked: RankStatus
    status: string
    total_length: number
    url: string
    user_id: number
    version: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    accuracy: number
    ar: number
    beatmapset_id: number
    bpm: number
    checksum: string
    convert: boolean
    count_circles: number
    count_sliders: number
    count_spinners: number
    cs: number
    deleted_at: null | Date
    difficulty_rating: number
    drain: number
    failtimes: {
        exit: number[];
        fail: number[];
    }

    Type declaration

    • exit: number[]
    • fail: number[]
    hit_length: number
    id: number
    is_scoreable: boolean
    last_updated: Date
    mode: string
    mode_int: number
    passcount: number
    playcount: number
    ranked: RankStatus
    status: string
    total_length: number
    url: string
    user_id: number
    version: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/BeatmapExtendedWithFailtimesBeatmapsetextended.html b/docs/interfaces/BeatmapExtendedWithFailtimesBeatmapsetextended.html index 424cea2..f2cd109 100644 --- a/docs/interfaces/BeatmapExtendedWithFailtimesBeatmapsetextended.html +++ b/docs/interfaces/BeatmapExtendedWithFailtimesBeatmapsetextended.html @@ -1,5 +1,5 @@ BeatmapExtendedWithFailtimesBeatmapsetextended | osu-api-v2-js

    Interface BeatmapExtendedWithFailtimesBeatmapsetextended

    Expected from api.getBeatmap()

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    Properties

    accuracy: number
    ar: number
    beatmapset: BeatmapsetExtended
    beatmapset_id: number
    bpm: number
    checksum: string
    convert: boolean
    count_circles: number
    count_sliders: number
    count_spinners: number
    cs: number
    deleted_at: null | Date
    difficulty_rating: number
    drain: number
    failtimes: {
        exit: number[];
        fail: number[];
    }

    Type declaration

    • exit: number[]
    • fail: number[]
    hit_length: number
    id: number
    is_scoreable: boolean
    last_updated: Date
    mode: string
    mode_int: number
    passcount: number
    playcount: number
    ranked: RankStatus
    status: string
    total_length: number
    url: string
    user_id: number
    version: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    accuracy: number
    ar: number
    beatmapset: BeatmapsetExtended
    beatmapset_id: number
    bpm: number
    checksum: string
    convert: boolean
    count_circles: number
    count_sliders: number
    count_spinners: number
    cs: number
    deleted_at: null | Date
    difficulty_rating: number
    drain: number
    failtimes: {
        exit: number[];
        fail: number[];
    }

    Type declaration

    • exit: number[]
    • fail: number[]
    hit_length: number
    id: number
    is_scoreable: boolean
    last_updated: Date
    mode: string
    mode_int: number
    passcount: number
    playcount: number
    ranked: RankStatus
    status: string
    total_length: number
    url: string
    user_id: number
    version: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/BeatmapPack.html b/docs/interfaces/BeatmapPack.html index d0ce2cf..12b60f3 100644 --- a/docs/interfaces/BeatmapPack.html +++ b/docs/interfaces/BeatmapPack.html @@ -1,5 +1,5 @@ BeatmapPack | osu-api-v2-js

    Interface BeatmapPack

    Expected from api.getBeatmapPack(), api.getBeatmapPacks()

    -

    Hierarchy

    • BeatmapPack

    Properties

    Hierarchy

    • BeatmapPack

    Properties

    author: string
    beatmapsets?: BeatmapsetExtended[]
    date: Date
    name: string
    no_diff_reduction: boolean

    Are difficulty reduction mods unable to be used to clear this pack? (is false if you can use such mods)

    -
    ruleset_id: null | number
    tag: string
    url: string
    user_completion_data?: {
        beatmapset_ids: number[];
        completed: boolean;
    }

    Type declaration

    • beatmapset_ids: number[]

      IDs of beatmapsets completed by the user (according to the requirements of the pack)

      +

    Properties

    author: string
    beatmapsets?: BeatmapsetExtended[]
    date: Date
    name: string
    no_diff_reduction: boolean

    Are difficulty reduction mods unable to be used to clear this pack? (is false if you can use such mods)

    +
    ruleset_id: null | number
    tag: string
    url: string
    user_completion_data?: {
        beatmapset_ids: number[];
        completed: boolean;
    }

    Type declaration

    • beatmapset_ids: number[]

      IDs of beatmapsets completed by the user (according to the requirements of the pack)

    • completed: boolean

      Whether all beatmapsets are completed by the user or not

      -

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/BeatmapPlaycount.html b/docs/interfaces/BeatmapPlaycount.html new file mode 100644 index 0000000..9518eb1 --- /dev/null +++ b/docs/interfaces/BeatmapPlaycount.html @@ -0,0 +1,7 @@ +BeatmapPlaycount | osu-api-v2-js

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/BeatmapUserScore.html b/docs/interfaces/BeatmapUserScore.html index 3bf6d24..c71980d 100644 --- a/docs/interfaces/BeatmapUserScore.html +++ b/docs/interfaces/BeatmapUserScore.html @@ -1,5 +1,5 @@ BeatmapUserScore | osu-api-v2-js

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/BeatmapWithBeatmapset.html b/docs/interfaces/BeatmapWithBeatmapset.html index af5d3b3..f23b80b 100644 --- a/docs/interfaces/BeatmapWithBeatmapset.html +++ b/docs/interfaces/BeatmapWithBeatmapset.html @@ -1,5 +1,5 @@ BeatmapWithBeatmapset | osu-api-v2-js

    Interface BeatmapWithBeatmapset

    Expected from Match

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    beatmapset: Beatmapset
    beatmapset_id: number
    difficulty_rating: number
    id: number
    mode: string
    status: string
    total_length: number
    user_id: number
    version: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    beatmapset: Beatmapset
    beatmapset_id: number
    difficulty_rating: number
    id: number
    mode: string
    status: string
    total_length: number
    user_id: number
    version: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/BeatmapWithBeatmapsetChecksumMaxcombo.html b/docs/interfaces/BeatmapWithBeatmapsetChecksumMaxcombo.html index bee7f5d..3c93ab6e 100644 --- a/docs/interfaces/BeatmapWithBeatmapsetChecksumMaxcombo.html +++ b/docs/interfaces/BeatmapWithBeatmapsetChecksumMaxcombo.html @@ -1,5 +1,5 @@ BeatmapWithBeatmapsetChecksumMaxcombo | osu-api-v2-js

    Interface BeatmapWithBeatmapsetChecksumMaxcombo

    Expected from PlaylistItem

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    beatmapset: Beatmapset
    beatmapset_id: number
    checksum: string
    difficulty_rating: number
    id: number
    max_combo: number
    mode: string
    status: string
    total_length: number
    user_id: number
    version: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    beatmapset: Beatmapset
    beatmapset_id: number
    checksum: string
    difficulty_rating: number
    id: number
    max_combo: number
    mode: string
    status: string
    total_length: number
    user_id: number
    version: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/Beatmapset.html b/docs/interfaces/Beatmapset.html index f20aa6e..309efdd 100644 --- a/docs/interfaces/Beatmapset.html +++ b/docs/interfaces/Beatmapset.html @@ -1,5 +1,5 @@ -Beatmapset | osu-api-v2-js

    Interface Beatmapset

    Expected from BeatmapWithBeatmapset, Score

    -

    Hierarchy

    Properties

    artist +Beatmapset | osu-api-v2-js

    Interface Beatmapset

    Expected from BeatmapWithBeatmapset, Score, BeatmapPlaycount

    +

    Hierarchy

    Properties

    artist: string
    artist_unicode: string
    covers: {
        card: string;
        card@2x: string;
        cover: string;
        cover@2x: string;
        list: string;
        list@2x: string;
        slimcover: string;
        slimcover@2x: string;
    }

    Type declaration

    • card: string
    • card@2x: string
    • cover: string
    • cover@2x: string
    • list: string
    • list@2x: string
    • slimcover: string
    • slimcover@2x: string
    creator: string
    favourite_count: number
    id: number
    nsfw: boolean
    offset: number
    play_count: number
    preview_url: string

    A string like that, where id is the id of the beatmapset: //b.ppy.sh/preview/58951.mp3

    -
    source: string | 0

    Can be/Is 0 if there is no source

    -
    spotlight: boolean
    status: string

    Is it ranked, is it graveyarded, etc

    -
    title: string

    A title readable by any english-speaking person, so it'd be romaji if the song's title is in Japanese

    -
    title_unicode: string

    Basically the title is the original language, so with hiraganas and kanji if Japanese

    -
    user_id: number
    video: boolean

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    artist: string
    artist_unicode: string
    covers: {
        card: string;
        card@2x: string;
        cover: string;
        cover@2x: string;
        list: string;
        list@2x: string;
        slimcover: string;
        slimcover@2x: string;
    }

    Type declaration

    • card: string
    • card@2x: string
    • cover: string
    • cover@2x: string
    • list: string
    • list@2x: string
    • slimcover: string
    • slimcover@2x: string
    creator: string
    favourite_count: number
    id: number
    nsfw: boolean
    offset: number
    play_count: number
    preview_url: string

    A string like that, where id is the id of the beatmapset: //b.ppy.sh/preview/58951.mp3

    +
    source: string | 0

    Can be/Is 0 if there is no source

    +
    spotlight: boolean
    status: string

    Is it ranked, is it graveyarded, etc

    +
    title: string

    A title readable by any english-speaking person, so it'd be romaji if the song's title is in Japanese

    +
    title_unicode: string

    Basically the title is the original language, so with hiraganas and kanji if Japanese

    +
    user_id: number
    video: boolean

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/BeatmapsetExtended.html b/docs/interfaces/BeatmapsetExtended.html index 8edf266..f531f1e 100644 --- a/docs/interfaces/BeatmapsetExtended.html +++ b/docs/interfaces/BeatmapsetExtended.html @@ -1,5 +1,5 @@ BeatmapsetExtended | osu-api-v2-js

    Interface BeatmapsetExtended

    Expected from RankingsSpotlight, BeatmapExtendedWithFailtimesBeatmapsetextended

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    artist: string
    artist_unicode: string
    availability: {
        download_disabled: boolean;
        more_information: null | string;
    }

    Type declaration

    • download_disabled: boolean

      So it's false if you can download it

      -
    • more_information: null | string
    bpm: number
    can_be_hyped: boolean
    covers: {
        card: string;
        card@2x: string;
        cover: string;
        cover@2x: string;
        list: string;
        list@2x: string;
        slimcover: string;
        slimcover@2x: string;
    }

    Type declaration

    • card: string
    • card@2x: string
    • cover: string
    • cover@2x: string
    • list: string
    • list@2x: string
    • slimcover: string
    • slimcover@2x: string
    creator: string
    deleted_at: null | string
    discussion_locked: boolean
    favourite_count: number
    hype: null | {
        current: number;
        required: number;
    }

    Type declaration

    • current: number
    • required: number
    id: number
    is_scoreable: boolean
    last_updated: Date
    legacy_thread_url: string
    nominations_summary: {
        current: number;
        required: number;
    }

    Type declaration

    • current: number
    • required: number
    nsfw: boolean
    offset: number
    play_count: number
    preview_url: string

    A string like that, where id is the id of the beatmapset: //b.ppy.sh/preview/58951.mp3

    -
    ranked: RankStatus
    ranked_date: null | Date
    source: string

    Can be/Is 0 if there is no source

    -
    spotlight: boolean
    status: string

    Is it ranked, is it graveyarded, etc

    -
    storyboard: boolean
    submitted_date: null | Date
    tags: string | 0

    0 if no tags at all, a string with tags separated from each other by a whitespace

    -
    title: string

    A title readable by any english-speaking person, so it'd be romaji if the song's title is in Japanese

    -
    title_unicode: string

    Basically the title is the original language, so with hiraganas and kanji if Japanese

    -
    user_id: number
    video: boolean

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    artist: string
    artist_unicode: string
    availability: {
        download_disabled: boolean;
        more_information: null | string;
    }

    Type declaration

    • download_disabled: boolean

      So it's false if you can download it

      +
    • more_information: null | string
    bpm: number
    can_be_hyped: boolean
    covers: {
        card: string;
        card@2x: string;
        cover: string;
        cover@2x: string;
        list: string;
        list@2x: string;
        slimcover: string;
        slimcover@2x: string;
    }

    Type declaration

    • card: string
    • card@2x: string
    • cover: string
    • cover@2x: string
    • list: string
    • list@2x: string
    • slimcover: string
    • slimcover@2x: string
    creator: string
    deleted_at: null | string
    discussion_locked: boolean
    favourite_count: number
    hype: null | {
        current: number;
        required: number;
    }

    Type declaration

    • current: number
    • required: number
    id: number
    is_scoreable: boolean
    last_updated: Date
    legacy_thread_url: string
    nominations_summary: {
        current: number;
        required: number;
    }

    Type declaration

    • current: number
    • required: number
    nsfw: boolean
    offset: number
    play_count: number
    preview_url: string

    A string like that, where id is the id of the beatmapset: //b.ppy.sh/preview/58951.mp3

    +
    ranked: RankStatus
    ranked_date: null | Date
    source: string

    Can be/Is 0 if there is no source

    +
    spotlight: boolean
    status: string

    Is it ranked, is it graveyarded, etc

    +
    storyboard: boolean
    submitted_date: null | Date
    tags: string | 0

    0 if no tags at all, a string with tags separated from each other by a whitespace

    +
    title: string

    A title readable by any english-speaking person, so it'd be romaji if the song's title is in Japanese

    +
    title_unicode: string

    Basically the title is the original language, so with hiraganas and kanji if Japanese

    +
    user_id: number
    video: boolean

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/BeatmapsetExtendedPlus.html b/docs/interfaces/BeatmapsetExtendedPlus.html index 08d4a31..019899f 100644 --- a/docs/interfaces/BeatmapsetExtendedPlus.html +++ b/docs/interfaces/BeatmapsetExtendedPlus.html @@ -1,5 +1,5 @@ BeatmapsetExtendedPlus | osu-api-v2-js

    Interface BeatmapsetExtendedPlus

    Expected from api.getBeatmapset()

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    Properties

    artist: string
    artist_unicode: string
    availability: {
        download_disabled: boolean;
        more_information: null | string;
    }

    Type declaration

    • download_disabled: boolean

      So it's false if you can download it

      -
    • more_information: null | string

    The different beatmaps/difficulties this beatmapset has

    -
    bpm: number
    can_be_hyped: boolean

    The different beatmaps made for osu!, but converted to the other Rulesets

    -
    covers: {
        card: string;
        card@2x: string;
        cover: string;
        cover@2x: string;
        list: string;
        list@2x: string;
        slimcover: string;
        slimcover@2x: string;
    }

    Type declaration

    • card: string
    • card@2x: string
    • cover: string
    • cover@2x: string
    • list: string
    • list@2x: string
    • slimcover: string
    • slimcover@2x: string
    creator: string
    current_nominations: {
        beatmapset_id: number;
        reset: boolean;
        rulesets: Rulesets[];
        user_id: number;
    }[]

    Type declaration

    • beatmapset_id: number
    • reset: boolean
    • rulesets: Rulesets[]
    • user_id: number
    deleted_at: null | string
    description: {
        description: string;
    }

    Type declaration

    • description: string

      In HTML

      -
    discussion_locked: boolean
    favourite_count: number
    genre: {
        id: number;
        name: string;
    }

    Type declaration

    • id: number
    • name: string
    has_favourited?: boolean

    Only exists if authorized user

    -
    hype: null | {
        current: number;
        required: number;
    }

    Type declaration

    • current: number
    • required: number
    id: number
    is_scoreable: boolean
    language: {
        id: number;
        name: string;
    }

    Type declaration

    • id: number
    • name: string
    last_updated: Date
    legacy_thread_url: string
    nominations_summary: {
        current: number;
        required: number;
    }

    Type declaration

    • current: number
    • required: number
    nsfw: boolean
    offset: number
    pack_tags: string[]
    play_count: number
    preview_url: string

    A string like that, where id is the id of the beatmapset: //b.ppy.sh/preview/58951.mp3

    -
    ranked: RankStatus
    ranked_date: null | Date
    ratings: number[]
    recent_favourites: User[]
    related_users: User[]
    source: string

    Can be/Is 0 if there is no source

    -
    spotlight: boolean
    status: string

    Is it ranked, is it graveyarded, etc

    -
    storyboard: boolean
    submitted_date: null | Date
    tags: string | 0

    0 if no tags at all, a string with tags separated from each other by a whitespace

    -
    title: string

    A title readable by any english-speaking person, so it'd be romaji if the song's title is in Japanese

    -
    title_unicode: string

    Basically the title is the original language, so with hiraganas and kanji if Japanese

    -
    user: User
    user_id: number
    video: boolean

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    artist: string
    artist_unicode: string
    availability: {
        download_disabled: boolean;
        more_information: null | string;
    }

    Type declaration

    • download_disabled: boolean

      So it's false if you can download it

      +
    • more_information: null | string

    The different beatmaps/difficulties this beatmapset has

    +
    bpm: number
    can_be_hyped: boolean

    The different beatmaps made for osu!, but converted to the other Rulesets

    +
    covers: {
        card: string;
        card@2x: string;
        cover: string;
        cover@2x: string;
        list: string;
        list@2x: string;
        slimcover: string;
        slimcover@2x: string;
    }

    Type declaration

    • card: string
    • card@2x: string
    • cover: string
    • cover@2x: string
    • list: string
    • list@2x: string
    • slimcover: string
    • slimcover@2x: string
    creator: string
    current_nominations: {
        beatmapset_id: number;
        reset: boolean;
        rulesets: Rulesets[];
        user_id: number;
    }[]

    Type declaration

    • beatmapset_id: number
    • reset: boolean
    • rulesets: Rulesets[]
    • user_id: number
    deleted_at: null | string
    description: {
        description: string;
    }

    Type declaration

    • description: string

      In HTML

      +
    discussion_locked: boolean
    favourite_count: number
    genre: {
        id: number;
        name: string;
    }

    Type declaration

    • id: number
    • name: string
    has_favourited?: boolean

    Only exists if authorized user

    +
    hype: null | {
        current: number;
        required: number;
    }

    Type declaration

    • current: number
    • required: number
    id: number
    is_scoreable: boolean
    language: {
        id: number;
        name: string;
    }

    Type declaration

    • id: number
    • name: string
    last_updated: Date
    legacy_thread_url: string
    nominations_summary: {
        current: number;
        required: number;
    }

    Type declaration

    • current: number
    • required: number
    nsfw: boolean
    offset: number
    pack_tags: string[]
    play_count: number
    preview_url: string

    A string like that, where id is the id of the beatmapset: //b.ppy.sh/preview/58951.mp3

    +
    ranked: RankStatus
    ranked_date: null | Date
    ratings: number[]
    recent_favourites: User[]
    related_users: User[]
    source: string

    Can be/Is 0 if there is no source

    +
    spotlight: boolean
    status: string

    Is it ranked, is it graveyarded, etc

    +
    storyboard: boolean
    submitted_date: null | Date
    tags: string | 0

    0 if no tags at all, a string with tags separated from each other by a whitespace

    +
    title: string

    A title readable by any english-speaking person, so it'd be romaji if the song's title is in Japanese

    +
    title_unicode: string

    Basically the title is the original language, so with hiraganas and kanji if Japanese

    +
    user: User
    user_id: number
    video: boolean

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/BeatmapsetExtendedWithBeatmapExtended.html b/docs/interfaces/BeatmapsetExtendedWithBeatmapExtended.html new file mode 100644 index 0000000..3c93ab67 --- /dev/null +++ b/docs/interfaces/BeatmapsetExtendedWithBeatmapExtended.html @@ -0,0 +1,42 @@ +BeatmapsetExtendedWithBeatmapExtended | osu-api-v2-js

    Interface BeatmapsetExtendedWithBeatmapExtended

    Expected from api.getUserBeatmaps()

    +

    Hierarchy

    Properties

    artist: string
    artist_unicode: string
    availability: {
        download_disabled: boolean;
        more_information: null | string;
    }

    Type declaration

    • download_disabled: boolean

      So it's false if you can download it

      +
    • more_information: null | string
    beatmaps: BeatmapExtended[]
    bpm: number
    can_be_hyped: boolean
    covers: {
        card: string;
        card@2x: string;
        cover: string;
        cover@2x: string;
        list: string;
        list@2x: string;
        slimcover: string;
        slimcover@2x: string;
    }

    Type declaration

    • card: string
    • card@2x: string
    • cover: string
    • cover@2x: string
    • list: string
    • list@2x: string
    • slimcover: string
    • slimcover@2x: string
    creator: string
    deleted_at: null | string
    discussion_locked: boolean
    favourite_count: number
    hype: null | {
        current: number;
        required: number;
    }

    Type declaration

    • current: number
    • required: number
    id: number
    is_scoreable: boolean
    last_updated: Date
    legacy_thread_url: string
    nominations_summary: {
        current: number;
        required: number;
    }

    Type declaration

    • current: number
    • required: number
    nsfw: boolean
    offset: number
    play_count: number
    preview_url: string

    A string like that, where id is the id of the beatmapset: //b.ppy.sh/preview/58951.mp3

    +
    ranked: RankStatus
    ranked_date: null | Date
    source: string

    Can be/Is 0 if there is no source

    +
    spotlight: boolean
    status: string

    Is it ranked, is it graveyarded, etc

    +
    storyboard: boolean
    submitted_date: null | Date
    tags: string | 0

    0 if no tags at all, a string with tags separated from each other by a whitespace

    +
    title: string

    A title readable by any english-speaking person, so it'd be romaji if the song's title is in Japanese

    +
    title_unicode: string

    Basically the title is the original language, so with hiraganas and kanji if Japanese

    +
    user_id: number
    video: boolean

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/ChangelogBuildWithChangelogentriesVersions.html b/docs/interfaces/ChangelogBuildWithChangelogentriesVersions.html index 69cd651..d237c84 100644 --- a/docs/interfaces/ChangelogBuildWithChangelogentriesVersions.html +++ b/docs/interfaces/ChangelogBuildWithChangelogentriesVersions.html @@ -1,5 +1,5 @@ ChangelogBuildWithChangelogentriesVersions | osu-api-v2-js

    Interface ChangelogBuildWithChangelogentriesVersions

    Expected from api.getChangelogBuild()

    -

    Hierarchy

    • ChangelogBuildWithChangelogentries
      • ChangelogBuildWithChangelogentriesVersions

    Properties

    Hierarchy

    • ChangelogBuildWithChangelogentries
      • ChangelogBuildWithChangelogentriesVersions

    Properties

  • github_pull_request_id: null | number
  • github_url: null | string
  • Optional github_user?: {
        display_name: string;
        github_url: null | string;
        github_username: null | string;
        id: null | number;
        osu_username: null | string;
        user_id: null | number;
        user_url: null | string;
    }

    Doesn't exist if no github user is associated with who's credited with the change

    • display_name: string
    • github_url: null | string
    • github_username: null | string
    • id: null | number
    • osu_username: null | string
    • user_id: null | number
    • user_url: null | string
  • id: null | number
  • major: boolean
  • Optional message?: null | string

    Entry message in Markdown format, embedded HTML is allowed, exists only if Markdown was requested

  • Optional message_html?: null | string

    Entry message in HTML format, exists only if HTML was requested

    -
  • repository: null | string
  • title: null | string
  • type: string
  • url: null | string
  • created_at: Date
    display_version: string
    id: number
    users: number

    How many users are playing on this version of the game? (if lazer/web, should be 0, lazer doesn't show such stats)

    -
    version: null | string

    The name of the version

    -
    versions: {
        next: null | ChangelogBuildWithUpdatestreams;
        previous: null | ChangelogBuildWithUpdatestreams;
    }

    Type declaration

    youtube_id: null | string

    If a video is showcased on the changelog

    +
  • repository: null | string
  • title: null | string
  • type: string
  • url: null | string
  • created_at: Date
    display_version: string
    id: number
    users: number

    How many users are playing on this version of the game? (if lazer/web, should be 0, lazer doesn't show such stats)

    +
    version: null | string

    The name of the version

    +
    versions: {
        next: null | ChangelogBuildWithUpdatestreams;
        previous: null | ChangelogBuildWithUpdatestreams;
    }

    Type declaration

    youtube_id: null | string

    If a video is showcased on the changelog

    Remarks

    The ID of a Youtube video is whatever comes after /watch?v= in its url

    -

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/ChangelogBuildWithUpdatestreams.html b/docs/interfaces/ChangelogBuildWithUpdatestreams.html index f1d2725..ee49af8 100644 --- a/docs/interfaces/ChangelogBuildWithUpdatestreams.html +++ b/docs/interfaces/ChangelogBuildWithUpdatestreams.html @@ -1,13 +1,13 @@ ChangelogBuildWithUpdatestreams | osu-api-v2-js

    Interface ChangelogBuildWithUpdatestreams

    Expected from ChangelogBuildWithChangelogentriesVersions

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    created_at: Date
    display_version: string
    id: number
    update_stream: UpdateStream
    users: number

    How many users are playing on this version of the game? (if lazer/web, should be 0, lazer doesn't show such stats)

    -
    version: null | string

    The name of the version

    -
    youtube_id: null | string

    If a video is showcased on the changelog

    +

    Properties

    created_at: Date
    display_version: string
    id: number
    update_stream: UpdateStream
    users: number

    How many users are playing on this version of the game? (if lazer/web, should be 0, lazer doesn't show such stats)

    +
    version: null | string

    The name of the version

    +
    youtube_id: null | string

    If a video is showcased on the changelog

    Remarks

    The ID of a Youtube video is whatever comes after /watch?v= in its url

    -

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/ChangelogBuildWithUpdatestreamsChangelogentries.html b/docs/interfaces/ChangelogBuildWithUpdatestreamsChangelogentries.html index ba84656..dfd3879 100644 --- a/docs/interfaces/ChangelogBuildWithUpdatestreamsChangelogentries.html +++ b/docs/interfaces/ChangelogBuildWithUpdatestreamsChangelogentries.html @@ -1,5 +1,5 @@ ChangelogBuildWithUpdatestreamsChangelogentries | osu-api-v2-js

    Interface ChangelogBuildWithUpdatestreamsChangelogentries

    Expected from api.getChangelogBuilds()

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

  • github_pull_request_id: null | number
  • github_url: null | string
  • Optional github_user?: {
        display_name: string;
        github_url: null | string;
        github_username: null | string;
        id: null | number;
        osu_username: null | string;
        user_id: null | number;
        user_url: null | string;
    }

    Doesn't exist if no github user is associated with who's credited with the change

    • display_name: string
    • github_url: null | string
    • github_username: null | string
    • id: null | number
    • osu_username: null | string
    • user_id: null | number
    • user_url: null | string
  • id: null | number
  • major: boolean
  • Optional message?: null | string

    Entry message in Markdown format, embedded HTML is allowed, exists only if Markdown was requested

  • Optional message_html?: null | string

    Entry message in HTML format, exists only if HTML was requested

    -
  • repository: null | string
  • title: null | string
  • type: string
  • url: null | string
  • created_at: Date
    display_version: string
    id: number
    update_stream: UpdateStream
    users: number

    How many users are playing on this version of the game? (if lazer/web, should be 0, lazer doesn't show such stats)

    -
    version: null | string

    The name of the version

    -
    youtube_id: null | string

    If a video is showcased on the changelog

    +
  • repository: null | string
  • title: null | string
  • type: string
  • url: null | string
  • created_at: Date
    display_version: string
    id: number
    update_stream: UpdateStream
    users: number

    How many users are playing on this version of the game? (if lazer/web, should be 0, lazer doesn't show such stats)

    +
    version: null | string

    The name of the version

    +
    youtube_id: null | string

    If a video is showcased on the changelog

    Remarks

    The ID of a Youtube video is whatever comes after /watch?v= in its url

    -

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/Event.html b/docs/interfaces/Event.html new file mode 100644 index 0000000..08d4214 --- /dev/null +++ b/docs/interfaces/Event.html @@ -0,0 +1,3 @@ +Event | osu-api-v2-js

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/EventAchievement.html b/docs/interfaces/EventAchievement.html new file mode 100644 index 0000000..edd35db --- /dev/null +++ b/docs/interfaces/EventAchievement.html @@ -0,0 +1,9 @@ +EventAchievement | osu-api-v2-js

    Interface EventAchievement

    Hierarchy

    Properties

    achievement: {
        description: string;
        grouping: string;
        icon_url: string;
        id: number;
        instructions: string;
        mode: null | string;
        name: string;
        ordering: number;
        slug: string;
    }

    Type declaration

    • description: string
    • grouping: string
    • icon_url: string
    • id: number
    • instructions: string

      May contain HTML (like have the text between )

      +
    • mode: null | string

      If the achievement is for a specific mode only (such as pass a 2* beatmap in taiko)

      +
    • name: string
    • ordering: number
    • slug: string
    created_at: Date
    id: number
    type: "achievement"
    user: {
        url: string;
        username: string;
    }

    Type declaration

    • url: string

      What goes after the website's URL, so for example, it could be the /u/7276846 of https://osu.ppy.sh/u/7276846 (or users instead of u)

      +
    • username: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/EventBeatmap.html b/docs/interfaces/EventBeatmap.html new file mode 100644 index 0000000..f83da39 --- /dev/null +++ b/docs/interfaces/EventBeatmap.html @@ -0,0 +1,7 @@ +EventBeatmap | osu-api-v2-js

    Interface EventBeatmap

    Hierarchy

    Properties

    Properties

    created_at: Date
    id: number
    title: string

    {artist} - {title} [{difficulty_name}]

    +
    url: string

    What goes after the website's URL, like it could be the /b/2980857?m=0 of https://osu.ppy.sh/b/2980857?m=0 (/{beatmap_id}?m={ruleset_id})

    +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/EventBeatmapPlaycount.html b/docs/interfaces/EventBeatmapPlaycount.html new file mode 100644 index 0000000..a6fce50 --- /dev/null +++ b/docs/interfaces/EventBeatmapPlaycount.html @@ -0,0 +1,9 @@ +EventBeatmapPlaycount | osu-api-v2-js

    Interface EventBeatmapPlaycount

    Hierarchy

    Properties

    Properties

    count: number
    created_at: Date
    id: number
    title: string

    {artist} - {title} [{difficulty_name}]

    +
    type: "beatmapPlaycount"
    url: string

    What goes after the website's URL, like it could be the /b/2980857?m=0 of https://osu.ppy.sh/b/2980857?m=0 (/{beatmap_id}?m={ruleset_id})

    +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/EventBeatmapset.html b/docs/interfaces/EventBeatmapset.html new file mode 100644 index 0000000..621cb32 --- /dev/null +++ b/docs/interfaces/EventBeatmapset.html @@ -0,0 +1,7 @@ +EventBeatmapset | osu-api-v2-js

    Interface EventBeatmapset

    Hierarchy

    Properties

    Properties

    created_at: Date
    id: number
    title: string

    {artist} - {title}

    +
    url: string

    What goes after the website's URL, like it could be the /s/689155 of https://osu.ppy.sh/s/689155 (/{beatmapset_id})

    +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/EventBeatmapsetApprove.html b/docs/interfaces/EventBeatmapsetApprove.html new file mode 100644 index 0000000..1652d9a --- /dev/null +++ b/docs/interfaces/EventBeatmapsetApprove.html @@ -0,0 +1,11 @@ +EventBeatmapsetApprove | osu-api-v2-js

    Interface EventBeatmapsetApprove

    Hierarchy

    Properties

    Properties

    approval: "ranked" | "approved" | "qualified" | "loved"
    created_at: Date
    id: number
    title: string

    {artist} - {title}

    +
    type: "beatmapsetApprove"
    url: string

    What goes after the website's URL, like it could be the /s/689155 of https://osu.ppy.sh/s/689155 (/{beatmapset_id})

    +
    user: {
        url: string;
        username: string;
    }

    Type declaration

    • url: string

      What goes after the website's URL, so for example, it could be the /u/7276846 of https://osu.ppy.sh/u/7276846 (or users instead of u)

      +
    • username: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/EventBeatmapsetDelete.html b/docs/interfaces/EventBeatmapsetDelete.html new file mode 100644 index 0000000..690ebbd --- /dev/null +++ b/docs/interfaces/EventBeatmapsetDelete.html @@ -0,0 +1,8 @@ +EventBeatmapsetDelete | osu-api-v2-js

    Interface EventBeatmapsetDelete

    Hierarchy

    Properties

    Properties

    created_at: Date
    id: number
    title: string

    {artist} - {title}

    +
    type: "beatmapsetDelete"
    url: string

    What goes after the website's URL, like it could be the /s/689155 of https://osu.ppy.sh/s/689155 (/{beatmapset_id})

    +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/EventBeatmapsetRevive.html b/docs/interfaces/EventBeatmapsetRevive.html new file mode 100644 index 0000000..dd3e95e --- /dev/null +++ b/docs/interfaces/EventBeatmapsetRevive.html @@ -0,0 +1,10 @@ +EventBeatmapsetRevive | osu-api-v2-js

    Interface EventBeatmapsetRevive

    Hierarchy

    Properties

    Properties

    created_at: Date
    id: number
    title: string

    {artist} - {title}

    +
    type: "beatmapsetRevive"
    url: string

    What goes after the website's URL, like it could be the /s/689155 of https://osu.ppy.sh/s/689155 (/{beatmapset_id})

    +
    user: {
        url: string;
        username: string;
    }

    Type declaration

    • url: string

      What goes after the website's URL, so for example, it could be the /u/7276846 of https://osu.ppy.sh/u/7276846 (or users instead of u)

      +
    • username: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/EventBeatmapsetUpdate.html b/docs/interfaces/EventBeatmapsetUpdate.html new file mode 100644 index 0000000..81e974d --- /dev/null +++ b/docs/interfaces/EventBeatmapsetUpdate.html @@ -0,0 +1,10 @@ +EventBeatmapsetUpdate | osu-api-v2-js

    Interface EventBeatmapsetUpdate

    Hierarchy

    Properties

    Properties

    created_at: Date
    id: number
    title: string

    {artist} - {title}

    +
    type: "beatmapsetUpdate"
    url: string

    What goes after the website's URL, like it could be the /s/689155 of https://osu.ppy.sh/s/689155 (/{beatmapset_id})

    +
    user: {
        url: string;
        username: string;
    }

    Type declaration

    • url: string

      What goes after the website's URL, so for example, it could be the /u/7276846 of https://osu.ppy.sh/u/7276846 (or users instead of u)

      +
    • username: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/EventBeatmapsetUpload.html b/docs/interfaces/EventBeatmapsetUpload.html new file mode 100644 index 0000000..0d44b3e --- /dev/null +++ b/docs/interfaces/EventBeatmapsetUpload.html @@ -0,0 +1,10 @@ +EventBeatmapsetUpload | osu-api-v2-js

    Interface EventBeatmapsetUpload

    Hierarchy

    Properties

    Properties

    created_at: Date
    id: number
    title: string

    {artist} - {title}

    +
    type: "beatmapsetUpload"
    url: string

    What goes after the website's URL, like it could be the /s/689155 of https://osu.ppy.sh/s/689155 (/{beatmapset_id})

    +
    user: {
        url: string;
        username: string;
    }

    Type declaration

    • url: string

      What goes after the website's URL, so for example, it could be the /u/7276846 of https://osu.ppy.sh/u/7276846 (or users instead of u)

      +
    • username: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/EventRank.html b/docs/interfaces/EventRank.html new file mode 100644 index 0000000..2229f63 --- /dev/null +++ b/docs/interfaces/EventRank.html @@ -0,0 +1,15 @@ +EventRank | osu-api-v2-js

    Interface EventRank

    Hierarchy

    Properties

    created_at: Date
    id: number
    mode: Rulesets
    rank: number

    The position achieved, like 14

    +
    scoreRank: string

    The grade, like "S"

    +
    title: string

    {artist} - {title} [{difficulty_name}]

    +
    type: "rank"
    url: string

    What goes after the website's URL, like it could be the /b/2980857?m=0 of https://osu.ppy.sh/b/2980857?m=0 (/{beatmap_id}?m={ruleset_id})

    +
    user: {
        url: string;
        username: string;
    }

    Type declaration

    • url: string

      What goes after the website's URL, so for example, it could be the /u/7276846 of https://osu.ppy.sh/u/7276846 (or users instead of u)

      +
    • username: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/EventRankLost.html b/docs/interfaces/EventRankLost.html new file mode 100644 index 0000000..e386db9 --- /dev/null +++ b/docs/interfaces/EventRankLost.html @@ -0,0 +1,11 @@ +EventRankLost | osu-api-v2-js

    Interface EventRankLost

    Hierarchy

    Properties

    Properties

    created_at: Date
    id: number
    mode: Rulesets
    title: string

    {artist} - {title} [{difficulty_name}]

    +
    type: "rankLost"
    url: string

    What goes after the website's URL, like it could be the /b/2980857?m=0 of https://osu.ppy.sh/b/2980857?m=0 (/{beatmap_id}?m={ruleset_id})

    +
    user: {
        url: string;
        username: string;
    }

    Type declaration

    • url: string

      What goes after the website's URL, so for example, it could be the /u/7276846 of https://osu.ppy.sh/u/7276846 (or users instead of u)

      +
    • username: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/EventUser.html b/docs/interfaces/EventUser.html new file mode 100644 index 0000000..26fb1d2 --- /dev/null +++ b/docs/interfaces/EventUser.html @@ -0,0 +1,5 @@ +EventUser | osu-api-v2-js

    Interface EventUser

    Hierarchy

    Properties

    Properties

    created_at: Date
    id: number
    user: {
        url: string;
        username: string;
    }

    Type declaration

    • url: string

      What goes after the website's URL, so for example, it could be the /u/7276846 of https://osu.ppy.sh/u/7276846 (or users instead of u)

      +
    • username: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/EventUserSupportAgain.html b/docs/interfaces/EventUserSupportAgain.html new file mode 100644 index 0000000..74840f9 --- /dev/null +++ b/docs/interfaces/EventUserSupportAgain.html @@ -0,0 +1,6 @@ +EventUserSupportAgain | osu-api-v2-js

    Interface EventUserSupportAgain

    Hierarchy

    Properties

    Properties

    created_at: Date
    id: number
    type: "userSupportAgain"
    user: {
        url: string;
        username: string;
    }

    Type declaration

    • url: string

      What goes after the website's URL, so for example, it could be the /u/7276846 of https://osu.ppy.sh/u/7276846 (or users instead of u)

      +
    • username: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/EventUserSupportFirst.html b/docs/interfaces/EventUserSupportFirst.html new file mode 100644 index 0000000..91fbc9c --- /dev/null +++ b/docs/interfaces/EventUserSupportFirst.html @@ -0,0 +1,6 @@ +EventUserSupportFirst | osu-api-v2-js

    Interface EventUserSupportFirst

    Hierarchy

    Properties

    Properties

    created_at: Date
    id: number
    type: "userSupportFirst"
    user: {
        url: string;
        username: string;
    }

    Type declaration

    • url: string

      What goes after the website's URL, so for example, it could be the /u/7276846 of https://osu.ppy.sh/u/7276846 (or users instead of u)

      +
    • username: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/EventUserSupportGift.html b/docs/interfaces/EventUserSupportGift.html new file mode 100644 index 0000000..ea502b1 --- /dev/null +++ b/docs/interfaces/EventUserSupportGift.html @@ -0,0 +1,6 @@ +EventUserSupportGift | osu-api-v2-js

    Interface EventUserSupportGift

    Hierarchy

    Properties

    Properties

    created_at: Date
    id: number
    type: "userSupportGift"
    user: {
        url: string;
        username: string;
    }

    Type declaration

    • url: string

      What goes after the website's URL, so for example, it could be the /u/7276846 of https://osu.ppy.sh/u/7276846 (or users instead of u)

      +
    • username: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/EventUsernameChange.html b/docs/interfaces/EventUsernameChange.html new file mode 100644 index 0000000..40610d5 --- /dev/null +++ b/docs/interfaces/EventUsernameChange.html @@ -0,0 +1,6 @@ +EventUsernameChange | osu-api-v2-js

    Interface EventUsernameChange

    Hierarchy

    Properties

    Properties

    created_at: Date
    id: number
    type: "usernameChange"
    user: {
        previousUsername: string;
        url: string;
        username: string;
    }

    Type declaration

    • previousUsername: string
    • url: string

      What goes after the website's URL, so for example, it could be the /u/7276846 of https://osu.ppy.sh/u/7276846

      +
    • username: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/KudosuHistory.html b/docs/interfaces/KudosuHistory.html index f9946c6..892119a 100644 --- a/docs/interfaces/KudosuHistory.html +++ b/docs/interfaces/KudosuHistory.html @@ -1,8 +1,9 @@ -KudosuHistory | osu-api-v2-js

    Interface KudosuHistory

    Hierarchy

    • KudosuHistory

    Properties

    action +KudosuHistory | osu-api-v2-js

    Interface KudosuHistory

    Expected from api.getUserKudosu()

    +

    Hierarchy

    • KudosuHistory

    Properties

    action: "reset" | "give" | "vote.give" | "vote.reset" | "revoke" | "vote.revoke"
    amount: number
    created_at: Date
    giver: null | {
        url: string;
        username: string;
    }

    Type declaration

    • url: string
    • username: string
    id: number
    model: string
    post: {
        title: string;
        url: null | string;
    }

    Type declaration

    • title: string
    • url: null | string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    action: "reset" | "give" | "vote.give" | "vote.reset" | "revoke" | "vote.revoke"
    amount: number
    created_at: Date
    giver: null | {
        url: string;
        username: string;
    }

    Type declaration

    • url: string
    • username: string
    id: number
    model: string
    post: {
        title: string;
        url: null | string;
    }

    Type declaration

    • title: string
    • url: null | string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/Leader.html b/docs/interfaces/Leader.html index f0c59fb..77a9606 100644 --- a/docs/interfaces/Leader.html +++ b/docs/interfaces/Leader.html @@ -1,4 +1,4 @@ -Leader | osu-api-v2-js

    Interface Leader

    Hierarchy

    • Leader

    Properties

    accuracy +Leader | osu-api-v2-js

    Interface Leader

    Hierarchy

    • Leader

    Properties

    Properties

    accuracy: number

    In a format where 96.40% would be 0.9640 (likely with some numbers after the zero)

    -
    attempts: number
    completed: number
    pp: number
    room_id: number
    total_score: number
    user_id: number

    Generated using TypeDoc

    \ No newline at end of file +
    attempts: number
    completed: number
    pp: number
    room_id: number
    total_score: number
    user_id: number

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/Match.html b/docs/interfaces/Match.html index 287d545..a48aa80 100644 --- a/docs/interfaces/Match.html +++ b/docs/interfaces/Match.html @@ -1,10 +1,10 @@ Match | osu-api-v2-js

    Interface Match

    Expected from api.getMatch()

    -

    Hierarchy

    • Match

    Properties

    Hierarchy

    • Match

    Properties

    current_game_id: null | number
    events: {
        detail: {
            text?: string;
            type: string;
        };
        game?: {
            beatmap: BeatmapWithBeatmapset;
            beatmap_id: number;
            end_time: null | Date;
            id: number;
            mode: string;
            mode_int: Rulesets;
            mods: string[];
            scores: ScoreWithMatch[];
            scoring_type: string;
            start_time: Date;
            team_type: string;
        };
        id: number;
        timestamp: Date;
        user_id: null | number;
    }[]

    Type declaration

    • detail: {
          text?: string;
          type: string;
      }
      • Optional text?: string

        If detail.type is other, this exists and will be the name of the room

        +

    Properties

    current_game_id: null | number
    events: {
        detail: {
            text?: string;
            type: string;
        };
        game?: {
            beatmap: BeatmapWithBeatmapset;
            beatmap_id: number;
            end_time: null | Date;
            id: number;
            mode: string;
            mode_int: Rulesets;
            mods: string[];
            scores: ScoreWithMatch[];
            scoring_type: string;
            start_time: Date;
            team_type: string;
        };
        id: number;
        timestamp: Date;
        user_id: null | number;
    }[]

    Type declaration

    • detail: {
          text?: string;
          type: string;
      }
      • Optional text?: string

        If detail.type is other, this exists and will be the name of the room

      • type: string
    • Optional game?: {
          beatmap: BeatmapWithBeatmapset;
          beatmap_id: number;
          end_time: null | Date;
          id: number;
          mode: string;
          mode_int: Rulesets;
          mods: string[];
          scores: ScoreWithMatch[];
          scoring_type: string;
          start_time: Date;
          team_type: string;
      }

      If detail.type is other, then this should exist!

      -
    • id: number
    • timestamp: Date
    • user_id: null | number
    first_event_id: number
    latest_event_id: number
    match: MatchInfo

    Generated using TypeDoc

    \ No newline at end of file +
  • id: number
  • timestamp: Date
  • user_id: null | number
  • first_event_id: number
    latest_event_id: number
    match: MatchInfo

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/MatchInfo.html b/docs/interfaces/MatchInfo.html index 127c760..bcfa75a 100644 --- a/docs/interfaces/MatchInfo.html +++ b/docs/interfaces/MatchInfo.html @@ -1,6 +1,6 @@ MatchInfo | osu-api-v2-js

    Properties

    end_time: null | Date
    id: number
    name: string
    start_time: Date

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/MultiplayerScore.html b/docs/interfaces/MultiplayerScore.html index e526214..c95fbc2 100644 --- a/docs/interfaces/MultiplayerScore.html +++ b/docs/interfaces/MultiplayerScore.html @@ -1,6 +1,6 @@ MultiplayerScore | osu-api-v2-js

    Interface MultiplayerScore

    Expected from MultiplayerScores

    Remarks

    This particular interface seems really unstable, beware

    -

    Hierarchy

    • MultiplayerScore

    Properties

    Hierarchy

    • MultiplayerScore

    Properties

    Properties

    accuracy: number

    In a format where 96.40% would be 0.9640 (and no number afterwards)

    -
    beatmap_id: number
    ended_at: Date
    id: number
    max_combo: number
    maximum_statistics: {
        great: number;
        ignore_hit: number;
        large_tick_hit: number;
        small_tick_hit: number;
    }

    Type declaration

    • great: number
    • ignore_hit: number
    • large_tick_hit: number
    • small_tick_hit: number
    mods: Mod[]
    passed: boolean
    playlist_item_id: number
    pp: null | number
    rank: string
    replay: boolean
    room_id: number
    ruleset_id: number
    started_at: Date
    statistics: {
        great?: number;
        large_bonus?: number;
        large_tick_hit?: number;
        meh?: number;
        miss?: number;
        ok?: number;
        small_bonus?: number;
        small_tick_hit?: number;
        small_tick_miss?: number;
    }

    All of its properties are optional because instead of being 0, the property actually disappears instead! +

    beatmap_id: number
    ended_at: Date
    id: number
    max_combo: number
    maximum_statistics: {
        great: number;
        ignore_hit: number;
        large_tick_hit: number;
        small_tick_hit: number;
    }

    Type declaration

    • great: number
    • ignore_hit: number
    • large_tick_hit: number
    • small_tick_hit: number
    mods: Mod[]
    passed: boolean
    playlist_item_id: number
    pp: null | number
    rank: string
    replay: boolean
    room_id: number
    ruleset_id: number
    started_at: Date
    statistics: {
        great?: number;
        large_bonus?: number;
        large_tick_hit?: number;
        meh?: number;
        miss?: number;
        ok?: number;
        small_bonus?: number;
        small_tick_hit?: number;
        small_tick_miss?: number;
    }

    All of its properties are optional because instead of being 0, the property actually disappears instead! (so if the score has no miss, the miss property is simply not there)

    -

    Type declaration

    • Optional great?: number
    • Optional large_bonus?: number
    • Optional large_tick_hit?: number
    • Optional meh?: number
    • Optional miss?: number
    • Optional ok?: number
    • Optional small_bonus?: number
    • Optional small_tick_hit?: number
    • Optional small_tick_miss?: number
    total_score: number
    type: string
    user_id: number

    Generated using TypeDoc

    \ No newline at end of file +

    Type declaration

    • Optional great?: number
    • Optional large_bonus?: number
    • Optional large_tick_hit?: number
    • Optional meh?: number
    • Optional miss?: number
    • Optional ok?: number
    • Optional small_bonus?: number
    • Optional small_tick_hit?: number
    • Optional small_tick_miss?: number
    total_score: number
    type: string
    user_id: number

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/MultiplayerScores.html b/docs/interfaces/MultiplayerScores.html index ece6f44..e653cda 100644 --- a/docs/interfaces/MultiplayerScores.html +++ b/docs/interfaces/MultiplayerScores.html @@ -1,10 +1,10 @@ MultiplayerScores | osu-api-v2-js

    Interface MultiplayerScores

    Expected from api.getPlaylistItemScores()

    -

    Hierarchy

    • MultiplayerScores

    Properties

    Hierarchy

    • MultiplayerScores

    Properties

    cursor_string: null | string

    Will be null if there is no next page

    -
    params: {
        limit: number;
        sort: string;
    }

    Type declaration

    • limit: number
    • sort: string
    total: number

    How many scores there are across all pages, not necessarily scores.length

    -
    user_score: null | MultiplayerScore

    Will be null if not an authorized user or if the authorized user has no score

    -

    Generated using TypeDoc

    \ No newline at end of file +
    params: {
        limit: number;
        sort: string;
    }

    Type declaration

    • limit: number
    • sort: string
    total: number

    How many scores there are across all pages, not necessarily scores.length

    +
    user_score: null | MultiplayerScore

    Will be null if not an authorized user or if the authorized user has no score

    +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/PlaylistItem.html b/docs/interfaces/PlaylistItem.html index 7cd606e..3584c8c 100644 --- a/docs/interfaces/PlaylistItem.html +++ b/docs/interfaces/PlaylistItem.html @@ -1,5 +1,5 @@ PlaylistItem | osu-api-v2-js

    Interface PlaylistItem

    Expected from Room

    -

    Hierarchy

    • PlaylistItem

    Properties

    Hierarchy

    • PlaylistItem

    Properties

    allowed_mods: Mod[]
    beatmap_id: number
    expired: boolean
    id: number
    owner_id: number
    played_at: null | Date

    Should be null if the room isn't the realtime multiplayer kind

    -
    playlist_order: null | number

    Should be null if the room isn't the realtime multiplayer kind

    -
    required_mods: Mod[]
    room_id: number
    ruleset_id: number

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    allowed_mods: Mod[]
    beatmap_id: number
    expired: boolean
    id: number
    owner_id: number
    played_at: null | Date

    Should be null if the room isn't the realtime multiplayer kind

    +
    playlist_order: null | number

    Should be null if the room isn't the realtime multiplayer kind

    +
    required_mods: Mod[]
    room_id: number
    ruleset_id: number

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/Rankings.html b/docs/interfaces/Rankings.html index d70a2dd..0d5cace 100644 --- a/docs/interfaces/Rankings.html +++ b/docs/interfaces/Rankings.html @@ -1,7 +1,7 @@ Rankings | osu-api-v2-js

    Interface Rankings

    Expected from api.getRanking()

    -

    Hierarchy

    • RankingsBare
      • Rankings

    Properties

    Hierarchy

    • RankingsBare
      • Rankings

    Properties

    Properties

    cursor: {
        page: null | number;
    }

    Type declaration

    • page: null | number

      The number of the next page, is null if no more results are available

      -
    total: number

    Total amount of elements available across all pages, not on this specific page! Maximum of 10000

    -

    Generated using TypeDoc

    \ No newline at end of file +
    total: number

    Total amount of elements available across all pages, not on this specific page! Maximum of 10000

    +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/RankingsCountry.html b/docs/interfaces/RankingsCountry.html index a23bc2c..ed10809 100644 --- a/docs/interfaces/RankingsCountry.html +++ b/docs/interfaces/RankingsCountry.html @@ -1,10 +1,10 @@ RankingsCountry | osu-api-v2-js

    Interface RankingsCountry

    Expected from api.getCountryRanking()

    Remarks

    Not in the API's documentation

    -

    Hierarchy

    • RankingsBare
      • RankingsCountry

    Properties

    Hierarchy

    • RankingsBare
      • RankingsCountry

    Properties

    Properties

    cursor: {
        page: null | number;
    }

    Type declaration

    • page: null | number

      The number of the next page, is null if no more results are available

      -
    ranking: {
        active_users: number;
        code: string;
        country: {
            code: string;
            name: string;
        };
        performance: number;
        play_count: number;
        ranked_score: number;
    }[]

    Type declaration

    • active_users: number
    • code: string

      Same as country.code

      +
    ranking: {
        active_users: number;
        code: string;
        country: {
            code: string;
            name: string;
        };
        performance: number;
        play_count: number;
        ranked_score: number;
    }[]

    Type declaration

    • active_users: number
    • code: string

      Same as country.code

    • country: {
          code: string;
          name: string;
      }
      • code: string

        The country's ISO 3166-1 alpha-2 code! (France would be FR, United States US)

        -
      • name: string
    • performance: number
    • play_count: number
    • ranked_score: number
    total: number

    Total amount of elements available across all pages, not on this specific page! Maximum of 10000

    -

    Generated using TypeDoc

    \ No newline at end of file +
  • name: string
  • performance: number
  • play_count: number
  • ranked_score: number
  • total: number

    Total amount of elements available across all pages, not on this specific page! Maximum of 10000

    +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/RankingsSpotlight.html b/docs/interfaces/RankingsSpotlight.html index efe85ed..2ae75d8 100644 --- a/docs/interfaces/RankingsSpotlight.html +++ b/docs/interfaces/RankingsSpotlight.html @@ -1,5 +1,5 @@ RankingsSpotlight | osu-api-v2-js

    Properties

    beatmapsets: BeatmapsetExtended[]

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/Room.html b/docs/interfaces/Room.html index d2834f7..9de9841 100644 --- a/docs/interfaces/Room.html +++ b/docs/interfaces/Room.html @@ -1,5 +1,5 @@ Room | osu-api-v2-js

    Interface Room

    Expected from api.getRoom()

    -

    Hierarchy

    • Room

    Properties

    Hierarchy

    • Room

    Properties

    Properties

    active: boolean
    auto_skip: boolean
    category: string
    channel_id: number
    current_user_score?: {
        accuracy: number;
        attempts: number;
        completed: number;
        playlist_item_attempts: {
            attempts: number;
            id: number;
        }[];
        pp: number;
        room_id: number;
        total_score: number;
        user_id: number;
    }

    Only exists if authorized user

    +

    Properties

    active: boolean
    auto_skip: boolean
    category: string
    channel_id: number
    current_user_score?: {
        accuracy: number;
        attempts: number;
        completed: number;
        playlist_item_attempts: {
            attempts: number;
            id: number;
        }[];
        pp: number;
        room_id: number;
        total_score: number;
        user_id: number;
    }

    Only exists if authorized user

    Type declaration

    • accuracy: number

      In a format where 96.40% would be 0.9640 (likely with some numbers after the zero)

    • attempts: number
    • completed: number
    • playlist_item_attempts: {
          attempts: number;
          id: number;
      }[]

      How many (completed?) attempts on each item? Empty array if the multiplayer room is the realtime kind

      -
    • pp: number
    • room_id: number
    • total_score: number
    • user_id: number
    ends_at: null | Date
    has_password: boolean
    id: number
    max_attempts: null | number
    name: string
    participant_count: number
    playlist: PlaylistItem[]
    queue_mode: string
    recent_participants: User[]
    starts_at: Date
    type: string
    user_id: number

    Generated using TypeDoc

    \ No newline at end of file +
  • pp: number
  • room_id: number
  • total_score: number
  • user_id: number
  • ends_at: null | Date
    has_password: boolean
    id: number
    max_attempts: null | number
    name: string
    participant_count: number
    playlist: PlaylistItem[]
    queue_mode: string
    recent_participants: User[]
    starts_at: Date
    type: string
    user_id: number

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/Score.html b/docs/interfaces/Score.html index 12f7997..1fe32a0 100644 --- a/docs/interfaces/Score.html +++ b/docs/interfaces/Score.html @@ -1,5 +1,5 @@ Score | osu-api-v2-js

    Interface Score

    Expected from api.getBeatmapUserScores()

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    Properties

    accuracy: number

    In a format where 96.40% would be 0.9640 (likely with some numbers after the zero)

    -
    best_id: null | number
    created_at: Date
    id: null | number
    max_combo: number
    mode: string
    mode_int: Rulesets
    mods: string[]
    passed: boolean
    perfect: boolean
    pp: null | number

    null when Beatmap is Loved (for example)

    -
    rank: string

    Also known as a grade, for example this is X (SS) if accuracy is 1 (100.00%)

    -
    replay: boolean

    Can this score's replay be downloaded from the website?

    -
    score: number
    statistics: {
        count_100: number;
        count_300: number;
        count_50: number;
        count_geki: number;
        count_katu: number;
        count_miss: number;
    }

    Type declaration

    • count_100: number
    • count_300: number
    • count_50: number
    • count_geki: number
    • count_katu: number
    • count_miss: number
    type: string
    user_id: number

    The ID of the user who made the score

    -
    weight?: {
        percentage: number;
        pp: number;
    }

    Type declaration

    • percentage: number
    • pp: number

    Remarks

    Only if type is set to best on getUserScores

    -

    Generated using TypeDoc

    \ No newline at end of file +
    best_id: null | number
    created_at: Date
    id: null | number
    max_combo: number
    mode: string
    mode_int: Rulesets
    mods: string[]
    passed: boolean
    perfect: boolean
    pp: null | number

    null when Beatmap is Loved (for example)

    +
    rank: string

    Also known as a grade, for example this is X (SS) if accuracy is 1 (100.00%)

    +
    replay: boolean

    Can this score's replay be downloaded from the website?

    +
    score: number
    statistics: {
        count_100: number;
        count_300: number;
        count_50: number;
        count_geki: number;
        count_katu: number;
        count_miss: number;
    }

    Type declaration

    • count_100: number
    • count_300: number
    • count_50: number
    • count_geki: number
    • count_katu: number
    • count_miss: number
    type: string
    user_id: number

    The ID of the user who made the score

    +
    weight?: {
        percentage: number;
        pp: number;
    }

    Type declaration

    • percentage: number
    • pp: number

    Remarks

    Only if type is set to best on getUserScores

    +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/ScoreWithMatch.html b/docs/interfaces/ScoreWithMatch.html index c5d3fae..01c275a 100644 --- a/docs/interfaces/ScoreWithMatch.html +++ b/docs/interfaces/ScoreWithMatch.html @@ -1,5 +1,5 @@ ScoreWithMatch | osu-api-v2-js

    Interface ScoreWithMatch

    Expected from Match

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    Properties

    accuracy: number

    In a format where 96.40% would be 0.9640 (likely with some numbers after the zero)

    -
    best_id: null | number
    created_at: Date
    id: null | number
    match: {
        pass: boolean;
        slot: number;
        team: string;
    }

    Type declaration

    • pass: boolean
    • slot: number
    • team: string
    max_combo: number
    mode: string
    mode_int: Rulesets
    mods: string[]
    passed: boolean
    perfect: boolean
    pp: null | number

    null when Beatmap is Loved (for example)

    -
    rank: string

    Also known as a grade, for example this is X (SS) if accuracy is 1 (100.00%)

    -
    replay: boolean

    Can this score's replay be downloaded from the website?

    -
    score: number
    statistics: {
        count_100: number;
        count_300: number;
        count_50: number;
        count_geki: number;
        count_katu: number;
        count_miss: number;
    }

    Type declaration

    • count_100: number
    • count_300: number
    • count_50: number
    • count_geki: number
    • count_katu: number
    • count_miss: number
    type: string
    user_id: number

    The ID of the user who made the score

    -
    weight?: {
        percentage: number;
        pp: number;
    }

    Type declaration

    • percentage: number
    • pp: number

    Remarks

    Only if type is set to best on getUserScores

    -

    Generated using TypeDoc

    \ No newline at end of file +
    best_id: null | number
    created_at: Date
    id: null | number
    match: {
        pass: boolean;
        slot: number;
        team: string;
    }

    Type declaration

    • pass: boolean
    • slot: number
    • team: string
    max_combo: number
    mode: string
    mode_int: Rulesets
    mods: string[]
    passed: boolean
    perfect: boolean
    pp: null | number

    null when Beatmap is Loved (for example)

    +
    rank: string

    Also known as a grade, for example this is X (SS) if accuracy is 1 (100.00%)

    +
    replay: boolean

    Can this score's replay be downloaded from the website?

    +
    score: number
    statistics: {
        count_100: number;
        count_300: number;
        count_50: number;
        count_geki: number;
        count_katu: number;
        count_miss: number;
    }

    Type declaration

    • count_100: number
    • count_300: number
    • count_50: number
    • count_geki: number
    • count_katu: number
    • count_miss: number
    type: string
    user_id: number

    The ID of the user who made the score

    +
    weight?: {
        percentage: number;
        pp: number;
    }

    Type declaration

    • percentage: number
    • pp: number

    Remarks

    Only if type is set to best on getUserScores

    +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/ScoreWithUser.html b/docs/interfaces/ScoreWithUser.html index a4268e1..f70389e 100644 --- a/docs/interfaces/ScoreWithUser.html +++ b/docs/interfaces/ScoreWithUser.html @@ -1,5 +1,5 @@ ScoreWithUser | osu-api-v2-js

    Interface ScoreWithUser

    Expected from api.getBeatmapScores()

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    Properties

    accuracy: number

    In a format where 96.40% would be 0.9640 (likely with some numbers after the zero)

    -
    best_id: null | number
    created_at: Date
    id: null | number
    max_combo: number
    mode: string
    mode_int: Rulesets
    mods: string[]
    passed: boolean
    perfect: boolean
    pp: null | number

    null when Beatmap is Loved (for example)

    -
    rank: string

    Also known as a grade, for example this is X (SS) if accuracy is 1 (100.00%)

    -
    replay: boolean

    Can this score's replay be downloaded from the website?

    -
    score: number
    statistics: {
        count_100: number;
        count_300: number;
        count_50: number;
        count_geki: number;
        count_katu: number;
        count_miss: number;
    }

    Type declaration

    • count_100: number
    • count_300: number
    • count_50: number
    • count_geki: number
    • count_katu: number
    • count_miss: number
    type: string
    user_id: number

    The ID of the user who made the score

    -
    weight?: {
        percentage: number;
        pp: number;
    }

    Type declaration

    • percentage: number
    • pp: number

    Remarks

    Only if type is set to best on getUserScores

    -

    Generated using TypeDoc

    \ No newline at end of file +
    best_id: null | number
    created_at: Date
    id: null | number
    max_combo: number
    mode: string
    mode_int: Rulesets
    mods: string[]
    passed: boolean
    perfect: boolean
    pp: null | number

    null when Beatmap is Loved (for example)

    +
    rank: string

    Also known as a grade, for example this is X (SS) if accuracy is 1 (100.00%)

    +
    replay: boolean

    Can this score's replay be downloaded from the website?

    +
    score: number
    statistics: {
        count_100: number;
        count_300: number;
        count_50: number;
        count_geki: number;
        count_katu: number;
        count_miss: number;
    }

    Type declaration

    • count_100: number
    • count_300: number
    • count_50: number
    • count_geki: number
    • count_katu: number
    • count_miss: number
    type: string
    user_id: number

    The ID of the user who made the score

    +
    weight?: {
        percentage: number;
        pp: number;
    }

    Type declaration

    • percentage: number
    • pp: number

    Remarks

    Only if type is set to best on getUserScores

    +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/ScoreWithUserBeatmap.html b/docs/interfaces/ScoreWithUserBeatmap.html index cbc2a69..d1ebbd7 100644 --- a/docs/interfaces/ScoreWithUserBeatmap.html +++ b/docs/interfaces/ScoreWithUserBeatmap.html @@ -1,5 +1,5 @@ ScoreWithUserBeatmap | osu-api-v2-js

    Interface ScoreWithUserBeatmap

    Expected from BeatmapUserScore

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    Properties

    accuracy: number

    In a format where 96.40% would be 0.9640 (likely with some numbers after the zero)

    -
    best_id: null | number
    created_at: Date
    id: null | number
    max_combo: number
    mode: string
    mode_int: Rulesets
    mods: string[]
    passed: boolean
    perfect: boolean
    pp: null | number

    null when Beatmap is Loved (for example)

    -
    rank: string

    Also known as a grade, for example this is X (SS) if accuracy is 1 (100.00%)

    -
    replay: boolean

    Can this score's replay be downloaded from the website?

    -
    score: number
    statistics: {
        count_100: number;
        count_300: number;
        count_50: number;
        count_geki: number;
        count_katu: number;
        count_miss: number;
    }

    Type declaration

    • count_100: number
    • count_300: number
    • count_50: number
    • count_geki: number
    • count_katu: number
    • count_miss: number
    type: string
    user: User
    user_id: number

    The ID of the user who made the score

    -
    weight?: {
        percentage: number;
        pp: number;
    }

    Type declaration

    • percentage: number
    • pp: number

    Remarks

    Only if type is set to best on getUserScores

    -

    Generated using TypeDoc

    \ No newline at end of file +
    best_id: null | number
    created_at: Date
    id: null | number
    max_combo: number
    mode: string
    mode_int: Rulesets
    mods: string[]
    passed: boolean
    perfect: boolean
    pp: null | number

    null when Beatmap is Loved (for example)

    +
    rank: string

    Also known as a grade, for example this is X (SS) if accuracy is 1 (100.00%)

    +
    replay: boolean

    Can this score's replay be downloaded from the website?

    +
    score: number
    statistics: {
        count_100: number;
        count_300: number;
        count_50: number;
        count_geki: number;
        count_katu: number;
        count_miss: number;
    }

    Type declaration

    • count_100: number
    • count_300: number
    • count_50: number
    • count_geki: number
    • count_katu: number
    • count_miss: number
    type: string
    user: User
    user_id: number

    The ID of the user who made the score

    +
    weight?: {
        percentage: number;
        pp: number;
    }

    Type declaration

    • percentage: number
    • pp: number

    Remarks

    Only if type is set to best on getUserScores

    +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/ScoreWithUserBeatmapBeatmapset.html b/docs/interfaces/ScoreWithUserBeatmapBeatmapset.html index 8456a2c..73a2f1b 100644 --- a/docs/interfaces/ScoreWithUserBeatmapBeatmapset.html +++ b/docs/interfaces/ScoreWithUserBeatmapBeatmapset.html @@ -1,5 +1,5 @@ ScoreWithUserBeatmapBeatmapset | osu-api-v2-js

    Interface ScoreWithUserBeatmapBeatmapset

    Expected from api.getUserScores()

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    Properties

    accuracy: number

    In a format where 96.40% would be 0.9640 (likely with some numbers after the zero)

    -
    beatmapset: Beatmapset
    best_id: null | number
    created_at: Date
    id: null | number
    max_combo: number
    mode: string
    mode_int: Rulesets
    mods: string[]
    passed: boolean
    perfect: boolean
    pp: null | number

    null when Beatmap is Loved (for example)

    -
    rank: string

    Also known as a grade, for example this is X (SS) if accuracy is 1 (100.00%)

    -
    replay: boolean

    Can this score's replay be downloaded from the website?

    -
    score: number
    statistics: {
        count_100: number;
        count_300: number;
        count_50: number;
        count_geki: number;
        count_katu: number;
        count_miss: number;
    }

    Type declaration

    • count_100: number
    • count_300: number
    • count_50: number
    • count_geki: number
    • count_katu: number
    • count_miss: number
    type: string
    user: User
    user_id: number

    The ID of the user who made the score

    -
    weight?: {
        percentage: number;
        pp: number;
    }

    Type declaration

    • percentage: number
    • pp: number

    Remarks

    Only if type is set to best on getUserScores

    -

    Generated using TypeDoc

    \ No newline at end of file +
    beatmapset: Beatmapset
    best_id: null | number
    created_at: Date
    id: null | number
    max_combo: number
    mode: string
    mode_int: Rulesets
    mods: string[]
    passed: boolean
    perfect: boolean
    pp: null | number

    null when Beatmap is Loved (for example)

    +
    rank: string

    Also known as a grade, for example this is X (SS) if accuracy is 1 (100.00%)

    +
    replay: boolean

    Can this score's replay be downloaded from the website?

    +
    score: number
    statistics: {
        count_100: number;
        count_300: number;
        count_50: number;
        count_geki: number;
        count_katu: number;
        count_miss: number;
    }

    Type declaration

    • count_100: number
    • count_300: number
    • count_50: number
    • count_geki: number
    • count_katu: number
    • count_miss: number
    type: string
    user: User
    user_id: number

    The ID of the user who made the score

    +
    weight?: {
        percentage: number;
        pp: number;
    }

    Type declaration

    • percentage: number
    • pp: number

    Remarks

    Only if type is set to best on getUserScores

    +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/SearchResultUser.html b/docs/interfaces/SearchResultUser.html new file mode 100644 index 0000000..a3ec3a0 --- /dev/null +++ b/docs/interfaces/SearchResultUser.html @@ -0,0 +1,6 @@ +SearchResultUser | osu-api-v2-js

    Interface SearchResultUser

    Expected from api.searchUser()

    +

    Hierarchy

    • SearchResult
      • SearchResultUser

    Properties

    Properties

    data: User[]

    The Users that have been found

    +
    total: number

    How many results there are across all pages

    +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/SearchResultWiki.html b/docs/interfaces/SearchResultWiki.html new file mode 100644 index 0000000..527bba1 --- /dev/null +++ b/docs/interfaces/SearchResultWiki.html @@ -0,0 +1,6 @@ +SearchResultWiki | osu-api-v2-js

    Interface SearchResultWiki

    Expected from api.searchWiki()

    +

    Hierarchy

    • SearchResult
      • SearchResultWiki

    Properties

    Properties

    data: WikiPage[]

    The WikiPages that have been found

    +
    total: number

    How many results there are across all pages

    +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/Spotlight.html b/docs/interfaces/Spotlight.html index 132abf9..26f58bd 100644 --- a/docs/interfaces/Spotlight.html +++ b/docs/interfaces/Spotlight.html @@ -1,9 +1,9 @@ Spotlight | osu-api-v2-js

    Interface Spotlight

    Expected from api.getSpotlights()

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    end_date: Date
    id: number
    mode_specific: boolean

    Pretty sure this is only true when the spotlight has different beatmaps for each ruleset

    -
    name: string
    start_date: Date
    type: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    end_date: Date
    id: number
    mode_specific: boolean

    Pretty sure this is only true when the spotlight has different beatmaps for each ruleset

    +
    name: string
    start_date: Date
    type: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/SpotlightWithParticipantcount.html b/docs/interfaces/SpotlightWithParticipantcount.html index d9de0b0..9bc04d4 100644 --- a/docs/interfaces/SpotlightWithParticipantcount.html +++ b/docs/interfaces/SpotlightWithParticipantcount.html @@ -1,10 +1,10 @@ SpotlightWithParticipantcount | osu-api-v2-js

    Interface SpotlightWithParticipantcount

    Expected from RankingsSpotlight

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    end_date: Date
    id: number
    mode_specific: boolean

    Pretty sure this is only true when the spotlight has different beatmaps for each ruleset

    -
    name: string
    participant_count: number
    start_date: Date
    type: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    end_date: Date
    id: number
    mode_specific: boolean

    Pretty sure this is only true when the spotlight has different beatmaps for each ruleset

    +
    name: string
    participant_count: number
    start_date: Date
    type: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/UpdateStream.html b/docs/interfaces/UpdateStream.html index 0d352ce..d922571 100644 --- a/docs/interfaces/UpdateStream.html +++ b/docs/interfaces/UpdateStream.html @@ -1,6 +1,6 @@ UpdateStream | osu-api-v2-js

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    display_name: null | string
    id: number
    is_featured: boolean
    name: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/User.html b/docs/interfaces/User.html index 307b716..9ecc8bc 100644 --- a/docs/interfaces/User.html +++ b/docs/interfaces/User.html @@ -1,5 +1,5 @@ -User | osu-api-v2-js

    Interface User

    Expected from BeatmapsetExtendedPlus, Room

    -

    Hierarchy

    Properties

    avatar_url +User | osu-api-v2-js

    Interface User

    Expected from BeatmapsetExtendedPlus, Room, SearchResultUser

    +

    Hierarchy

    Properties

    avatar_url: string
    country_code: string
    default_group: string
    id: number
    is_active: boolean
    is_bot: boolean
    is_deleted: boolean
    is_online: boolean
    is_supporter: boolean
    last_visit: null | Date
    pm_friends_only: boolean
    profile_colour: null | string
    username: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    avatar_url: string
    country_code: string
    default_group: string
    id: number
    is_active: boolean
    is_bot: boolean
    is_deleted: boolean
    is_online: boolean
    is_supporter: boolean
    last_visit: null | Date
    pm_friends_only: boolean
    profile_colour: null | string
    username: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/UserExtended.html b/docs/interfaces/UserExtended.html index 3a1d442..4cb715e 100644 --- a/docs/interfaces/UserExtended.html +++ b/docs/interfaces/UserExtended.html @@ -1,5 +1,5 @@ UserExtended | osu-api-v2-js

    Interface UserExtended

    Expected from api.getUser()

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    account_history: {
        description: null | string;
        id: number;
        length: number;
        permanent: boolean;
        timestamp: Date;
        type: "note" | "restriction" | "silence";
    }[]

    Type declaration

    • description: null | string
    • id: number
    • length: number
    • permanent: boolean
    • timestamp: Date
    • type: "note" | "restriction" | "silence"
    active_tournament_banner: null | ProfileBanner
    active_tournament_banners: ProfileBanner[]

    This is not documented by osu!, likely because support for multiple banners has been recently added (OWC2023)

    -
    avatar_url: string
    badges: {
        awarded_at: Date;
        description: string;
        image_url: string;
        url: string;
    }[]

    Type declaration

    • awarded_at: Date
    • description: string
    • image_url: string
    • url: string
    beatmap_playcounts_count: number
    comments_count: number
    country: {
        code: string;
        name: string;
    }

    Type declaration

    • code: string
    • name: string
    country_code: string
    cover: {
        custom_url: null | string;
        id: null | number;
        url: string;
    }

    Type declaration

    • custom_url: null | string
    • id: null | number
    • url: string
    cover_url: string
    default_group: string
    discord: null | string
    favourite_beatmapset_count: number
    follower_count: number
    graveyard_beatmapset_count: number
    groups: {
        colour: null | string;
        has_listing: boolean;
        has_playmodes: boolean;
        id: number;
        identifier: string;
        is_probationary: boolean;
        name: string;
        playmodes: null | string[];
        short_name: string;
    }[]

    Type declaration

    • colour: null | string
    • has_listing: boolean
    • has_playmodes: boolean
    • id: number
    • identifier: string
    • is_probationary: boolean
    • name: string
    • playmodes: null | string[]
    • short_name: string
    guest_beatmapset_count: number
    has_supported: boolean
    id: number
    interests: null | string
    is_active: boolean
    is_bot: boolean
    is_deleted: boolean
    is_online: boolean
    is_supporter: boolean
    join_date: Date
    kudosu: {
        available: number;
        total: number;
    }

    Type declaration

    • available: number
    • total: number
    last_visit: null | Date
    location: null | string
    loved_beatmapset_count: number
    mapping_follower_count: number
    max_blocks: number
    max_friends: number
    monthly_playcounts: {
        count: number;
        start_date: Date;
    }[]

    Type declaration

    • count: number
    • start_date: Date
    nominated_beatmapset_count: number
    occupation: null | string
    page: {
        html: string;
        raw: string;
    }

    Type declaration

    • html: string
    • raw: string

      Basically the text with the BBCode

      -
    pending_beatmapset_count: number
    playmode: string
    playstyle: string[]
    pm_friends_only: boolean
    post_count: number
    previous_usernames: string[]
    profile_colour: null | string
    profile_order: ("me" | "recent_activity" | "beatmaps" | "historical" | "kudosu" | "top_ranks" | "medals")[]
    rank_highest: null | {
        rank: number;
        updated_at: Date;
    }

    Type declaration

    • rank: number
    • updated_at: Date
    rank_history: {
        data: number[];
        mode: string;
    }

    Type declaration

    • data: number[]
    • mode: string
    replays_watched_counts: {
        count: number;
        start_date: Date;
    }[]

    Type declaration

    • count: number
    • start_date: Date
    scores_best_count: number
    scores_first_count: number
    scores_pinned_count: number

    Specific to the Ruleset (playmode)

    -
    scores_recent_count: number
    support_level: number
    title: null | string
    title_url: null | string
    twitter: null | string
    user_achievements: {
        achieved_at: Date;
        achievement_id: number;
    }[]

    Type declaration

    • achieved_at: Date
    • achievement_id: number
    username: string
    website: null | string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    account_history: {
        description: null | string;
        id: number;
        length: number;
        permanent: boolean;
        timestamp: Date;
        type: "note" | "restriction" | "silence";
    }[]

    Type declaration

    • description: null | string
    • id: number
    • length: number
    • permanent: boolean
    • timestamp: Date
    • type: "note" | "restriction" | "silence"
    active_tournament_banner: null | ProfileBanner
    active_tournament_banners: ProfileBanner[]

    This is not documented by osu!, likely because support for multiple banners has been recently added (OWC2023)

    +
    avatar_url: string
    badges: {
        awarded_at: Date;
        description: string;
        image_url: string;
        url: string;
    }[]

    Type declaration

    • awarded_at: Date
    • description: string
    • image_url: string
    • url: string
    beatmap_playcounts_count: number
    comments_count: number
    country: {
        code: string;
        name: string;
    }

    Type declaration

    • code: string
    • name: string
    country_code: string
    cover: {
        custom_url: null | string;
        id: null | number;
        url: string;
    }

    Type declaration

    • custom_url: null | string
    • id: null | number
    • url: string
    cover_url: string
    default_group: string
    discord: null | string
    favourite_beatmapset_count: number
    follower_count: number
    graveyard_beatmapset_count: number
    groups: {
        colour: null | string;
        has_listing: boolean;
        has_playmodes: boolean;
        id: number;
        identifier: string;
        is_probationary: boolean;
        name: string;
        playmodes: null | string[];
        short_name: string;
    }[]

    Type declaration

    • colour: null | string
    • has_listing: boolean
    • has_playmodes: boolean
    • id: number
    • identifier: string
    • is_probationary: boolean
    • name: string
    • playmodes: null | string[]
    • short_name: string
    guest_beatmapset_count: number
    has_supported: boolean
    id: number
    interests: null | string
    is_active: boolean
    is_bot: boolean
    is_deleted: boolean
    is_online: boolean
    is_supporter: boolean
    join_date: Date
    kudosu: {
        available: number;
        total: number;
    }

    Type declaration

    • available: number
    • total: number
    last_visit: null | Date
    location: null | string
    loved_beatmapset_count: number
    mapping_follower_count: number
    max_blocks: number
    max_friends: number
    monthly_playcounts: {
        count: number;
        start_date: Date;
    }[]

    Type declaration

    • count: number
    • start_date: Date
    nominated_beatmapset_count: number
    occupation: null | string
    page: {
        html: string;
        raw: string;
    }

    Type declaration

    • html: string
    • raw: string

      Basically the text with the BBCode

      +
    pending_beatmapset_count: number
    playmode: string
    playstyle: string[]
    pm_friends_only: boolean
    post_count: number
    previous_usernames: string[]
    profile_colour: null | string
    profile_order: ("me" | "recent_activity" | "beatmaps" | "historical" | "kudosu" | "top_ranks" | "medals")[]
    rank_highest: null | {
        rank: number;
        updated_at: Date;
    }

    Type declaration

    • rank: number
    • updated_at: Date
    rank_history: {
        data: number[];
        mode: string;
    }

    Type declaration

    • data: number[]
    • mode: string
    replays_watched_counts: {
        count: number;
        start_date: Date;
    }[]

    Type declaration

    • count: number
    • start_date: Date
    scores_best_count: number
    scores_first_count: number
    scores_pinned_count: number

    Specific to the Ruleset (playmode)

    +
    scores_recent_count: number
    support_level: number
    title: null | string
    title_url: null | string
    twitter: null | string
    user_achievements: {
        achieved_at: Date;
        achievement_id: number;
    }[]

    Type declaration

    • achieved_at: Date
    • achievement_id: number
    username: string
    website: null | string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/UserExtendedWithStatisticsrulesets.html b/docs/interfaces/UserExtendedWithStatisticsrulesets.html index c0bb570..40bee30 100644 --- a/docs/interfaces/UserExtendedWithStatisticsrulesets.html +++ b/docs/interfaces/UserExtendedWithStatisticsrulesets.html @@ -1,5 +1,5 @@ UserExtendedWithStatisticsrulesets | osu-api-v2-js

    Interface UserExtendedWithStatisticsrulesets

    Expected from api.getResourceOwner()

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    account_history: {
        description: null | string;
        id: number;
        length: number;
        permanent: boolean;
        timestamp: Date;
        type: "note" | "restriction" | "silence";
    }[]

    Type declaration

    • description: null | string
    • id: number
    • length: number
    • permanent: boolean
    • timestamp: Date
    • type: "note" | "restriction" | "silence"
    active_tournament_banner: null | ProfileBanner
    active_tournament_banners: ProfileBanner[]

    This is not documented by osu!, likely because support for multiple banners has been recently added (OWC2023)

    -
    avatar_url: string
    badges: {
        awarded_at: Date;
        description: string;
        image_url: string;
        url: string;
    }[]

    Type declaration

    • awarded_at: Date
    • description: string
    • image_url: string
    • url: string
    beatmap_playcounts_count: number
    comments_count: number
    country: {
        code: string;
        name: string;
    }

    Type declaration

    • code: string
    • name: string
    country_code: string
    cover: {
        custom_url: null | string;
        id: null | number;
        url: string;
    }

    Type declaration

    • custom_url: null | string
    • id: null | number
    • url: string
    cover_url: string
    default_group: string
    discord: null | string
    favourite_beatmapset_count: number
    follower_count: number
    graveyard_beatmapset_count: number
    groups: {
        colour: null | string;
        has_listing: boolean;
        has_playmodes: boolean;
        id: number;
        identifier: string;
        is_probationary: boolean;
        name: string;
        playmodes: null | string[];
        short_name: string;
    }[]

    Type declaration

    • colour: null | string
    • has_listing: boolean
    • has_playmodes: boolean
    • id: number
    • identifier: string
    • is_probationary: boolean
    • name: string
    • playmodes: null | string[]
    • short_name: string
    guest_beatmapset_count: number
    has_supported: boolean
    id: number
    interests: null | string
    is_active: boolean
    is_bot: boolean
    is_deleted: boolean
    is_online: boolean
    is_supporter: boolean
    join_date: Date
    kudosu: {
        available: number;
        total: number;
    }

    Type declaration

    • available: number
    • total: number
    last_visit: null | Date
    location: null | string
    loved_beatmapset_count: number
    mapping_follower_count: number
    max_blocks: number
    max_friends: number
    monthly_playcounts: {
        count: number;
        start_date: Date;
    }[]

    Type declaration

    • count: number
    • start_date: Date
    nominated_beatmapset_count: number
    occupation: null | string
    page: {
        html: string;
        raw: string;
    }

    Type declaration

    • html: string
    • raw: string

      Basically the text with the BBCode

      -
    pending_beatmapset_count: number
    playmode: string
    playstyle: string[]
    pm_friends_only: boolean
    post_count: number
    previous_usernames: string[]
    profile_colour: null | string
    profile_order: ("me" | "recent_activity" | "beatmaps" | "historical" | "kudosu" | "top_ranks" | "medals")[]
    rank_highest: null | {
        rank: number;
        updated_at: Date;
    }

    Type declaration

    • rank: number
    • updated_at: Date
    rank_history: {
        data: number[];
        mode: string;
    }

    Type declaration

    • data: number[]
    • mode: string
    replays_watched_counts: {
        count: number;
        start_date: Date;
    }[]

    Type declaration

    • count: number
    • start_date: Date
    scores_best_count: number
    scores_first_count: number
    scores_pinned_count: number

    Specific to the Ruleset (playmode)

    -
    scores_recent_count: number
    statistics_rulesets: {
        fruits: UserStatistics;
        mania: UserStatistics;
        osu: UserStatistics;
        taiko: UserStatistics;
    }

    Type declaration

    support_level: number
    title: null | string
    title_url: null | string
    twitter: null | string
    user_achievements: {
        achieved_at: Date;
        achievement_id: number;
    }[]

    Type declaration

    • achieved_at: Date
    • achievement_id: number
    username: string
    website: null | string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    account_history: {
        description: null | string;
        id: number;
        length: number;
        permanent: boolean;
        timestamp: Date;
        type: "note" | "restriction" | "silence";
    }[]

    Type declaration

    • description: null | string
    • id: number
    • length: number
    • permanent: boolean
    • timestamp: Date
    • type: "note" | "restriction" | "silence"
    active_tournament_banner: null | ProfileBanner
    active_tournament_banners: ProfileBanner[]

    This is not documented by osu!, likely because support for multiple banners has been recently added (OWC2023)

    +
    avatar_url: string
    badges: {
        awarded_at: Date;
        description: string;
        image_url: string;
        url: string;
    }[]

    Type declaration

    • awarded_at: Date
    • description: string
    • image_url: string
    • url: string
    beatmap_playcounts_count: number
    comments_count: number
    country: {
        code: string;
        name: string;
    }

    Type declaration

    • code: string
    • name: string
    country_code: string
    cover: {
        custom_url: null | string;
        id: null | number;
        url: string;
    }

    Type declaration

    • custom_url: null | string
    • id: null | number
    • url: string
    cover_url: string
    default_group: string
    discord: null | string
    favourite_beatmapset_count: number
    follower_count: number
    graveyard_beatmapset_count: number
    groups: {
        colour: null | string;
        has_listing: boolean;
        has_playmodes: boolean;
        id: number;
        identifier: string;
        is_probationary: boolean;
        name: string;
        playmodes: null | string[];
        short_name: string;
    }[]

    Type declaration

    • colour: null | string
    • has_listing: boolean
    • has_playmodes: boolean
    • id: number
    • identifier: string
    • is_probationary: boolean
    • name: string
    • playmodes: null | string[]
    • short_name: string
    guest_beatmapset_count: number
    has_supported: boolean
    id: number
    interests: null | string
    is_active: boolean
    is_bot: boolean
    is_deleted: boolean
    is_online: boolean
    is_supporter: boolean
    join_date: Date
    kudosu: {
        available: number;
        total: number;
    }

    Type declaration

    • available: number
    • total: number
    last_visit: null | Date
    location: null | string
    loved_beatmapset_count: number
    mapping_follower_count: number
    max_blocks: number
    max_friends: number
    monthly_playcounts: {
        count: number;
        start_date: Date;
    }[]

    Type declaration

    • count: number
    • start_date: Date
    nominated_beatmapset_count: number
    occupation: null | string
    page: {
        html: string;
        raw: string;
    }

    Type declaration

    • html: string
    • raw: string

      Basically the text with the BBCode

      +
    pending_beatmapset_count: number
    playmode: string
    playstyle: string[]
    pm_friends_only: boolean
    post_count: number
    previous_usernames: string[]
    profile_colour: null | string
    profile_order: ("me" | "recent_activity" | "beatmaps" | "historical" | "kudosu" | "top_ranks" | "medals")[]
    rank_highest: null | {
        rank: number;
        updated_at: Date;
    }

    Type declaration

    • rank: number
    • updated_at: Date
    rank_history: {
        data: number[];
        mode: string;
    }

    Type declaration

    • data: number[]
    • mode: string
    replays_watched_counts: {
        count: number;
        start_date: Date;
    }[]

    Type declaration

    • count: number
    • start_date: Date
    scores_best_count: number
    scores_first_count: number
    scores_pinned_count: number

    Specific to the Ruleset (playmode)

    +
    scores_recent_count: number
    statistics_rulesets: {
        fruits: UserStatistics;
        mania: UserStatistics;
        osu: UserStatistics;
        taiko: UserStatistics;
    }

    Type declaration

    support_level: number
    title: null | string
    title_url: null | string
    twitter: null | string
    user_achievements: {
        achieved_at: Date;
        achievement_id: number;
    }[]

    Type declaration

    • achieved_at: Date
    • achievement_id: number
    username: string
    website: null | string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/UserStatistics.html b/docs/interfaces/UserStatistics.html index f17f989..6da89c6 100644 --- a/docs/interfaces/UserStatistics.html +++ b/docs/interfaces/UserStatistics.html @@ -1,4 +1,5 @@ -UserStatistics | osu-api-v2-js

    Interface UserStatistics

    Hierarchy

    Properties

    count_100 +UserStatistics | osu-api-v2-js

    Interface UserStatistics

    Expected from UserWithCountryCoverGroupsStatisticsrulesets, UserWithCountryCoverGroupsStatisticsSupport

    +

    Hierarchy

    Properties

    count_100: number
    count_300: number
    count_50: number
    count_miss: number
    global_rank: null | number
    global_rank_exp: null | number
    grade_counts: {
        a: number;
        s: number;
        sh: number;
        ss: number;
        ssh: number;
    }

    Type declaration

    • a: number
    • s: number
    • sh: number
    • ss: number
    • ssh: number
    hit_accuracy: number

    Accuracy in the normal format, where 96.56% would be 96.56

    -
    is_ranked: boolean

    Hasn't went inactive in the rankings

    -
    level: {
        current: number;
        progress: number;
    }

    Type declaration

    • current: number
    • progress: number
    maximum_combo: number
    play_count: number
    play_time: null | number
    pp: null | number
    pp_exp: number
    ranked_score: number
    replays_watched_by_others: number
    total_hits: number
    total_score: number

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    count_100: number
    count_300: number
    count_50: number
    count_miss: number
    global_rank: null | number
    global_rank_exp: null | number
    grade_counts: {
        a: number;
        s: number;
        sh: number;
        ss: number;
        ssh: number;
    }

    Type declaration

    • a: number
    • s: number
    • sh: number
    • ss: number
    • ssh: number
    hit_accuracy: number

    Accuracy in the normal format, where 96.56% would be 96.56

    +
    is_ranked: boolean

    Hasn't went inactive in the rankings

    +
    level: {
        current: number;
        progress: number;
    }

    Type declaration

    • current: number
    • progress: number
    maximum_combo: number
    play_count: number
    play_time: null | number
    pp: null | number
    pp_exp: number
    ranked_score: number
    replays_watched_by_others: number
    total_hits: number
    total_score: number

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/UserStatisticsWithCountryrank.html b/docs/interfaces/UserStatisticsWithCountryrank.html index ad3dd08..6e9ce9f 100644 --- a/docs/interfaces/UserStatisticsWithCountryrank.html +++ b/docs/interfaces/UserStatisticsWithCountryrank.html @@ -1,5 +1,5 @@ UserStatisticsWithCountryrank | osu-api-v2-js

    Interface UserStatisticsWithCountryrank

    Expected from UserExtended

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    count_100: number
    count_300: number
    count_50: number
    count_miss: number
    country_rank: number
    global_rank: null | number
    global_rank_exp: null | number
    grade_counts: {
        a: number;
        s: number;
        sh: number;
        ss: number;
        ssh: number;
    }

    Type declaration

    • a: number
    • s: number
    • sh: number
    • ss: number
    • ssh: number
    hit_accuracy: number

    Accuracy in the normal format, where 96.56% would be 96.56

    -
    is_ranked: boolean

    Hasn't went inactive in the rankings

    -
    level: {
        current: number;
        progress: number;
    }

    Type declaration

    • current: number
    • progress: number
    maximum_combo: number
    play_count: number
    play_time: null | number
    pp: null | number
    pp_exp: number
    ranked_score: number
    replays_watched_by_others: number
    total_hits: number
    total_score: number

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    count_100: number
    count_300: number
    count_50: number
    count_miss: number
    country_rank: number
    global_rank: null | number
    global_rank_exp: null | number
    grade_counts: {
        a: number;
        s: number;
        sh: number;
        ss: number;
        ssh: number;
    }

    Type declaration

    • a: number
    • s: number
    • sh: number
    • ss: number
    • ssh: number
    hit_accuracy: number

    Accuracy in the normal format, where 96.56% would be 96.56

    +
    is_ranked: boolean

    Hasn't went inactive in the rankings

    +
    level: {
        current: number;
        progress: number;
    }

    Type declaration

    • current: number
    • progress: number
    maximum_combo: number
    play_count: number
    play_time: null | number
    pp: null | number
    pp_exp: number
    ranked_score: number
    replays_watched_by_others: number
    total_hits: number
    total_score: number

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/UserStatisticsWithUser.html b/docs/interfaces/UserStatisticsWithUser.html index 2df5331..98d8ad4 100644 --- a/docs/interfaces/UserStatisticsWithUser.html +++ b/docs/interfaces/UserStatisticsWithUser.html @@ -1,5 +1,5 @@ UserStatisticsWithUser | osu-api-v2-js

    Interface UserStatisticsWithUser

    Expected from Rankings

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    count_100: number
    count_300: number
    count_50: number
    count_miss: number
    global_rank: null | number
    global_rank_exp: null | number
    grade_counts: {
        a: number;
        s: number;
        sh: number;
        ss: number;
        ssh: number;
    }

    Type declaration

    • a: number
    • s: number
    • sh: number
    • ss: number
    • ssh: number
    hit_accuracy: number

    Accuracy in the normal format, where 96.56% would be 96.56

    -
    is_ranked: boolean

    Hasn't went inactive in the rankings

    -
    level: {
        current: number;
        progress: number;
    }

    Type declaration

    • current: number
    • progress: number
    maximum_combo: number
    play_count: number
    play_time: null | number
    pp: null | number
    pp_exp: number
    ranked_score: number
    replays_watched_by_others: number
    total_hits: number
    total_score: number

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    count_100: number
    count_300: number
    count_50: number
    count_miss: number
    global_rank: null | number
    global_rank_exp: null | number
    grade_counts: {
        a: number;
        s: number;
        sh: number;
        ss: number;
        ssh: number;
    }

    Type declaration

    • a: number
    • s: number
    • sh: number
    • ss: number
    • ssh: number
    hit_accuracy: number

    Accuracy in the normal format, where 96.56% would be 96.56

    +
    is_ranked: boolean

    Hasn't went inactive in the rankings

    +
    level: {
        current: number;
        progress: number;
    }

    Type declaration

    • current: number
    • progress: number
    maximum_combo: number
    play_count: number
    play_time: null | number
    pp: null | number
    pp_exp: number
    ranked_score: number
    replays_watched_by_others: number
    total_hits: number
    total_score: number

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/UserWithCountry.html b/docs/interfaces/UserWithCountry.html index 384d17f..49f780b 100644 --- a/docs/interfaces/UserWithCountry.html +++ b/docs/interfaces/UserWithCountry.html @@ -1,5 +1,5 @@ UserWithCountry | osu-api-v2-js

    Interface UserWithCountry

    Expected from api.getMatch(), Leader

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    avatar_url: string
    country: {
        code: string;
        name: string;
    }

    Type declaration

    • code: string
    • name: string
    country_code: string
    default_group: string
    id: number
    is_active: boolean
    is_bot: boolean
    is_deleted: boolean
    is_online: boolean
    is_supporter: boolean
    last_visit: null | Date
    pm_friends_only: boolean
    profile_colour: null | string
    username: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    avatar_url: string
    country: {
        code: string;
        name: string;
    }

    Type declaration

    • code: string
    • name: string
    country_code: string
    default_group: string
    id: number
    is_active: boolean
    is_bot: boolean
    is_deleted: boolean
    is_online: boolean
    is_supporter: boolean
    last_visit: null | Date
    pm_friends_only: boolean
    profile_colour: null | string
    username: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/UserWithCountryCover.html b/docs/interfaces/UserWithCountryCover.html index 4746ea5..9401438 100644 --- a/docs/interfaces/UserWithCountryCover.html +++ b/docs/interfaces/UserWithCountryCover.html @@ -1,5 +1,5 @@ UserWithCountryCover | osu-api-v2-js

    Interface UserWithCountryCover

    Expected from UserStatisticsWithUser, MultiplayerScore, ScoreWithUser

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    avatar_url: string
    country: {
        code: string;
        name: string;
    }

    Type declaration

    • code: string
    • name: string
    country_code: string
    cover: {
        custom_url: null | string;
        id: null | number;
        url: string;
    }

    Type declaration

    • custom_url: null | string
    • id: null | number
    • url: string
    default_group: string
    id: number
    is_active: boolean
    is_bot: boolean
    is_deleted: boolean
    is_online: boolean
    is_supporter: boolean
    last_visit: null | Date
    pm_friends_only: boolean
    profile_colour: null | string
    username: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    avatar_url: string
    country: {
        code: string;
        name: string;
    }

    Type declaration

    • code: string
    • name: string
    country_code: string
    cover: {
        custom_url: null | string;
        id: null | number;
        url: string;
    }

    Type declaration

    • custom_url: null | string
    • id: null | number
    • url: string
    default_group: string
    id: number
    is_active: boolean
    is_bot: boolean
    is_deleted: boolean
    is_online: boolean
    is_supporter: boolean
    last_visit: null | Date
    pm_friends_only: boolean
    profile_colour: null | string
    username: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/UserWithCountryCoverGroupsStatisticsSupport.html b/docs/interfaces/UserWithCountryCoverGroupsStatisticsSupport.html index bebc89e..36c05b0 100644 --- a/docs/interfaces/UserWithCountryCoverGroupsStatisticsSupport.html +++ b/docs/interfaces/UserWithCountryCoverGroupsStatisticsSupport.html @@ -1,5 +1,5 @@ UserWithCountryCoverGroupsStatisticsSupport | osu-api-v2-js

    Interface UserWithCountryCoverGroupsStatisticsSupport

    Expected from api.getFriends()

    -

    Hierarchy

    • UserWithCountryCoverGroups

    Properties

    Hierarchy

    • UserWithCountryCoverGroups

    Properties

    avatar_url: string
    country: {
        code: string;
        name: string;
    }

    Type declaration

    • code: string
    • name: string
    country_code: string
    cover: {
        custom_url: null | string;
        id: null | number;
        url: string;
    }

    Type declaration

    • custom_url: null | string
    • id: null | number
    • url: string
    default_group: string
    groups: {
        colour: null | string;
        has_listing: boolean;
        has_playmodes: boolean;
        id: number;
        identifier: string;
        is_probationary: boolean;
        name: string;
        playmodes: null | string[];
        short_name: string;
    }[]

    Type declaration

    • colour: null | string
    • has_listing: boolean
    • has_playmodes: boolean
    • id: number
    • identifier: string
    • is_probationary: boolean
    • name: string
    • playmodes: null | string[]
    • short_name: string
    id: number
    is_active: boolean
    is_bot: boolean
    is_deleted: boolean
    is_online: boolean
    is_supporter: boolean
    last_visit: null | Date
    pm_friends_only: boolean
    profile_colour: null | string
    statistics: UserStatistics
    support_level: number
    username: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    avatar_url: string
    country: {
        code: string;
        name: string;
    }

    Type declaration

    • code: string
    • name: string
    country_code: string
    cover: {
        custom_url: null | string;
        id: null | number;
        url: string;
    }

    Type declaration

    • custom_url: null | string
    • id: null | number
    • url: string
    default_group: string
    groups: {
        colour: null | string;
        has_listing: boolean;
        has_playmodes: boolean;
        id: number;
        identifier: string;
        is_probationary: boolean;
        name: string;
        playmodes: null | string[];
        short_name: string;
    }[]

    Type declaration

    • colour: null | string
    • has_listing: boolean
    • has_playmodes: boolean
    • id: number
    • identifier: string
    • is_probationary: boolean
    • name: string
    • playmodes: null | string[]
    • short_name: string
    id: number
    is_active: boolean
    is_bot: boolean
    is_deleted: boolean
    is_online: boolean
    is_supporter: boolean
    last_visit: null | Date
    pm_friends_only: boolean
    profile_colour: null | string
    statistics: UserStatistics
    support_level: number
    username: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/UserWithCountryCoverGroupsStatisticsrulesets.html b/docs/interfaces/UserWithCountryCoverGroupsStatisticsrulesets.html index be64c69..22f8a5e 100644 --- a/docs/interfaces/UserWithCountryCoverGroupsStatisticsrulesets.html +++ b/docs/interfaces/UserWithCountryCoverGroupsStatisticsrulesets.html @@ -1,5 +1,5 @@ UserWithCountryCoverGroupsStatisticsrulesets | osu-api-v2-js

    Interface UserWithCountryCoverGroupsStatisticsrulesets

    Expected from api.getUsers()

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    avatar_url: string
    country: {
        code: string;
        name: string;
    }

    Type declaration

    • code: string
    • name: string
    country_code: string
    cover: {
        custom_url: null | string;
        id: null | number;
        url: string;
    }

    Type declaration

    • custom_url: null | string
    • id: null | number
    • url: string
    default_group: string
    groups: {
        colour: null | string;
        has_listing: boolean;
        has_playmodes: boolean;
        id: number;
        identifier: string;
        is_probationary: boolean;
        name: string;
        playmodes: null | string[];
        short_name: string;
    }[]

    Type declaration

    • colour: null | string
    • has_listing: boolean
    • has_playmodes: boolean
    • id: number
    • identifier: string
    • is_probationary: boolean
    • name: string
    • playmodes: null | string[]
    • short_name: string
    id: number
    is_active: boolean
    is_bot: boolean
    is_deleted: boolean
    is_online: boolean
    is_supporter: boolean
    last_visit: null | Date
    pm_friends_only: boolean
    profile_colour: null | string
    statistics_rulesets: {
        fruits: UserStatistics;
        mania: UserStatistics;
        osu: UserStatistics;
        taiko: UserStatistics;
    }

    Type declaration

    username: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    avatar_url: string
    country: {
        code: string;
        name: string;
    }

    Type declaration

    • code: string
    • name: string
    country_code: string
    cover: {
        custom_url: null | string;
        id: null | number;
        url: string;
    }

    Type declaration

    • custom_url: null | string
    • id: null | number
    • url: string
    default_group: string
    groups: {
        colour: null | string;
        has_listing: boolean;
        has_playmodes: boolean;
        id: number;
        identifier: string;
        is_probationary: boolean;
        name: string;
        playmodes: null | string[];
        short_name: string;
    }[]

    Type declaration

    • colour: null | string
    • has_listing: boolean
    • has_playmodes: boolean
    • id: number
    • identifier: string
    • is_probationary: boolean
    • name: string
    • playmodes: null | string[]
    • short_name: string
    id: number
    is_active: boolean
    is_bot: boolean
    is_deleted: boolean
    is_online: boolean
    is_supporter: boolean
    last_visit: null | Date
    pm_friends_only: boolean
    profile_colour: null | string
    statistics_rulesets: {
        fruits: UserStatistics;
        mania: UserStatistics;
        osu: UserStatistics;
        taiko: UserStatistics;
    }

    Type declaration

    username: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/UserWithKudosu.html b/docs/interfaces/UserWithKudosu.html index fb9e0f0..18dcf52 100644 --- a/docs/interfaces/UserWithKudosu.html +++ b/docs/interfaces/UserWithKudosu.html @@ -1,5 +1,5 @@ UserWithKudosu | osu-api-v2-js

    Interface UserWithKudosu

    Expected from api.getKudosuRanking()

    -

    Hierarchy

    Properties

    Hierarchy

    Properties

    avatar_url: string
    country_code: string
    default_group: string
    id: number
    is_active: boolean
    is_bot: boolean
    is_deleted: boolean
    is_online: boolean
    is_supporter: boolean
    kudosu: {
        available: number;
        total: number;
    }

    Type declaration

    • available: number
    • total: number
    last_visit: null | Date
    pm_friends_only: boolean
    profile_colour: null | string
    username: string

    Generated using TypeDoc

    \ No newline at end of file +

    Properties

    avatar_url: string
    country_code: string
    default_group: string
    id: number
    is_active: boolean
    is_bot: boolean
    is_deleted: boolean
    is_online: boolean
    is_supporter: boolean
    kudosu: {
        available: number;
        total: number;
    }

    Type declaration

    • available: number
    • total: number
    last_visit: null | Date
    pm_friends_only: boolean
    profile_colour: null | string
    username: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/interfaces/WikiPage.html b/docs/interfaces/WikiPage.html new file mode 100644 index 0000000..7957357 --- /dev/null +++ b/docs/interfaces/WikiPage.html @@ -0,0 +1,14 @@ +WikiPage | osu-api-v2-js

    Interface WikiPage

    Expected from api.getWikiPage(), SearchResultWiki

    +

    Hierarchy

    • WikiPage

    Properties

    available_locales: string[]
    layout: string
    locale: string

    BCP 47 language (sub)tag, lowercase (for example, en for english)

    +
    markdown: string
    path: string

    It's what should be after https://osu.ppy.sh/wiki/{locale}/

    +
    subtitle: null | string

    Think of it as the title of the parent wiki page

    +

    Remarks

    If the title in the path (assuming it's in it (very unlikely if locale is not en)) is after a slash (/), this is what is before the slash

    +
    tags: string[]
    title: string

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/modules.html b/docs/modules.html index f34f503..3d38643 100644 --- a/docs/modules.html +++ b/docs/modules.html @@ -12,15 +12,34 @@ BeatmapExtendedWithFailtimes BeatmapExtendedWithFailtimesBeatmapsetextended BeatmapPack +BeatmapPlaycount BeatmapUserScore BeatmapWithBeatmapset BeatmapWithBeatmapsetChecksumMaxcombo Beatmapset BeatmapsetExtended BeatmapsetExtendedPlus +BeatmapsetExtendedWithBeatmapExtended ChangelogBuildWithChangelogentriesVersions ChangelogBuildWithUpdatestreams ChangelogBuildWithUpdatestreamsChangelogentries +Event +EventAchievement +EventBeatmap +EventBeatmapPlaycount +EventBeatmapset +EventBeatmapsetApprove +EventBeatmapsetDelete +EventBeatmapsetRevive +EventBeatmapsetUpdate +EventBeatmapsetUpload +EventRank +EventRankLost +EventUser +EventUserSupportAgain +EventUserSupportFirst +EventUserSupportGift +EventUsernameChange KudosuHistory Leader Match @@ -37,6 +56,8 @@ ScoreWithUser ScoreWithUserBeatmap ScoreWithUserBeatmapBeatmapset +SearchResultUser +SearchResultWiki Spotlight SpotlightWithParticipantcount UpdateStream @@ -51,8 +72,9 @@ UserWithCountryCoverGroupsStatisticsSupport UserWithCountryCoverGroupsStatisticsrulesets UserWithKudosu +WikiPage

    Type Aliases

    Functions

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/types/Mod.html b/docs/types/Mod.html index d59e6a1..dcef2a1 100644 --- a/docs/types/Mod.html +++ b/docs/types/Mod.html @@ -1 +1 @@ -Mod | osu-api-v2-js

    Generated using TypeDoc

    \ No newline at end of file +Mod | osu-api-v2-js

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/types/ProfileBanner.html b/docs/types/ProfileBanner.html index e26949a..ec26aa0 100644 --- a/docs/types/ProfileBanner.html +++ b/docs/types/ProfileBanner.html @@ -1,2 +1,2 @@ ProfileBanner | osu-api-v2-js

    Generated using TypeDoc

    \ No newline at end of file +

    Type declaration

    • id: number
    • image: string
    • tournament_id: number

    Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/types/Scope.html b/docs/types/Scope.html index 5e06a06..4c364c3 100644 --- a/docs/types/Scope.html +++ b/docs/types/Scope.html @@ -1,3 +1,3 @@ Scope | osu-api-v2-js

    Type alias Scope

    Scope: "chat.read" | "chat.write" | "chat.write_manage" | "delegate" | "forum.write" | "friends.read" | "identify" | "public"

    Scopes determine what the API instance can do as a user!

    Remarks

    "identify" is always implicity provided, "public" is implicitly needed for almost everything

    -

    Generated using TypeDoc

    \ No newline at end of file +

    Generated using TypeDoc

    \ No newline at end of file diff --git a/lib/beatmap.ts b/lib/beatmap.ts index db25169..bea5356 100644 --- a/lib/beatmap.ts +++ b/lib/beatmap.ts @@ -233,7 +233,7 @@ export interface BeatmapPlaycount { } /** - * @privateRemarks While not expected from anywhere, it should be exported for ease of use purposes + * Expected from api.getBeatmapDifficultyAttributes() */ export interface BeatmapDifficultyAttributes { star_rating: number diff --git a/lib/index.ts b/lib/index.ts index dffd88d..9f28f17 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -6,7 +6,8 @@ import { User, UserWithKudosu, UserWithCountry, UserWithCountryCover, UserWithCo UserStatistics, UserStatisticsWithUser, UserStatisticsWithCountryrank, KudosuHistory, ProfileBanner } from "./user.js" import { Beatmap, BeatmapExtendedWithFailtimesBeatmapsetextended, BeatmapWithBeatmapset, BeatmapWithBeatmapsetChecksumMaxcombo, BeatmapExtended, BeatmapPlaycount, BeatmapDifficultyAttributes, BeatmapDifficultyAttributesOsu, BeatmapDifficultyAttributesTaiko, BeatmapDifficultyAttributesFruits, BeatmapDifficultyAttributesMania, - Beatmapset, BeatmapsetExtended, BeatmapExtendedWithFailtimes, BeatmapsetExtendedPlus, BeatmapPack, RankStatus, BeatmapsetExtendedWithBeatmapExtended } from "./beatmap.js" + Beatmapset, BeatmapsetExtended, BeatmapExtendedWithFailtimes, BeatmapsetExtendedWithBeatmapExtended, BeatmapsetExtendedPlus, BeatmapPack, RankStatus } + from "./beatmap.js" import { Room, Leader, PlaylistItem, MultiplayerScore, MultiplayerScores, Match, MatchInfo } from "./multiplayer.js" import { Score, ScoreWithMatch, ScoreWithUser, ScoreWithUserBeatmap, ScoreWithUserBeatmapBeatmapset, BeatmapUserScore } from "./score.js" @@ -26,7 +27,8 @@ export { User, UserWithKudosu, UserWithCountry, UserWithCountryCover, UserWithCo UserStatistics, UserStatisticsWithUser, UserStatisticsWithCountryrank, KudosuHistory, ProfileBanner } from "./user.js" export { Beatmap, BeatmapExtendedWithFailtimesBeatmapsetextended, BeatmapWithBeatmapset, BeatmapWithBeatmapsetChecksumMaxcombo, BeatmapExtended, BeatmapPlaycount, BeatmapDifficultyAttributes, BeatmapDifficultyAttributesOsu, BeatmapDifficultyAttributesTaiko, BeatmapDifficultyAttributesFruits, BeatmapDifficultyAttributesMania, - Beatmapset, BeatmapsetExtended, BeatmapExtendedWithFailtimes, BeatmapsetExtendedPlus, BeatmapPack, RankStatus } from "./beatmap.js" + Beatmapset, BeatmapsetExtended, BeatmapExtendedWithFailtimes, BeatmapsetExtendedWithBeatmapExtended, BeatmapsetExtendedPlus, BeatmapPack, RankStatus } + from "./beatmap.js" export { Room, Leader, PlaylistItem, MultiplayerScore, MultiplayerScores, Match, MatchInfo } from "./multiplayer.js" export { Score, ScoreWithMatch, ScoreWithUser, ScoreWithUserBeatmap, ScoreWithUserBeatmapBeatmapset, BeatmapUserScore } from "./score.js" @@ -41,6 +43,33 @@ export { WikiPage } from "./wiki.js" export { SearchResultUser, SearchResultWiki } from "./home.js" export { Rulesets, Mod, Scope } from "./misc.js" +/** + * Some stuff doesn't have the right type to begin with, such as dates, which are being returned as strings, this fixes that + * @param x Anything, but should be a string, an array that contains a string, or an object which has a string + * @returns x, but with it (or what it contains) now having the correct type + */ +function correctType(x: any): any { + if (typeof x === "boolean") { + return x + } else if (/^[+-[0-9][0-9]+-[0-9]{2}-[0-9]{2}/.test(x)) { + if (/[0-9]{2}:[0-9]{2}:[0-9]{2}$/.test(x)) x += "Z" + if (/[0-9]{2}:[0-9]{2}:[0-9]{2}\+[0-9]{2}:[0-9]{2}$/.test(x)) x = x.substring(0, x.indexOf("+")) + "Z" + return new Date(x) + } else if (Array.isArray(x)) { + return x.map((e) => correctType(e)) + } else if (!isNaN(x) && x !== "") { + return x === null ? null : Number(x) + } else if (typeof x === "object" && x !== null) { + const k = Object.keys(x) + const v = Object.values(x) + for (let i = 0; i < k.length; i++) { + if (typeof v[i] === "string" && (k[i].includes("name") || k[i].includes("version"))) continue // don't turn names made of numbers into integers + x[k[i]] = correctType(v[i]) + } + } + return x +} + /** * Generates a link for users to click on in order to use your application! @@ -292,14 +321,14 @@ export class API { this.log(true, "Will request again in a few instants...", `(Try #${number_try})`) const to_wait = (Math.floor(Math.random() * (500 - 100 + 1)) + 100) * 10 await new Promise(res => setTimeout(res, to_wait)) - return await this.request(method, endpoint, parameters, number_try + 1) + return correctType(await this.request(method, endpoint, parameters, number_try + 1)) } throw new APIError(err, `${this.server}/api/v2`, endpoint, JSON.stringify(parameters)) } this.log(false, response.statusText, response.status, {endpoint, parameters}) - return response.json() + return correctType(await response.json()) } @@ -311,8 +340,7 @@ export class API { * @scope identify */ async getResourceOwner(ruleset?: Rulesets): Promise { - const response = await this.request("get", "me", {mode: ruleset}) - return correctType(response) as UserExtendedWithStatisticsrulesets + return await this.request("get", "me", {mode: ruleset}) } /** @@ -323,10 +351,9 @@ export class API { async getUser(user: {id?: number, username?: string} | User, ruleset?: Rulesets): Promise { const key = user.id !== undefined ? "id" : "username" const lookup = user.id !== undefined ? user.id : user.username - const mode = ruleset ? `/${Rulesets[ruleset]}` : "" + const mode = ruleset !== undefined ? `/${Rulesets[ruleset]}` : "" - const response = await this.request("get", `users/${lookup}${mode}`, {key}) - return correctType(response) + return await this.request("get", `users/${lookup}${mode}`, {key}) } /** @@ -335,7 +362,7 @@ export class API { */ async getUsers(ids: number[]): Promise { const response = await this.request("get", "users", {ids}) - return correctType(response.users) + return response.users } /** @@ -349,9 +376,8 @@ export class API { */ async getUserScores(user: {id: number} | User, type: "best" | "firsts" | "recent", limit?: number, ruleset?: Rulesets, include_fails: boolean = false, offset?: number): Promise { - const mode = ruleset ? Rulesets[ruleset] : undefined - const response = await this.request("get", `users/${user.id}/scores/${type}`, {mode, limit, offset, include_fails: String(Number(include_fails))}) - return correctType(response) + const mode = ruleset !== undefined ? Rulesets[ruleset] : undefined + return await this.request("get", `users/${user.id}/scores/${type}`, {mode, limit, offset, include_fails: String(Number(include_fails))}) } /** @@ -363,8 +389,7 @@ export class API { */ async getUserBeatmaps(user: {id: number} | User, type: "favourite" | "graveyard" | "guest" | "loved" | "nominated" | "pending" | "ranked", limit: number = 5, offset?: number): Promise { - const response = await this.request("get", `users/${user.id}/beatmapsets/${type}`, {limit, offset}) - return correctType(response) + return await this.request("get", `users/${user.id}/beatmapsets/${type}`, {limit, offset}) } /** @@ -374,8 +399,7 @@ export class API { * @param offset How many elements that would be at the top of the returned array get skipped (while still filling the array up to the limit) */ async getUserMostPlayed(user: {id: number} | User, limit: number = 5, offset?: number): Promise { - const response = await this.request("get", `users/${user.id}/beatmapsets/most_played`, {limit, offset}) - return correctType(response) + return await this.request("get", `users/${user.id}/beatmapsets/most_played`, {limit, offset}) } /** @@ -387,8 +411,7 @@ export class API { async getUserRecentActivity(user: {id: number} | User, limit: number = 5, offset?: number): Promise> { - const response = await this.request("get", `users/${user.id}/recent_activity`, {limit, offset}) - return correctType(response) + return await this.request("get", `users/${user.id}/recent_activity`, {limit, offset}) } /** @@ -398,8 +421,7 @@ export class API { * @param offset How many elements that would be at the top of the returned array get skipped (while still filling the array up to the limit) */ async getUserKudosu(user: {id: number} | User, limit?: number, offset?: number): Promise { - const response = await this.request("get", `users/${user.id}/kudosu`, {limit, offset}) - return correctType(response) + return await this.request("get", `users/${user.id}/kudosu`, {limit, offset}) } /** @@ -407,8 +429,7 @@ export class API { * @scope friends.read */ async getFriends(): Promise { - const response = await this.request("get", "friends") - return correctType(response) + return await this.request("get", "friends") } @@ -419,8 +440,7 @@ export class API { * @param beatmap An object with the id of the beatmap you're trying to get */ async getBeatmap(beatmap: {id: number} | Beatmap): Promise { - const response = await this.request("get", `beatmaps/${beatmap.id}`) - return correctType(response) + return await this.request("get", `beatmaps/${beatmap.id}`) } /** @@ -429,48 +449,53 @@ export class API { */ async getBeatmaps(ids?: number[]): Promise { const response = await this.request("get", "beatmaps", {ids}) - return correctType(response.beatmaps) + return response.beatmaps } - private async getBeatmapDifficultyAttributes(id: number, mods?: Mod[] | string[] | number, ruleset?: Rulesets): Promise { - const response = await this.request("post", `beatmaps/${id}/attributes`, {ruleset_id: ruleset, mods}) - return correctType(response.attributes) - } /** * Get various data about the difficulty of a beatmap! - * @remarks Will ignore the customization of your mods + * @remarks You may want to use getBeatmapDifficultyAttributesOsu (or Taiko or whatever) instead for better type safety + * @param beatmap The Beatmap in question + * @param mods (defaults to No Mod) (will ignore mod settings) Can be a bitset of mods, an array of mod acronyms ("DT" for DoubleTime), or an array of Mods + * @param ruleset (defaults to the ruleset the beatmap was intended for) Useful to specify if the beatmap is a convert + */ + async getBeatmapDifficultyAttributes(beatmap: {id: number} | Beatmap, mods?: Mod[] | string[] | number, ruleset?: Rulesets): + Promise { + const response = await this.request("post", `beatmaps/${beatmap.id}/attributes`, {ruleset_id: ruleset, mods}) + return response.attributes + } + /** + * Get various data about the difficulty of an osu! beatmap! * @param beatmap The Beatmap in question - * @param mods Defaults to No Mod, can be a bitset of mods, an array of mod acronyms ("DT" for DoubleTime), or an array of Mods + * @param mods (defaults to No Mod) (will ignore mod settings) Can be a bitset of mods, an array of mod acronyms ("DT" for DoubleTime), or an array of Mods */ async getBeatmapDifficultyAttributesOsu(beatmap: {id: number} | Beatmap, mods?: Mod[] | string[] | number): Promise { - return await this.getBeatmapDifficultyAttributes(beatmap.id, mods, Rulesets.osu) as BeatmapDifficultyAttributesOsu + return await this.getBeatmapDifficultyAttributes(beatmap, mods, Rulesets.osu) as BeatmapDifficultyAttributesOsu } /** - * Get various data about the difficulty of a beatmap! - * @remarks Will ignore the customization of your mods + * Get various data about the difficulty of a taiko beatmap! * @param beatmap The Beatmap in question - * @param mods Defaults to No Mod, can be a bitset of mods, an array of mod acronyms ("DT" for DoubleTime), or an array of Mods + * @param mods (defaults to No Mod) (will ignore mod settings) Can be a bitset of mods, an array of mod acronyms ("DT" for DoubleTime), or an array of Mods */ async getBeatmapDifficultyAttributesTaiko(beatmap: {id: number} | Beatmap, mods?: Mod[] | string[] | number): Promise { - return await this.getBeatmapDifficultyAttributes(beatmap.id, mods, Rulesets.taiko) as BeatmapDifficultyAttributesTaiko + return await this.getBeatmapDifficultyAttributes(beatmap, mods, Rulesets.taiko) as BeatmapDifficultyAttributesTaiko } /** - * Get various data about the difficulty of a beatmap! - * @remarks Will ignore the customization of your mods + * Get various data about the difficulty of a ctb beatmap! * @param beatmap The Beatmap in question - * @param mods Defaults to No Mod, can be a bitset of mods, an array of mod acronyms ("DT" for DoubleTime), or an array of Mods + * @param mods (defaults to No Mod) (will ignore mod settings) Can be a bitset of mods, an array of mod acronyms ("DT" for DoubleTime), or an array of Mods */ async getBeatmapDifficultyAttributesFruits(beatmap: {id: number} | Beatmap, mods?: Mod[] | string[] | number): Promise { - return await this.getBeatmapDifficultyAttributes(beatmap.id, mods, Rulesets.fruits) as BeatmapDifficultyAttributesFruits + return await this.getBeatmapDifficultyAttributes(beatmap, mods, Rulesets.fruits) as BeatmapDifficultyAttributesFruits } /** - * Get various data about the difficulty of a beatmap! - * @remarks Will ignore the customization of your mods + * Get various data about the difficulty of a mania beatmap! * @param beatmap The Beatmap in question - * @param mods Defaults to No Mod, can be a bitset of mods, an array of mod acronyms ("DT" for DoubleTime), or an array of Mods + * @param mods (defaults to No Mod) (will ignore mod settings) Can be a bitset of mods, an array of mod acronyms ("DT" for DoubleTime), or an array of Mods */ async getBeatmapDifficultyAttributesMania(beatmap: {id: number} | Beatmap, mods?: Mod[] | string[] | number): Promise { - return await this.getBeatmapDifficultyAttributes(beatmap.id, mods, Rulesets.mania) as BeatmapDifficultyAttributesMania + return await this.getBeatmapDifficultyAttributes(beatmap, mods, Rulesets.mania) as BeatmapDifficultyAttributesMania } /** @@ -481,9 +506,9 @@ export class API { * @param type (2023-11-16) Currently doesn't do anything */ async getBeatmapScores(beatmap: {id: number} | Beatmap, ruleset?: Rulesets, mods?: string[], type?: string): Promise { - const mode = ruleset ? Rulesets[ruleset] : undefined + const mode = ruleset !== undefined ? Rulesets[ruleset] : undefined const response = await this.request("get", `beatmaps/${beatmap.id}/scores`, {mode, mods, type}) - return correctType(response.scores) + return response.scores } /** @@ -496,9 +521,8 @@ export class API { */ async getBeatmapUserScore(beatmap: {id: number} | Beatmap, user: {id: number} | User, mods?: string[], ruleset?: Rulesets): Promise { - const mode = ruleset ? Rulesets[ruleset] : undefined - const response = await this.request("get", `beatmaps/${beatmap.id}/scores/users/${user.id}`, {mods, mode}) - return correctType(response) + const mode = ruleset !== undefined ? Rulesets[ruleset] : undefined + return await this.request("get", `beatmaps/${beatmap.id}/scores/users/${user.id}`, {mods, mode}) } /** @@ -508,9 +532,9 @@ export class API { * @param ruleset The Ruleset used to make the scores, defaults to the Ruleset the Beatmap was made for */ async getBeatmapUserScores(beatmap: {id: number} | Beatmap, user: {id: number} | User, ruleset?: Rulesets): Promise { - const mode = ruleset ? Rulesets[ruleset] : undefined + const mode = ruleset !== undefined ? Rulesets[ruleset] : undefined const response = await this.request("get", `beatmaps/${beatmap.id}/scores/users/${user.id}/all`, {mode}) - return correctType(response.scores) + return response.scores } /** @@ -518,8 +542,7 @@ export class API { * @param beatmapset An object with the id of the beatmapset you're trying to get */ async getBeatmapset(beatmapset: {id: number} | Beatmapset): Promise { - const response = await this.request("get", `beatmapsets/${beatmapset.id}`) - return correctType(response) + return await this.request("get", `beatmapsets/${beatmapset.id}`) } /** @@ -528,8 +551,7 @@ export class API { * @remarks Currently in https://osu.ppy.sh/beatmaps/packs, when hovering a pack, its link with its tag should show up on your browser's bottom left */ async getBeatmapPack(pack: {tag: string} | BeatmapPack): Promise { - const response = await this.request("get", `beatmaps/packs/${pack.tag}`) - return correctType(response) + return await this.request("get", `beatmaps/packs/${pack.tag}`) } /** @@ -538,7 +560,7 @@ export class API { */ async getBeatmapPacks(type: "standard" | "featured" | "tournament" | "loved" | "chart" | "theme" | "artist" = "standard"): Promise { const response = await this.request("get", "beatmaps/packs", {type}) - return correctType(response.beatmap_packs) + return response.beatmap_packs } @@ -550,8 +572,7 @@ export class API { * @param build The name of the version! Usually something like `2023.1026.0` for lazer, or `20230326` for stable */ async getChangelogBuild(stream: string, build: string): Promise { - const response = await this.request("get", `changelog/${stream}/${build}`) - return correctType(response) + return await this.request("get", `changelog/${stream}/${build}`) } /** @@ -565,7 +586,7 @@ export class API { stream?: string, message_formats: ("html" | "markdown")[] = ["html", "markdown"]): Promise { const [from, to] = [versions?.from, versions?.to] const response = await this.request("get", "changelog", {from, to, max_id, stream, message_formats}) - return correctType(response.builds) + return response.builds } /** @@ -576,7 +597,7 @@ export class API { */ async getChangelogStreams(): Promise { const response = await this.request("get", "changelog", {max_id: 0}) - return correctType(response.streams) + return response.streams } @@ -587,8 +608,7 @@ export class API { * @param room An object with the id of the room, is at the end of its URL (after `/multiplayer/rooms/`) */ async getRoom(room: {id: number} | Room): Promise { - const response = await this.request("get", `rooms/${room.id}`) - return correctType(response) + return await this.request("get", `rooms/${room.id}`) } /** @@ -597,8 +617,7 @@ export class API { * @scope public */ async getRooms(mode: "active" | "all" | "ended" | "participated" | "owned" = "active"): Promise { - const response = await this.request("get", "rooms", {mode}) - return correctType(response) + return await this.request("get", "rooms", {mode}) } /** @@ -608,7 +627,7 @@ export class API { */ async getRoomLeaderboard(room: {id: number} | Room): Promise { const response = await this.request("get", `rooms/${room.id}/leaderboard`) - return correctType(response.leaderboard) + return response.leaderboard } /** @@ -622,8 +641,7 @@ export class API { */ async getPlaylistItemScores(item: {id: number, room_id: number} | PlaylistItem, limit: number = 50, sort: "score_asc" | "score_desc" = "score_desc", cursor_string?: string): Promise { - const response = await this.request("get", `rooms/${item.room_id}/playlist/${item.id}/scores`, {limit, sort, cursor_string}) - return correctType(response) + return await this.request("get", `rooms/${item.room_id}/playlist/${item.id}/scores`, {limit, sort, cursor_string}) } /** @@ -638,7 +656,7 @@ export class API { response.events[i].game!.scores[e].perfect = Boolean(response.events[i].game!.scores[e].perfect) } } - return correctType(response) + return response } /** @@ -646,7 +664,7 @@ export class API { */ async getMatches(): Promise { const response = await this.request("get", "matches") - return correctType(response.matches) + return response.matches } @@ -657,7 +675,7 @@ export class API { */ async getKudosuRanking(): Promise { const response = await this.request("get", "rankings/kudosu") - return correctType(response.ranking) + return response.ranking } /** @@ -671,8 +689,7 @@ export class API { */ async getRanking(ruleset: Rulesets, type: "performance" | "score", page: number = 1, filter: "all" | "friends" = "all", country?: string, variant?: "4k" | "7k"): Promise { - const response = await this.request("get", `rankings/${Rulesets[ruleset]}/${type}`, {page, filter, country, variant}) - return correctType(response) + return await this.request("get", `rankings/${Rulesets[ruleset]}/${type}`, {page, filter, country, variant}) } /** @@ -681,8 +698,7 @@ export class API { * @param page (defaults to 1) Imagine `Rankings` as a page, it can only have a maximum of 50 countries, while 50 others may be on the next one */ async getCountryRanking(ruleset: Rulesets, page: number = 1): Promise { - const response = await this.request("get", `rankings/${Rulesets[ruleset]}/country`, {page}) - return correctType(response) + return await this.request("get", `rankings/${Rulesets[ruleset]}/country`, {page}) } /** @@ -692,8 +708,7 @@ export class API { * @param filter What kind of players do you want to see? Defaults to `all`, `friends` has no effect if no authorized user */ async getSpotlightRanking(ruleset: Rulesets, spotlight: {id: number} | Spotlight, filter: "all" | "friends" = "all"): Promise { - const response = await this.request("get", `rankings/${Rulesets[ruleset]}/charts`, {spotlight: spotlight.id, filter}) - return correctType(response) + return await this.request("get", `rankings/${Rulesets[ruleset]}/charts`, {spotlight: spotlight.id, filter}) } /** @@ -703,7 +718,7 @@ export class API { */ async getSpotlights(): Promise { const response = await this.request("get", "spotlights") - return correctType(response.spotlights) + return response.spotlights } @@ -716,7 +731,7 @@ export class API { */ async searchUser(query: string, page: number = 1): Promise { const response = await this.request("get", "search", {mode: "user", query, page}) - return correctType(response.user) + return response.user } /** @@ -726,7 +741,7 @@ export class API { */ async searchWiki(query: string, page: number = 1): Promise { const response = await this.request("get", "search", {mode: "wiki_page", query, page}) - return correctType(response.wiki_page) + return response.wiki_page } /** @@ -736,39 +751,6 @@ export class API { * @param locale (defaults to "en") The BCP 47 language (sub)tag, lowercase (for example, for the article in french, use "fr") */ async getWikiPage(path: string, locale: string = "en"): Promise { - const response = await this.request("get", `wiki/${locale}/${path}`) - return correctType(response) + return await this.request("get", `wiki/${locale}/${path}`) } } - -/** - * Some stuff doesn't have the right type to begin with, such as dates, which are being returned as strings, this fixes that - * @param x Anything, but should be a string, an array that contains a string, or an object which has a string - * @returns x, but with it (or what it contains) now having the correct type - */ -function correctType(x: any): any { - if (typeof x === "boolean") { - return x - } else if (/^[+-[0-9][0-9]+-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$/.test(x) || - /^[+-[0-9][0-9]+-[0-9]{2}-[0-9]{2}$/g.test(x) || /^[+-[0-9][0-9]+-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{0,}Z$/g.test(x)) { - return new Date(x) - } else if (/^[+-[0-9][0-9]+-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$/.test(x)) { - x += "Z" - return new Date(x) - } else if (/^[+-[0-9][0-9]+-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\+[0-9]{2}:[0-9]{2}$/.test(x)) { - x = x.substring(0, x.indexOf("+")) + "Z" - return new Date(x) - } else if (Array.isArray(x)) { - return x.map((e) => correctType(e)) - } else if (!isNaN(x) && x !== "") { - return x === null ? null : Number(x) - } else if (typeof x === "object" && x !== null) { - const k = Object.keys(x) - const v = Object.values(x) - for (let i = 0; i < k.length; i++) { - if (typeof v[i] === "string" && (k[i].includes("name") || k[i].includes("version"))) continue // don't turn names made of numbers into integers - x[k[i]] = correctType(v[i]) - } - } - return x -} diff --git a/lib/tests/test.ts b/lib/tests/test.ts index 6be374d..995c001 100644 --- a/lib/tests/test.ts +++ b/lib/tests/test.ts @@ -85,17 +85,16 @@ function validate(object: unknown, schemaName: string, generator: tsj.SchemaGene /** * Check if getUser() and similar work fine */ -const testUserStuff = async (): Promise => { +const testUserStuff = async (user_gen: tsj.SchemaGenerator, score_gen: tsj.SchemaGenerator, + beat_gen: tsj.SchemaGenerator, event_gen: tsj.SchemaGenerator): Promise => { let okay = true const user_id = 7276846 - const generator = tsj.createGenerator({path: "lib/user.ts", additionalProperties: true}) let a1 = await | false>>attempt("\ngetUser: ", api.getUser({id: user_id})) - if (!isOk(a1, !a1 || (a1.id === user_id && validate(a1, "UserExtended", generator)))) okay = false + if (!isOk(a1, !a1 || (a1.id === user_id && validate(a1, "UserExtended", user_gen)))) okay = false let a2 = await | false>>attempt("getUsers: ", api.getUsers([user_id, 2])) - if (!isOk(a2, !a2 || (a2.length === 2 && validate(a2, "UserWithCountryCoverGroupsStatisticsrulesets", generator)))) okay = false + if (!isOk(a2, !a2 || (a2.length === 2 && validate(a2, "UserWithCountryCoverGroupsStatisticsrulesets", user_gen)))) okay = false - const score_gen = tsj.createGenerator({path: "lib/score.ts", additionalProperties: true}) let a3 = await | false>>attempt("getUserScores (best): ", api.getUserScores({id: user_id}, "best", 5)) if (!isOk(a3, !a3 || (a3.length === 5 && validate(a3, "ScoreWithUserBeatmapBeatmapset", score_gen)))) okay = false let a4 = await | false>>attempt("getUserScores (firsts): ", api.getUserScores({id: 6503700}, "firsts", 3)) @@ -106,17 +105,15 @@ const testUserStuff = async (): Promise => { if (!isOk(a5, !a5 || (a5.length === 1 && validate(a5, "ScoreWithUserBeatmapBeatmapset", score_gen)))) okay = false // Those are tested here to be consistent with index.ts and the API server's documentation - const beat_gen = tsj.createGenerator({path: "lib/beatmap.ts", additionalProperties: true}) let a6 = await | false>>attempt("getUserBeatmaps: ", api.getUserBeatmaps({id: user_id}, "guest")) if (!isOk(a6, !a6 || (a6.length === 1 && validate(a6, "BeatmapsetExtendedWithBeatmapExtended", beat_gen)))) okay = false let a7 = await | false>>attempt("getUserMostPlayed: ", api.getUserMostPlayed({id: user_id})) if (!isOk(a7, !a7 || (a7[0].beatmapset.title === "furioso melodia" && validate(a7, "BeatmapPlaycount", beat_gen)))) okay = false - const event_gen = tsj.createGenerator({path: "lib/event.ts", additionalProperties: true}) let a8 = await | false>>attempt("getUserRecentActivity: ", api.getUserRecentActivity({id: 7562902}, 25)) if (!isOk(a8, !a8 || (a8.length <= 25 && validate(a8, "EventUser", event_gen)))) okay = false let a9 = await | false>>attempt("getUserKudosu: ", api.getUserKudosu({id: user_id}, 5)) - if (!isOk(a9, !a9 || (a9.length === 5 && validate(a9, "KudosuHistory", generator)))) okay = false + if (!isOk(a9, !a9 || (a9.length === 5 && validate(a9, "KudosuHistory", user_gen)))) okay = false return okay } @@ -124,30 +121,28 @@ const testUserStuff = async (): Promise => { /** * Check if getBeatmap() and similar work fine */ -const testBeatmapStuff = async (): Promise => { +const testBeatmapStuff = async (beat_gen: tsj.SchemaGenerator, score_gen: tsj.SchemaGenerator): Promise => { let okay = true const beatmap_id = 388463 - const generator = tsj.createGenerator({path: "lib/beatmap.ts", additionalProperties: true}) let b1 = await | false>>attempt("\ngetBeatmap: ", api.getBeatmap({id: beatmap_id})) - if (!isOk(b1, !b1 || (b1.id === beatmap_id && validate(b1, "BeatmapExtendedWithFailtimesBeatmapsetextended", generator)))) okay = false + if (!isOk(b1, !b1 || (b1.id === beatmap_id && validate(b1, "BeatmapExtendedWithFailtimesBeatmapsetextended", beat_gen)))) okay = false let b2 = await | false>>attempt("getBeatmaps: ", api.getBeatmaps([beatmap_id, 4089655])) - if (!isOk(b2, !b2 || (b2.length === 2 && validate(b2, "BeatmapExtended", generator)))) okay = false + if (!isOk(b2, !b2 || (b2.length === 2 && validate(b2, "BeatmapExtended", beat_gen)))) okay = false let b3 = await | false>>attempt( "getBeatmapAttributesOsu: ", api.getBeatmapDifficultyAttributesOsu({id: 125660}, ["DT"])) - if (!isOk(b3, !b3 || (b3.approach_rate.toFixed(2) === "9.67" && validate(b3, "BeatmapDifficultyAttributesOsu", generator)))) okay = false + if (!isOk(b3, !b3 || (b3.approach_rate.toFixed(2) === "9.67" && validate(b3, "BeatmapDifficultyAttributesOsu", beat_gen)))) okay = false let b4 = await | false>>attempt( "getBeatmapAttributesTaiko: ", api.getBeatmapDifficultyAttributesTaiko({id: beatmap_id}, ["DT"])) - if (!isOk(b4, !b4 || (b4.great_hit_window < 35 && validate(b4, "BeatmapDifficultyAttributesTaiko", generator)))) okay = false + if (!isOk(b4, !b4 || (b4.great_hit_window < 35 && validate(b4, "BeatmapDifficultyAttributesTaiko", beat_gen)))) okay = false let b5 = await | false>>attempt( "getBeatmapAttributesFruits: ", api.getBeatmapDifficultyAttributesFruits({id: 705339}, ["DT"])) - if (!isOk(b5, !b5 || (b5.approach_rate.toFixed(2) === "10.33" && validate(b5, "BeatmapDifficultyAttributesFruits", generator)))) okay = false + if (!isOk(b5, !b5 || (b5.approach_rate.toFixed(2) === "10.33" && validate(b5, "BeatmapDifficultyAttributesFruits", beat_gen)))) okay = false let b6 = await | false>>attempt( "getBeatmapAttributesMania: ", api.getBeatmapDifficultyAttributesMania({id: 3980252}, ["DT"])) - if (!isOk(b6, !b6 || (b6.great_hit_window === 40 && validate(b6, "BeatmapDifficultyAttributesMania", generator)))) okay = false + if (!isOk(b6, !b6 || (b6.great_hit_window === 40 && validate(b6, "BeatmapDifficultyAttributesMania", beat_gen)))) okay = false - const score_gen = tsj.createGenerator({path: "lib/score.ts", additionalProperties: true}) let b7 = await | false>>attempt( "getBeatmapUserScore: ", api.getBeatmapUserScore({id: 176960}, {id: 7276846}, ["NM"])) if (!isOk(b7, !b7 || (b7.score.accuracy < 0.99 && validate(b7, "BeatmapUserScore", score_gen)))) okay = false @@ -155,11 +150,11 @@ const testBeatmapStuff = async (): Promise => { "getBeatmapUserScores: ", api.getBeatmapUserScores({id: 203993}, {id: 7276846}, osu.Rulesets.fruits)) if (!isOk(b8, !b8 || (b8.length === 1 && validate(b8, "Score", score_gen)))) okay = false let b9 = await | false>>attempt("getBeatmapset: ", api.getBeatmapset({id: 1971037})) - if (!isOk(b9, !b9 || (b9.submitted_date?.toISOString().substring(0, 10) === "2023-04-07", validate(b9, "BeatmapsetExtendedPlus", generator)))) okay = false + if (!isOk(b9, !b9 || (b9.submitted_date?.toISOString().substring(0, 10) === "2023-04-07", validate(b9, "BeatmapsetExtendedPlus", beat_gen)))) okay = false let b10 = await | false>>attempt("getBeatmapPack: ", api.getBeatmapPack({tag: "P217"})) - if (!isOk(b10, !b10 || (b10.tag === "P217" && validate(b10, "BeatmapPack", generator)))) okay = false + if (!isOk(b10, !b10 || (b10.tag === "P217" && validate(b10, "BeatmapPack", beat_gen)))) okay = false let b11 = await | false>>attempt("getBeatmapPacks: ", api.getBeatmapPacks("tournament")) - if (!isOk(b11, !b11 || (b11.length >= 100 && validate(b11, "BeatmapPack", generator)))) okay = false + if (!isOk(b11, !b11 || (b11.length >= 100 && validate(b11, "BeatmapPack", beat_gen)))) okay = false let b12 = await | false>>attempt("getBeatmapScores: ", api.getBeatmapScores({id: 129891})) if (!isOk(b12, !b12 || (b12[0].score >= 132408001 && validate(b12, "ScoreWithUser", score_gen)))) okay = false @@ -169,17 +164,16 @@ const testBeatmapStuff = async (): Promise => { /** * Check if getChangelogBuild() and similar work fine */ -const testChangelogStuff = async (): Promise => { - const generator = tsj.createGenerator({path: "lib/changelog.ts", additionalProperties: true}) +const testChangelogStuff = async (changelog_gen: tsj.SchemaGenerator): Promise => { let okay = true let c1 = await | false>>attempt("\ngetChangelogBuild: ", api.getChangelogBuild("lazer", "2023.1008.1")) - if (!isOk(c1, !c1 || (c1.id === 7156 && validate(c1, "ChangelogBuildWithChangelogentriesVersions", generator)))) okay = false + if (!isOk(c1, !c1 || (c1.id === 7156 && validate(c1, "ChangelogBuildWithChangelogentriesVersions", changelog_gen)))) okay = false let c2 = await | false>>attempt( "getChangelogBuilds: ", api.getChangelogBuilds({from: "2023.1031.0", to: "20231102.3"}, 7184, undefined, ["markdown"])) - if (!isOk(c2, !c2 || (c2.length === 4 && validate(c2, "ChangelogBuildWithUpdatestreamsChangelogentries", generator)))) okay = false + if (!isOk(c2, !c2 || (c2.length === 4 && validate(c2, "ChangelogBuildWithUpdatestreamsChangelogentries", changelog_gen)))) okay = false let c3 = await | false>>attempt("getChangelogStreams: ", api.getChangelogStreams()) - if (!isOk(c3, !c3 || (c3.length > 2 && validate(c3, "UpdateStreamWithLatestbuildUsercount", generator)))) okay = false + if (!isOk(c3, !c3 || (c3.length > 2 && validate(c3, "UpdateStreamWithLatestbuildUsercount", changelog_gen)))) okay = false return okay } @@ -187,29 +181,28 @@ const testChangelogStuff = async (): Promise => { /** * Check if getRoom(), getMatch() and similar work fine */ -const testMultiplayerStuff = async (): Promise => { - const generator = tsj.createGenerator({path: "lib/multiplayer.ts", additionalProperties: true}) +const testMultiplayerStuff = async (multi_gen: tsj.SchemaGenerator): Promise => { let okay = true let d1 = await | false>>attempt("\ngetRoom (realtime): ", api.getRoom({id: 231069})) - if (!isOk(d1, !d1 || (d1.recent_participants.length === 4 && validate(d1, "Room", generator)))) okay = false + if (!isOk(d1, !d1 || (d1.recent_participants.length === 4 && validate(d1, "Room", multi_gen)))) okay = false let d2 = await | false>>attempt("getRoom (playlist): ", api.getRoom({id: 51693})) - if (!isOk(d2, !d2 || (d2.participant_count === 159 && validate(d2, "Room", generator)))) okay = false + if (!isOk(d2, !d2 || (d2.participant_count === 159 && validate(d2, "Room", multi_gen)))) okay = false if (d1) { // can't bother getting and writing down the id of a playlist item let d3 = await | false>>attempt( "getPlaylistItemScores (realtime): ", api.getPlaylistItemScores({id: d1.playlist[0].id, room_id: d1.id})) - !isOk(d3, !d3 || (d3.scores.length > 0 && validate(d3, "MultiplayerScores", generator)), 1) ? + !isOk(d3, !d3 || (d3.scores.length > 0 && validate(d3, "MultiplayerScores", multi_gen)), 1) ? console.log("Bug not fixed yet...") : console.log("Bug fixed!!! :partying_face:") } if (d2) { // still can't bother getting and writing down the id of a playlist item let d4 = await | false>>attempt( "getPlaylistItemScores (playlist): ", api.getPlaylistItemScores({id: d2.playlist[0].id, room_id: d2.id})) - if (!isOk(d4, !d4 || (d4.scores.length >= 50 && validate(d4, "MultiplayerScores", generator)), 1)) okay = false + if (!isOk(d4, !d4 || (d4.scores.length >= 50 && validate(d4, "MultiplayerScores", multi_gen)), 1)) okay = false } let d5 = await | false>>attempt("getMatch: ", api.getMatch(62006076)) - if (!isOk(d5, !d5 || (d5.match.name === "CWC2020: (Italy) vs (Indonesia)" && validate(d5, "Match", generator)), 3)) okay = false + if (!isOk(d5, !d5 || (d5.match.name === "CWC2020: (Italy) vs (Indonesia)" && validate(d5, "Match", multi_gen)), 3)) okay = false let d6 = await | false>>attempt("getMatches: ", api.getMatches()) - if (!isOk(d6, !d6 || (d6[0].id > 111250329 && validate(d6, "MatchInfo", generator)))) okay = false + if (!isOk(d6, !d6 || (d6[0].id > 111250329 && validate(d6, "MatchInfo", multi_gen)))) okay = false return okay } @@ -217,22 +210,21 @@ const testMultiplayerStuff = async (): Promise => { /** * Check if getRanking() and similar work fine */ -const testRankingStuff = async (): Promise => { - const generator = tsj.createGenerator({path: "lib/ranking.ts", additionalProperties: true}) +const testRankingStuff = async (rank_gen: tsj.SchemaGenerator): Promise => { let okay = true let e1 = await | false>>attempt("\ngetKudosuRanking: ", api.getKudosuRanking()) - if (!isOk(e1, !e1 || (e1[0].kudosu.total > 10000 && validate(e1, "UserWithKudosu", generator)))) okay = false + if (!isOk(e1, !e1 || (e1[0].kudosu.total > 10000 && validate(e1, "UserWithKudosu", rank_gen)))) okay = false let e2 = await | false>>attempt( "getRanking: ", api.getRanking(osu.Rulesets.osu, "score", 1, "all", "FR")) - if (!isOk(e2, !e2 || (e2.ranking[0].level.current > 106 && validate(e2, "Rankings", generator)), 2)) okay = false + if (!isOk(e2, !e2 || (e2.ranking[0].level.current > 106 && validate(e2, "Rankings", rank_gen)), 2)) okay = false let e3 = await | false>>attempt("getCountryRanking: ", api.getCountryRanking(osu.Rulesets.osu)) - if (!isOk(e3, !e3 || (e3.ranking[0].code === "US" && validate(e3, "RankingsCountry", generator)))) okay = false + if (!isOk(e3, !e3 || (e3.ranking[0].code === "US" && validate(e3, "RankingsCountry", rank_gen)))) okay = false let e4 = await | false>>attempt( "getSpotlightRanking: ", api.getSpotlightRanking(osu.Rulesets.taiko, {id: 48})) - if (!isOk(e4, !e4 || (e4.ranking[0].hit_accuracy === 97.85 && validate(e4, "RankingsSpotlight", generator)), 2)) okay = false + if (!isOk(e4, !e4 || (e4.ranking[0].hit_accuracy === 97.85 && validate(e4, "RankingsSpotlight", rank_gen)), 2)) okay = false let e5 = await | false>>attempt("getSpotlights: ", api.getSpotlights()) - if (!isOk(e5, !e5 || (e5.length >= 132 && validate(e5, "Spotlight", generator)))) okay = false + if (!isOk(e5, !e5 || (e5.length >= 132 && validate(e5, "Spotlight", rank_gen)))) okay = false return okay } @@ -240,16 +232,15 @@ const testRankingStuff = async (): Promise => { /** * Check if searchUser() and similar work fine */ -const testHomeStuff = async (): Promise => { - const generator = tsj.createGenerator({path: "lib/home.ts", additionalProperties: true}) +const testHomeStuff = async (home_gen: tsj.SchemaGenerator): Promise => { let okay = true let f1 = await | false>>attempt("\nsearchUser: ", api.searchUser("Tae", 2)) - if (!isOk(f1, !f1 || (f1.data.length === 20 && validate(f1, "SearchResultUser", generator)))) okay = false + if (!isOk(f1, !f1 || (f1.data.length === 20 && validate(f1, "SearchResultUser", home_gen)))) okay = false let f2 = await | false>>attempt("searchWiki: ", api.searchWiki("Beat", 2)) - if (!isOk(f2, !f2 || (f2.data.length === 50 && validate(f2, "SearchResultWiki", generator)))) okay = false + if (!isOk(f2, !f2 || (f2.data.length === 50 && validate(f2, "SearchResultWiki", home_gen)))) okay = false let f3 = await | false>>attempt("getWikiPage: ", api.getWikiPage("Rules")) - if (!isOk(f3, !f3 || (f3.title === "Rules" && validate(f3, "WikiPage", generator)))) okay = false + if (!isOk(f3, !f3 || (f3.title === "Rules" && validate(f3, "WikiPage", home_gen)))) okay = false return okay } @@ -257,12 +248,17 @@ const testHomeStuff = async (): Promise => { const test = async (id: string, secret: string): Promise => { api = await osu.API.createAsync({id: Number(id), secret}, undefined, "all") - const a = await testUserStuff() - const b = await testBeatmapStuff() - const c = await testChangelogStuff() - const d = await testMultiplayerStuff() - const e = await testRankingStuff() - const f = await testHomeStuff() + const score_gen = tsj.createGenerator({path: "lib/score.ts", additionalProperties: true}) + const user_gen = tsj.createGenerator({path: "lib/user.ts", additionalProperties: true}) + const beat_gen = tsj.createGenerator({path: "lib/beatmap.ts", additionalProperties: true}) + const event_gen = tsj.createGenerator({path: "lib/event.ts", additionalProperties: true}) + + const a = await testUserStuff(user_gen, score_gen, beat_gen, event_gen) + const b = await testBeatmapStuff(beat_gen, score_gen) + const c = await testChangelogStuff(tsj.createGenerator({path: "lib/changelog.ts", additionalProperties: true})) + const d = await testMultiplayerStuff(tsj.createGenerator({path: "lib/multiplayer.ts", additionalProperties: true})) + const e = await testRankingStuff(tsj.createGenerator({path: "lib/ranking.ts", additionalProperties: true})) + const f = await testHomeStuff(tsj.createGenerator({path: "lib/home.ts", additionalProperties: true})) const arr = [a,b,c,d,e,f] diff --git a/lib/user.ts b/lib/user.ts index f417913..8c42e59 100644 --- a/lib/user.ts +++ b/lib/user.ts @@ -198,6 +198,9 @@ export interface UserExtendedWithStatisticsrulesets extends UserExtended, UserWi } +/** + * Expected from UserWithCountryCoverGroupsStatisticsrulesets, UserWithCountryCoverGroupsStatisticsSupport + */ export interface UserStatistics { count_100: number count_300: number diff --git a/package.json b/package.json index d36be8a..3c9682c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-v2-js", - "version": "0.4.0", + "version": "0.4.1", "description": "Package to easily access osu!api version 2.0", "type": "module", "main": "dist/index.js",