UNPKG

osu-web.js

Version:

osu.js is an unofficial Javascript and Typescript SDK for the browser-facing portion of osu! with type safety in mind

1,722 lines (1,710 loc) 89.4 kB
import polyfillFetch, { Response as Response$1 } from 'node-fetch'; declare class Base$1 { protected clientId: number; protected clientSecret: string; protected redirectUri: string; protected oauthUrl: string; protected fetch: typeof fetch | typeof polyfillFetch; constructor(clientId: number, clientSecret: string, redirectUri: string, options?: { polyfillFetch?: typeof polyfillFetch; }); } declare const isOsuJSErrorSymbol: unique symbol; /** * Documentation: {@link https://osujs.mario564.com/extras/error-handling} */ declare class OsuJSGeneralError extends Error { readonly _: { [isOsuJSErrorSymbol]: boolean; }; type: 'invalid_json_syntax' | 'network_error' | 'undefined_fetch'; constructor(type: 'invalid_json_syntax' | 'network_error' | 'undefined_fetch'); } /** * Documentation: {@link https://osujs.mario564.com/extras/error-handling} */ declare class OsuJSUnexpectedResponseError extends Error { readonly _: { [isOsuJSErrorSymbol]: boolean; }; type: "unexpected_response"; private response1; constructor(response: Response | Response$1); response<T extends boolean | undefined = undefined>(polyfill?: T): T extends true ? Response$1 : Response; } /** * Documentation: {@link https://osujs.mario564.com/references/modes-enum} */ declare enum ModesEnum { osu = 0, taiko = 1, fruits = 2, mania = 3 } /** * Documentation: {@link https://osujs.mario564.com/references/status-enum} */ declare enum StatusEnum { graveyard = -2, wip = -1, pending = 0, ranked = 1, approved = 2, qualified = 3, loved = 4 } /** * Documentation: {@link https://osujs.mario564.com/references/genres-enum} */ declare enum GenresEnum { Any = 0, Unspecified = 1, 'Video Game' = 2, Anime = 3, Rock = 4, Pop = 5, Other = 6, Novelty = 7, 'Hip Hop' = 9, Electronic = 10, Metal = 11, Classical = 12, Folk = 13, Jazz = 14 } /** * Documentation: {@link https://osujs.mario564.com/references/languages-enum} */ declare enum LanguagesEnum { Any = 0, Unspecified = 1, English = 2, Japanese = 3, Chinese = 4, Instrumental = 5, Korean = 6, French = 7, German = 8, Swedish = 9, Spanish = 10, Italian = 11, Russian = 12, Polish = 13, Other = 14 } /** * Documentation: {@link https://osujs.mario564.com/references/mods-enum} */ declare enum ModsEnum { NF = 1, EZ = 2, TD = 4, HD = 8, HR = 16, SD = 32, DT = 64, RX = 128, HT = 256, NC = 512, FL = 1024, AT = 2048, SO = 4096, AP = 8192, PF = 16384, '4K' = 32768, '5K' = 65536, '6K' = 131072, '7K' = 262144, '8K' = 524288, FI = 1048576, RD = 2097152, CN = 4194304, TP = 8388608, K9 = 16777216, KC = 33554432, '1K' = 67108864, '3K' = 134217728, '2K' = 268435456, SV2 = 536870912, MR = 1073741824 } /** * Documentation: {@link https://osujs.mario564.com/references/scoring-type-enum} */ declare enum ScoringTypeEnum { Score = 0, Accuracy = 1, Combo = 2, 'Score V2' = 3 } /** * Documentation: {@link https://osujs.mario564.com/references/team-type-enum} */ declare enum TeamTypeEnum { 'Head To Head' = 0, 'Tag Co-Op' = 1, 'Team VS' = 2, 'Tag Team VS' = 3 } /** * Documentation: {@link https://osujs.mario564.com/references/team-color-enum} */ declare enum TeamColorEnum { Blue = 1, Red = 2 } type BaseMod<TAcronym extends string, TSettings extends Record<string, any> | undefined = undefined> = TSettings extends undefined ? { acronym: TAcronym; } : { acronym: TAcronym; settings?: TSettings; }; type EasyMod = BaseMod<'EZ', { retries: number; }>; type NoFailMod = BaseMod<'NF'>; type HalfTimeMod = BaseMod<'HT', { speed_change: number; adjust_pitch: boolean; }>; type DaycoreMod = BaseMod<'DC', { speed_change: number; }>; type HardRockMod = BaseMod<'HR'>; type SuddenDeathMod = BaseMod<'SD', { restart: boolean; }>; type PerfectMod = BaseMod<'PF', { restart: boolean; }>; type DoubleTimeMod = BaseMod<'DT', { speed_change: number; adjust_pitch: boolean; }>; type NightcoreMod = BaseMod<'NC', { speed_change: number; }>; type HiddenMod = BaseMod<'HD', { only_fade_approach_circles: boolean; }>; type FlaslightMod = BaseMod<'FL', { follow_delay: number; size_multiplier: number; combo_based_size: boolean; }>; type BlindsMod = BaseMod<'BL'>; type StrictTrackingMod = BaseMod<'ST'>; type AccuracyChallengeMod = BaseMod<'AC', { minimum_accuracy: number; accuracy_judge_mode: string; restart: boolean; }>; type TargetPracticeMod = BaseMod<'TP', { seed: number; metronome: boolean; }>; type DifficultyAdjustMod = BaseMod<'DA', { circle_size: number; approach_rate: number; drain_rate: number; overall_difficulty: number; extended_limits: boolean; }>; type ClassicMod = BaseMod<'CL', { no_slider_head_accuracy: boolean; classic_note_lock: boolean; always_play_tail_sample: boolean; fade_hit_circle_early: boolean; classic_health: boolean; }>; type RandomMod = BaseMod<'RD', { angle_sharpness: number; seed: number; }>; type MirrorMod = BaseMod<'MR', { reflection: string; }>; type AlternateMod = BaseMod<'AL'>; type SingleTapMod = BaseMod<'SG'>; type AutoplayMod = BaseMod<'AT'>; type CinemaMod = BaseMod<'CN'>; type RelaxMod = BaseMod<'RX'>; type AutopilotMod = BaseMod<'AP'>; type SpunOutMod = BaseMod<'SO'>; type TransformMod = BaseMod<'TR'>; type WiggleMod = BaseMod<'WG', { strength: number; }>; type SpinInMod = BaseMod<'SI'>; type GrowMod = BaseMod<'GR', { start_scale: number; }>; type DeflateMod = BaseMod<'DF', { start_scale: number; }>; type WindUpMod = BaseMod<'WU', { initial_rate: number; final_rate: number; adjust_pitch: boolean; }>; type WindDownMod = BaseMod<'WD', { initial_rate: number; final_rate: number; adjust_pitch: boolean; }>; type TraceableMod = BaseMod<'TC'>; type BarrelRollMod = BaseMod<'BR', { spin_speed: number; direction: string; }>; type ApproachDifferentMod = BaseMod<'AD', { scale: number; style: string; }>; type MutedMod = BaseMod<'MU', { inverse_muting: boolean; enable_metronome: boolean; mute_combo_count: number; affects_hit_sounds: boolean; }>; type NoScopeMod = BaseMod<'NS', { hidden_combo_count: number; }>; type MagnetisedMod = BaseMod<'MG', { attraction_strength: number; }>; type RepelMod = BaseMod<'RP', { repulsion_strength: number; }>; type AdaptiveSpeedMod = BaseMod<'AS', { initial_rate: number; adjust_pitch: boolean; }>; type FreezeFrameMod = BaseMod<'FR'>; type BubblesMod = BaseMod<'BU'>; type SynesthesiaMod = BaseMod<'SY'>; type DepthMod = BaseMod<'DP', { max_depth: number; show_approach_circles: boolean; }>; type TouchDeviceMod = BaseMod<'TD'>; type ScoreV2Mod = BaseMod<'SV2'>; type SwapMod = BaseMod<'SW'>; type FloatingFruitsMod = BaseMod<'FF'>; type FadeInMod = BaseMod<'FI', { coverage: number; }>; type DualStagesMod = BaseMod<'DS'>; type InvertMod = BaseMod<'IN'>; type ConstantSpeedMod = BaseMod<'CS'>; type HoldOffMod = BaseMod<'HO'>; type Key1Mod = BaseMod<'1K'>; type Key2Mod = BaseMod<'2K'>; type Key3Mod = BaseMod<'3K'>; type Key4Mod = BaseMod<'4K'>; type Key5Mod = BaseMod<'5K'>; type Key6Mod = BaseMod<'6K'>; type Key7Mod = BaseMod<'7K'>; type Key8Mod = BaseMod<'8K'>; type Key9Mod = BaseMod<'9K'>; type Key10Mod = BaseMod<'10K'>; type ModSettings = EasyMod | NoFailMod | HalfTimeMod | DaycoreMod | HardRockMod | SuddenDeathMod | PerfectMod | DoubleTimeMod | NightcoreMod | HiddenMod | FlaslightMod | BlindsMod | StrictTrackingMod | AccuracyChallengeMod | TargetPracticeMod | DifficultyAdjustMod | ClassicMod | RandomMod | MirrorMod | AlternateMod | SingleTapMod | AutoplayMod | CinemaMod | RelaxMod | AutopilotMod | SpunOutMod | TransformMod | WiggleMod | SpinInMod | GrowMod | DeflateMod | WindUpMod | WindDownMod | TraceableMod | BarrelRollMod | ApproachDifferentMod | MutedMod | NoScopeMod | MagnetisedMod | RepelMod | AdaptiveSpeedMod | FreezeFrameMod | BubblesMod | SynesthesiaMod | DepthMod | TouchDeviceMod | ScoreV2Mod | SwapMod | FloatingFruitsMod | FadeInMod | DualStagesMod | InvertMod | ConstantSpeedMod | HoldOffMod | Key1Mod | Key2Mod | Key3Mod | Key4Mod | Key5Mod | Key6Mod | Key7Mod | Key8Mod | Key9Mod | Key10Mod; /** * Timestamp string in ISO 8601 format */ type ISOTimestamp = string; /** * Documentation: {@link https://osujs.mario564.com/extras/error-handling} */ type OsuJSError = OsuJSGeneralError | OsuJSUnexpectedResponseError; type Cursor = string | null; type SafeParse<TData, TUsePolyfillResponse extends boolean = false> = { success: true; data: TData; } | { success: false; response: TUsePolyfillResponse extends true ? Response$1 : Response; }; type Mod = keyof typeof ModsEnum | 'DC' | 'BL' | 'ST' | 'AC' | 'DA' | 'CL' | 'AL' | 'SG' | 'TR' | 'WG' | 'SI' | 'GR' | 'DF' | 'WU' | 'WD' | 'TC' | 'BR' | 'AD' | 'MU' | 'NS' | 'MG' | 'RP' | 'AS' | 'FR' | 'BU' | 'SY' | 'DP' | 'SW' | 'FF' | 'DS' | 'IN' | 'CS' | 'HO' | '9K' | '10K'; type RankStatus = keyof typeof StatusEnum; type GameMode = 'fruits' | 'mania' | 'osu' | 'taiko'; type UserBeatmapsType = 'favourite' | 'graveyard' | 'guest' | 'loved' | 'most_played' | 'nominated' | 'pending' | 'ranked'; type CommentableType = 'beatmapset' | 'news_post' | 'build'; type CommentSort = 'new' | 'old' | 'top'; type MultiplayerScoresSort = 'score_asc' | 'score_desc'; type RankingType = 'charts' | 'country' | 'performance' | 'score'; type UserScoreType = 'best' | 'firsts' | 'recent'; type ChangelogStream = 'stable40' | 'beta40' | 'cuttingedge' | 'lazer' | 'web'; type DiscussionMessageType = 'suggestion' | 'problem' | 'mapper_note' | 'praise' | 'hype' | 'review'; type Playstyle = 'mouse' | 'keyboard' | 'tablet' | 'touch'; type Scope = 'chat.read' | 'chat.write' | 'chat.write_manage' | 'delegate' | 'forum.write' | 'friends.read' | 'identify' | 'public'; type ProfilePageSection = 'me' | 'recent_activity' | 'beatmaps' | 'historical' | 'kudosu' | 'top_ranks' | 'medals'; type UserAccountHistoryType = 'note' | 'restriction' | 'silence'; type KudosuAction = 'give' | 'vote.give' | 'reset' | 'vote.reset' | 'revoke' | 'vote.revoke'; type Rank = 'SS' | 'SSH' | 'S' | 'SH' | 'A' | 'B' | 'C' | 'D' | 'F'; type UserEventType = 'achievement' | 'beatmapPlaycount' | 'beatmapsetApprove' | 'beatmapsetDelete' | 'beatmapsetRevive' | 'beatmapsetUpdate' | 'beatmapsetUpload' | 'rank' | 'rankLost' | 'userSupportAgain' | 'userSupportFirst' | 'userSupportGift' | 'usernameChange'; type AchievementGrouping = 'Skill' | 'Hush-Hush' | 'Dedication' | 'Mod Introduction'; type EventBeatmapsetApprovedType = 'ranked' | 'approved' | 'qualified' | 'loved'; type SpotlightType = 'monthly' | 'spotlight' | 'theme' | 'special' | 'bestof'; type ChannelType = 'PUBLIC' | 'PRIVATE' | 'MULTIPLAYER' | 'SPECTATOR' | 'TEMPORARY' | 'PM' | 'GROUP' | 'ANNOUNCE'; type ChatMessageType = 'action' | 'markdown' | 'plain'; type ForumTopicType = 'normal' | 'sticky' | 'announcement'; interface Token { token_type: string; expires_in: number; access_token: string; refresh_token: string; } type GuestToken = Omit<Token, 'refresh_token'>; interface UserCompact { 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: string; pm_friends_only: boolean; profile_colour: string | null; username: string; } interface Country { code: string; name: string; } interface Cover { custom_url: string | null; url: string; id: string | null; } interface UserKudosu { available: number; total: number; } interface User extends UserCompact { country: Country; cover: Cover; discord: string | null; has_supported: boolean; interests: string | null; join_date: ISOTimestamp; kudosu: UserKudosu; location: string | null; max_blocks: number; max_friends: number; occupation: string | null; playmode: GameMode; playstyle: Playstyle[]; post_count: number; profile_order: ProfilePageSection[]; title: string | null; title_url: string | null; twitter: string | null; website: string | null; } interface UserAccountHistory { description: string | null; id: number; length: number; permanent: boolean; timestamp: string; type: UserAccountHistoryType; } interface UserActiveTournamentBanner { id: number; tournament_id: number; image: string | null; 'image@2x': string | null; } interface UserBadge { awarded_at: ISOTimestamp; description: string; image_url: string; 'image@2x_url': string; url: string; } interface Page { html: string; raw: string; } interface Group { colour: string | null; has_listing: boolean; has_playmodes: boolean; id: number; identifier: string; is_probationary: boolean; name: string; short_name: string; } interface UserGroup extends Group { playmodes: GameMode[] | null; } interface MonthlyPlaycount { start_date: ISOTimestamp; count: number; } interface RankHighest { rank: number; updated_at: ISOTimestamp; } interface RankHistory { mode: GameMode; data: number[]; } interface GradeCounts { a: number; s: number; sh: number; ss: number; ssh: number; } interface UserLevel { current: number; progress: number; } interface UserStatisticsVariant { mode: GameMode; variant: string; country_rank: number; global_rank: number; pp: number; } interface UserStatistics { count_100: number; count_300: number; count_50: number; count_miss: number; grade_counts: GradeCounts; hit_accuracy: number; is_ranked: boolean; level: UserLevel; maximum_combo: number; play_count: number; play_time: number; pp: number; pp_exp: number; global_rank: number | null; global_rank_exp: number | null; ranked_score: number; replays_watched_by_others: number; total_hits: number; total_score: number; country_rank: number | null; variants?: UserStatisticsVariant[]; } interface UserAchievement { achieved_at: ISOTimestamp; achievement_id: number; } interface UserExtended extends User { account_history: UserAccountHistory[]; active_tournament_banners: UserActiveTournamentBanner[]; active_tournament_banner: UserActiveTournamentBanner | null; badges: UserBadge[]; beatmap_playcounts_count: number; favourite_beatmapset_count: number; follower_count: number; graveyard_beatmapset_count: number; groups: UserGroup[]; loved_beatmapset_count: number; mapping_follower_count: number; monthly_playcounts: MonthlyPlaycount[]; page: Page; pending_beatmapset_count: number; previous_usernames: string[]; rank_highest: RankHighest | null; rank_history: RankHistory; ranked_beatmapset_count: number; replays_watched_counts: MonthlyPlaycount[]; scores_best_count: number; scores_first_count: number; scores_recent_count: number; statistics: UserStatistics; support_level: number; user_achievements: UserAchievement[]; } interface Giver { url: string; username: string; } interface Post { url: string | null; title: string; } interface UserKudosuHistory { id: number; action: KudosuAction; amount: number; model: string; created_at: ISOTimestamp; giver: Giver | null; post: Post; } type StatisticsRulesets = Record<GameMode, UserStatistics | undefined>; interface BeatmapCompact { beatmapset_id: number; difficulty_rating: number; id: number; mode: GameMode; status: RankStatus; total_length: number; user_id: number; version: string; } interface ScoreStatistics { count_50: number; count_100: number; count_300: number; count_geki: number | null; count_katu: number | null; count_miss: number; } interface Score { id: number; best_id: number; user_id: number; accuracy: number; mods: Mod[]; score: number; max_combo: number; perfect: boolean; statistics: ScoreStatistics; passed: boolean; pp: number; rank: Rank; created_at: ISOTimestamp; mode: GameMode; mode_int: number; replay: boolean; } interface ScoreV2 { accuracy: number; beatmap_id: number; best_id: number | null; build_id: number | null; classic_total_score: number | null; ended_at: ISOTimestamp; has_replay: boolean; id: number; is_perfect_combo: boolean; legacy_perfect: boolean; legacy_score_id: number | null; legacy_total_score: number; max_combo: number; maximum_statistics: ScoreStatistics; mods: ModSettings[]; passed: boolean; playlist_item_id: number | null; pp: number | null; preserve: boolean | null; processed: boolean | null; rank: Rank; room_id: number | null; ruleset_id: number; started_at: ISOTimestamp | null; statistics: ScoreStatistics; total_score: number; type: string; user_id: number; } interface Covers { cover: string; 'cover@2x': string; card: string; 'card@2x': string; list: string; 'list@2x': string; slimcover: string; 'slimcover@2x': string; } interface BeatmapsetCompact { artist: string; artist_unicode: string; covers: Covers; creator: string; favourite_count: number; id: number; nsfw: boolean; play_count: number; preview_url: string; source: string; status: RankStatus; title: string; title_unicode: string; user_id: string; video: boolean; } interface UserScore extends Score { beatmap: BeatmapCompact & { checksum: string | null; }; beatmapset: BeatmapsetCompact; user: UserCompact; } interface UserScoreV2 extends Pick<UserScore, 'beatmap' | 'beatmapset' | 'user'>, ScoreV2 { } interface Weight { percentage: number; pp: number; } interface UserBestScore extends UserScore, Score { weight: Weight; } interface UserBestScoreV2 extends UserScoreV2, ScoreV2 { weight: Weight; } interface BeatmapsetAvailability { download_disabled: boolean; more_information: string | null; } interface BeatmapsetHype { current: number; required: number; } interface Beatmapset extends BeatmapsetCompact { availability: BeatmapsetAvailability; bpm: number; can_be_hyped: boolean; creator: string; discussion_locked: boolean; hype: BeatmapsetHype | null; is_scoreable: boolean; last_updated: ISOTimestamp; legacy_thread_url: string | null; nominations_summary: BeatmapsetHype; ranked: number; ranked_date: ISOTimestamp | null; source: string; storyboard: boolean; submitted_date: ISOTimestamp | null; tags: string; } interface Beatmap extends BeatmapCompact { accuracy: number; ar: number; beatmapset_id: number; bpm: number | null; convert: boolean; count_circles: number; count_sliders: number; count_spinners: number; cs: number; deleted_at: ISOTimestamp | null; drain: number; hit_length: number; is_scoreable: boolean; last_updated: ISOTimestamp; mode_int: number; passcount: number; playcount: number; ranked: number; url: string; } interface BeatmapPlaycount { beatmap_id: number; beatmap: BeatmapCompact | null; beatmapset: BeatmapsetCompact | null; count: number; } interface EventAchievement { icon_url: string; id: number; name: string; grouping: AchievementGrouping; ordering: number; slug: string; description: string; mode: GameMode | null; instructions: string; } interface EventUser { username: string; url: string; } interface EventBeatmap { title: string; url: string; } interface BaseUserEvent { created_at: ISOTimestamp; id: number; type: UserEventType; } interface UserEventAchievement extends BaseUserEvent { type: 'achievement'; achievement: EventAchievement; user: EventUser; } interface UserEventBeatmapPlaycount extends BaseUserEvent { type: 'beatmapPlaycount'; beatmap: EventBeatmap; count: number; } interface UserEventBeatmapsetApprove extends BaseUserEvent { type: 'beatmapsetApprove'; approval: EventBeatmapsetApprovedType; beatmapset: EventBeatmap; } interface UserEventBeatmapsetDelete extends BaseUserEvent { type: 'beatmapsetDelete'; beatmapset: EventBeatmap; } interface UserEventBeatmapsetUpdate extends BaseUserEvent { type: 'beatmapsetRevive' | 'beatmapsetUpdate' | 'beatmapsetUpload'; beatmapset: EventBeatmap; user: EventUser; } interface UserEventRank extends BaseUserEvent { mode: GameMode; beatmap: EventBeatmap; user: EventUser; } interface UserEventRankAchieved extends BaseUserEvent, UserEventRank { type: 'rank'; scoreRank: Rank; } interface UserEventRankLost extends BaseUserEvent, UserEventRank { type: 'rankLost'; } interface UserEventUserUpdate extends BaseUserEvent { type: 'userSupportAgain' | 'userSupportFirst' | 'userSupportGift'; user: EventUser; } interface UserEventUsernameUpdate extends BaseUserEvent { type: 'usernameChange'; user: EventUser & { previousUsername: string | null; }; } type UserEvent = UserEventAchievement | UserEventBeatmapPlaycount | UserEventBeatmapsetApprove | UserEventBeatmapsetDelete | UserEventBeatmapsetUpdate | UserEventRankAchieved | UserEventRankLost | UserEventUserUpdate | UserEventUsernameUpdate; interface WikiPage { available_locales: string[]; layout: string; locale: string; markdown: string; path: string; subtitle: string | null; tags: string[]; title: string; } type SearchResult<T> = { data: T[]; total: number; }; interface SearchResults { user: SearchResult<UserCompact> | null; wiki_page: SearchResult<WikiPage> | null; } interface CommentableMetadata { id: number; title: string; type: string; url: string; } interface Comment { commentable_id: number; commentable_type: CommentableType; created_at: ISOTimestamp; deleted_at: ISOTimestamp | null; edited_at: ISOTimestamp | null; edited_by_id: number | null; id: number; legacy_name: string | null; message: string | null; message_html: string | null; parent_id: number | null; pinned: boolean; replies_count: number; updated_at: ISOTimestamp; user_id: number; votes_count: number; } interface CommentBundle { commentable_meta: CommentableMetadata[]; comments: Comment[]; has_more: boolean; has_more_id: number | null; included_comments: Comment[]; pinned_commnets: Comment[] | null; sort: CommentSort; top_level_count: number | null; total: number | null; user_follow: boolean; user_votes: number[]; users: UserCompact[]; } interface MultiplayerScoresParams { limit: number; sort: MultiplayerScoresSort; } interface MultiplayerScoreMod { acronym: Mod; } interface MultiplayerScoreStatistics { Ok: number; Meh: number; Good: number; Miss: number; None: number; Great: number; Perfect: number; IgnoreHit: number; IgnoreMiss: number; LargeBonus: number; SmallBonus: number; LargeTickHit: number; SmallTickHit: number; LargeTickMiss: number; SmallTickMiss: number; } interface MultiplayerScore { id: number; user_id: number; room_id: number; playlist_item_id: number; beatmap_id: number; rank: Rank; total_score: number; accuracy: number; max_combo: number; mods: MultiplayerScoreMod[]; statistics: MultiplayerScoreStatistics; passed: boolean; position: number | null; user: UserCompact & { country: Country; cover: Cover; }; } interface MultiplayerScores { cursor_string: Cursor; params: MultiplayerScoresParams; scores: MultiplayerScore[]; total: number | null; user_score: MultiplayerScore | null; } interface Spotlight { end_date: ISOTimestamp; id: number; mode_specific: boolean; participant_count: number | null; name: string; start_date: ISOTimestamp; type: SpotlightType; } interface Rankings { beatmapsets: Beatmapset[] | null; ranking: (UserStatistics & { user: UserCompact & { country: Country; cover: Cover; }; })[]; spotlight: Spotlight | null; total: number; } interface NewsPost { author: string; edit_url: string; first_image: string | null; id: number; published_at: ISOTimestamp; slug: string; title: string; updated_at: ISOTimestamp; } interface NewsSidebar { current_year: number; news_posts: NewsPost; years: number[]; } interface NewsSearch { limit: number; sort: 'published_desc'; } interface NewsListing { cursor_string: Cursor; news_posts: NewsPost & { preview: string; }; news_sidebar: NewsSidebar; search: NewsSearch; } interface NewsNavigation { newer: NewsPost | null; older: NewsPost | null; } interface Fails { exit: number[] | null; fail: number[] | null; } interface BeatmapUserScore { position: number; score: Score & { beatmap: Beatmap & { checksum: string | null; }; user: UserCompact & { country: Country; cover: Cover; }; }; } interface BeatmapUserScoreV2 { position: number; score: ScoreV2 & { beatmap: Beatmap & { checksum: string | null; }; user: UserCompact & { country: Country; cover: Cover; }; }; } interface BeatmapDifficultyAttributes { max_combo: number; star_rating: number; gamemode: GameMode; } interface OsuBeatmapDifficultyAttributes extends BeatmapDifficultyAttributes { gamemode: 'osu'; aim_difficulty: number; approach_rate: number; flashlight_difficulty: number; overall_difficulty: number; slider_factor: number; speed_difficulty: number; } interface TaikoBeatmapDifficultyAttributes extends BeatmapDifficultyAttributes { gamemode: 'taiko'; stamina_difficulty: number; rhythm_difficulty: number; colour_difficulty: number; approach_rate: number; great_hit_window: number; } interface FruitsBeatmapDifficultyAttributes extends BeatmapDifficultyAttributes { gamemode: 'fruits'; approach_rate: number; } interface ManiaBeatmapDifficultyAttributes extends BeatmapDifficultyAttributes { gamemode: 'mania'; great_hit_window: number; score_multiplier: number; } interface UpdateStream { display_name: string | null; id: number; is_featured: boolean; name: string; } interface Build { created_at: ISOTimestamp; display_version: string; id: number; update_stream: UpdateStream | null; users: number; version: string | null; } interface BuildVersions { next: Build | null; previous: Build | null; } interface ChangelogEntry { category: string; created_at: ISOTimestamp | null; github_pull_request_id: number | null; github_url: string | null; id: number | null; major: boolean; repository: string | null; title: string | null; type: string; url: string | null; } interface GithubUser { display_name: string; github_url: string | null; id: number | null; osu_username: string | null; user_id: number | null; user_url: string | null; } interface Channel { channel_id: number; name: string; description: string | null; icon: string | null; type: ChannelType; moderated: boolean; uuid: string | null; } interface ChatMessage { channel_id: number; content: string; is_action: boolean; message_id: number; sender_id: number; timestamp: ISOTimestamp; type: ChatMessageType; uuid: string | null; } interface ForumPost { created_at: ISOTimestamp; deleted_at: ISOTimestamp | null; edited_at: ISOTimestamp | null; edited_by_id: number | null; forum_id: number; id: number; topic_id: number; user_id: number; } interface ForumPostBody { html: string; raw: string; } interface ForumTopic { created_at: ISOTimestamp; deleted_at: ISOTimestamp | null; first_post_id: number; forum_id: number; id: number; is_locked: boolean; last_post_id: number; poll: ForumPoll | null; post_count: number; title: string; type: ForumTopicType; updated_at: ISOTimestamp; user_id: number; } interface ForumPoll { allow_vote_change: boolean; ended_at: ISOTimestamp | null; hide_incomplete_results: boolean; last_vote_at: ISOTimestamp | null; max_votes: number; options: ForumPollOptions[]; started_at: ISOTimestamp; title: { bbcode: string; html: string; }; total_vote_count: number; } interface ForumPollOptions { id: number; text: { bbcode: string; html: string; }; vote_count: number | null; } interface BeatmapsetDiscussion { beatmap_id: number | null; beatmapset_id: number | null; can_be_resolved: boolean; can_grant_kudosu: boolean; created_at: ISOTimestamp; deleted_at: ISOTimestamp | null; deleted_by_id: number | null; id: number; kudosu_denied: boolean; last_post_at: ISOTimestamp; message_type: DiscussionMessageType; parent_id: number | null; resolved: boolean; timestamp: number | null; updated_at: ISOTimestamp; user_id: number; } interface DiscussionPost { beatmapset_discussion_id: number; created_at: ISOTimestamp; deleted_at: ISOTimestamp | null; deleted_by_id: number | null; id: number; last_editor_id: number | null; message: string; system: boolean; updated_at: ISOTimestamp; user_id: number; } interface DiscussionVote { beatmapset_discussion_id: number; created_at: ISOTimestamp; id: number; score: number; updated_at: ISOTimestamp; user_id: number; } /** * Class that handles auth code grant flow related actions * * Documentation: {@link https://osujs.mario564.com/oauth/authorization-code-grant} */ declare class AuthCodeGrant extends Base$1 { private scopes; /** * @param clientId OAuth client ID * @param clientSecret OAuth client secret * @param redirectUri OAuth redirect URI * @param scopes An array of OAuth scopes * @param options.polyfillFetch In case developing with a Node.js version prior to 18, you need to pass a polyfill for the fetch API. Install `node-fetch` */ constructor(clientId: number, clientSecret: string, redirectUri: string, scopes: Scope[], options?: { polyfillFetch?: typeof polyfillFetch; }); /** * Gets a token * * Documentation: {@link https://osujs.mario564.com/oauth/authorization-code-grant} * @param code The string received after a user authorizes the app * @returns An API token */ requestToken(code: string): Promise<Token>; /** * Refreshes a token * * Documentation: {@link https://osujs.mario564.com/oauth/authorization-code-grant} * @param refreshToken The token used to refresh * @returns An API token */ refreshToken(refreshToken: string): Promise<Token>; } /** * Class that wraps all OAuth related endpoints * * Documentation: {@link https://osujs.mario564.com/oauth} */ declare class Auth extends Base$1 { /** * @param clientId OAuth client ID * @param clientSecret OAuth client secret * @param redirectUri OAuth redirect URI * @param options.polyfillFetch In case developing with a Node.js version prior to 18, you need to pass a polyfill for the fetch API. Install `node-fetch` */ constructor(clientId: number, clientSecret: string, redirectUri: string, options?: { polyfillFetch?: typeof polyfillFetch; }); /** * @param scopes An array of scopes * * Documentation: {@link https://osujs.mario564.com/oauth/authorization-code-grant} */ authorizationCodeGrant(scopes?: Scope[]): AuthCodeGrant; /** * Gets a token * * Documentation: {@link https://osujs.mario564.com/oauth/client-credentials-grant} * @param scopes An array of scopes * @returns An API token */ clientCredentialsGrant(scopes?: Scope[]): Promise<GuestToken>; /** * Revokes a token * * Documentation: {@link https://osujs.mario564.com/oauth/revoke-token} * @param accessToken Access token to revoke */ revokeToken(accessToken: string): Promise<void>; } interface Options { query?: Record<string, any>; body?: Record<string, any> | string; } interface LookupBeatmapOptions { query?: { /** A beatmap checksum */ checksum?: string; /** A beatmap file name */ filename?: string; /** ID of a beatmap */ id?: number; }; } interface GetBeatmapScoresOptions { query?: { /** Gamemode of the scores to return */ mode?: GameMode; }; } interface GetBeatmapTopNonLegacyScoresOptions { query?: { /** Set to true to only return legacy scores */ legacy_only?: boolean; /** Gamemode of the scores to return */ mode?: GameMode; }; } interface GetBeatmapsOptions { query?: { /** An array of beatmap IDs (can only take up to 50 IDs) */ ids?: number[]; }; } interface GetBeatmapAttributesOptions { body?: { /** Mods to apply (can be either the bitwise representation or an array of acronyms) */ mods?: number | Mod[]; /** Ruleset of the difficulty attributes. Only valid if it's the beatmap ruleset or the beatmap can be converted to the specified ruleset. Defaults to ruleset of the specified beatmap */ ruleset?: GameMode; /** The same as `ruleset` but in integer form */ ruleset_id?: number; }; } interface GetDiscussionBaseQuery { /** Max. number of results */ limit?: number; /** Search result page number */ page?: number; /** Sort posts by newest (`id_desc`) or oldest (`id_desc`) */ sort?: 'id_desc' | 'id_asc'; } interface GetDiscussionPostsOptions { query?: GetDiscussionBaseQuery & { /** ID of the beatmapset discussion */ beatmapset_discussion_id?: number; /** Post types */ types?: ('first' | 'reply' | 'system')[]; /** ID of the user to get posts from */ user?: number; }; } interface GetDiscussionVotesOptions { query?: GetDiscussionBaseQuery & { /** ID of the beatmapset discussion */ beatmapset_discussion_id?: number; /** ID of the user receiving the votes */ receiver?: number; /** `1` for up vote, `-1` for down vote */ score?: 1 | -1; /** ID of the user giving votes */ user?: number; }; } interface GetDiscussionsOptions { query?: GetDiscussionBaseQuery & { /** ID of the beatmap to get discussions from */ beatmap_id?: number; /** ID of the beatmapset to get discussions from */ beatmapset_id?: number; /** Specify beatmapset status */ beatmapset_status?: 'all' | 'ranked' | 'qualified' | 'disqualified' | 'never_qualified'; /** Specify message types, (unset for all) */ message_types?: DiscussionMessageType[]; /** Show only resolved issues? */ only_unresolved?: boolean; /** ID of the user (documentation doesn't specify about what) */ user?: number; }; } interface GetChangelogListingOptions { query?: { /** Minimum build version */ from?: string; /** Maximum build ID */ max_id?: number; /** Stream name to return builds from */ stream?: ChangelogStream; /** Maximum build version */ to?: string; /** Changelog entry format (returns both by default) */ message_formats?: ('html' | 'markdown')[]; }; } interface LookupChangelogBuildOptions { query?: { /** Unset to query by build version or stream name, or id to query by build ID */ key?: 'id'; /** Changelog entry format (returns both by default) */ message_formats?: ('html' | 'markdown')[]; }; } interface CreatePMOptions { body: { /** ID of the user to send a PM */ target_id: number; /** Message to send */ message: string; /** Is the message an action? */ is_action: boolean; /** Client side message identifier which will be sent back in response and websocket JSON */ uuid?: string; }; } interface CreatePMChannelOptions { body: { /** Message to send */ message?: string; /** Channel details */ channel?: { /** Channel name */ name?: string; /** Channel description */ description?: string; }; /** Target user ID */ target_id: number; }; } interface CreateAnnounceChannelOptions { body: { /** Message to send with the announcement */ message: string; /** Channel details */ channel: { /** Channel name */ name: string; /** Channel description */ description: string; }; /** Target user IDs */ target_ids: number[]; }; } interface GetCommentsOptions { query?: { /** Resource to get comments for */ commentable?: { /** Type of the resource */ type?: CommentableType; /** ID of the resource */ id?: number; }; /** Get replies of a specific comment ID */ parent_id?: number; /** Sort option */ sort?: CommentSort; }; } interface ReplyToTopicOptions { body: { /** Content of the reply */ body: string; }; } interface CreateTopicOptions { body: { /** Content of the topic */ body: string; /** ID of the forum to create the topic in */ forum_id: number; /** Title of the topic */ title: string; /** Create a poll with the topic? */ with_poll?: boolean; /** Poll details */ forum_topic_poll?: { /** Hide result (until voting period ends)? (Default: false) */ hide_results?: boolean; /** Length of the voting period in days. 0 means that the voting will never end (default: 0). This parameter is required if `hide_results` option is enabled */ length_days?: number; /** Max. number of votes each user can cast (default: 1) */ max_options?: number; /** Newline-separated list of voting options. BBCode is supported */ options: string; /** Title of the poll */ title: string; /** Can a user change their votes? (Default: false) */ vote_change?: boolean; }; }; } interface GetTopicOptions { query?: { /** Pagination cursor */ cursor_string?: string; /** Sort posts by */ sort?: 'id_asc' | 'id_desc'; /** Max. number of posts to be returned (caps at 50) */ limit?: number; /** First post ID to be returned with `sort` set to `id_asc`. This parameter is ignored if `cursor_string` is specified */ start?: number; /** First post ID to be returned with `sort` set to `id_desc`. This parameter is ignored if `cursor_string` is specified */ end?: number; }; } interface UpdateTopicOptions { body?: { /** Forum topic details */ forum_topic?: { /** Title of the topic */ topic_title?: string; }; }; } interface UpdatePostOptions { body: { /** Content of the post in BBCode format */ body: string; }; } interface SearchOptions { query?: { /** Search only users, only wiki pages or both */ mode?: 'all' | 'user' | 'wiki_page'; /** Query string to search */ query?: string; /** Page number */ page?: number; }; } interface GetPlaylistScoresOptions { query?: { /** Limit number of results */ limit?: number; /** Sort option */ sort?: MultiplayerScoresSort; /** Pagination cursor */ cursor_string?: string; }; } interface GetNewsListingOptions { query?: { /** Limit number of results */ limit?: number; /** Filter news posts by a specific year */ year?: number; /** Pagination cursor */ cursor_string?: string; }; } interface GetNewsPostOptions { query?: { /** Specify whether the query must be done with a news post ID (`id`) or a slug (unset value) */ key?: 'id'; }; } interface GetRankingOptions { query?: { /** Filter by country code (only available for type `performance`) */ country?: string; /** Show all users or friend ranking */ filter?: 'all' | 'friends'; /** ID of the spotlight (if type is `charts`) */ spotlight?: number; /** Filter ranking by specified mode variant (only available for type `performance`) */ variant?: string; }; } interface GetSelfOptions { urlParams?: { /** Gamemode of the profile to return */ mode: GameMode; }; } interface GetUserKodosuOptions { query?: { /** Limit number of results */ limit?: number; /** Pagination offset */ offset?: number; }; } interface GetUserScoresOptions { query?: { /** Limit number of results */ limit?: number; /** Pagination offset */ offset?: number; /** Gamemode of the scores to return */ mode?: GameMode; }; } interface GetUserRecentScoresOptions { query?: { /** Limit number of results */ limit?: number; /** Pagination offset */ offset?: number; /** Gamemode of the scores to return */ mode?: GameMode; /** Include failed scores? */ include_fails?: boolean | number; }; } interface GetUserBeatmapsOptions { query?: { /** Limit number of results */ limit?: number; /** Pagination offset */ offset?: number; }; } interface GetUserRecentActivityOptions { query?: { /** Limit number of results */ limit?: number; /** Pagination offset */ offset?: number; }; } interface GetUserOptions { urlParams?: { /** Gamemode of the profile to return */ mode?: GameMode; }; query?: { /** Specify if the `user` param is an `id` or a `username` */ key: 'id' | 'username'; }; } interface GetUsersOptions { query?: { /** An array of user IDs (can only take up to 50 IDs) */ ids?: number[]; /** Include `statistics_rulesets.variants`? */ include_variant_statistics?: boolean; }; } declare class Base<TPolyfillFetch extends typeof polyfillFetch | undefined = undefined> { protected accessToken: string; private fetch; private usingPolyfillFetch; constructor(accessToken: string, options?: { polyfillFetch?: TPolyfillFetch; }); protected request<T>(endpoint: string, method: 'POST' | 'GET' | 'PATCH' | 'DELETE', options?: Options & { returnNullOn404?: boolean; dontParseResp?: boolean; apiVersion?: string; }): Promise<T>; /** * Prevents a request done to the current API to throw an `OsuJSUnexpectedResponseError` error. * * Documentation: {@link https://osujs.mario564.com/current/safe-parse} */ safeParse<T extends Promise<any>>(request: T): Promise<SafeParse<Awaited<T>, TPolyfillFetch extends typeof polyfillFetch ? true : false>>; /** * Set a new access token to be used by the current client. * * Documentation: {@link https://osujs.mario564.com/current/set-access-token} */ setAccessToken(accessToken: string): void; } /** * Class that wraps all user related endpoints */ declare class Users<TPolyfillFetch extends typeof polyfillFetch | undefined = undefined> extends Base<TPolyfillFetch> { /** * @param accessToken OAuth access token * @param options.polyfillFetch In case developing with a Node.js version prior to 18, you need to pass a polyfill for the fetch API. Install `node-fetch` */ constructor(accessToken: string, options?: { polyfillFetch?: TPolyfillFetch; }); /** * Makes a GET request to the `me` endpoint (requires the `identify` scope) * * Documentation: {@link https://osujs.mario564.com/current/get-self} * @returns The user corresponding to the access token provided in the constructor of this class */ getSelf(options?: GetSelfOptions): Promise<UserExtended & { is_restricted: boolean; session_verified: boolean; statistics_rulesets: StatisticsRulesets; }>; /** * Makes a GET request to the `/users/{user}/kudosu` endpoint * * Documentation: {@link https://osujs.mario564.com/current/get-user-kudosu} * @param user ID of the user to get kudosu from * @param options * @returns An array containing the specified user's kudosu history */ getUserKudosu(user: number, options?: GetUserKodosuOptions): Promise<UserKudosuHistory[]>; /** * Makes a GET request to the `/users/{user}/recent_activity` endpoint * * Documentation: {@link https://osujs.mario564.com/current/get-user-recent-activity} * @param user ID of the user to get their recent activity from * @param options * @returns An array containing the specified user's recent activity (each event is a union, to discriminate, use the `type` key) */ getUserRecentActivity(user: number, options?: GetUserRecentActivityOptions): Promise<UserEvent[]>; private getUserScoresBase; /** * Makes a GET request to the `/users/{user}/scores/{type}` endpoint * * Documentation: {@link https://osujs.mario564.com/current/get-user-scores} * @param user ID of the user to get their scores * @param type Score type * @param options * @returns An array of the specified user's scores */ getUserScores: <T extends UserScoreType>(user: number, type: T, options?: (T extends "recent" ? GetUserRecentScoresOptions : GetUserScoresOptions) | undefined) => Promise<T extends "best" ? UserBestScore[] : UserScore[]>; /** * Makes a GET request to the `/users/{user}/scores/{type}` endpoint with the `x-api-version` header set to `20220705` * * Documentation: {@link https://osujs.mario564.com/current/get-user-scores} * @param user ID of the user to get their scores * @param type Score type * @param options * @returns An array of the specified user's scores */ getUserScoresV2: <T extends UserScoreType>(user: number, type: T, options?: (T extends "recent" ? GetUserRecentScoresOptions : GetUserScoresOptions) | undefined) => Promise<T extends "best" ? UserBestScoreV2[] : UserScoreV2[]>; /** * Makes a GET request to the `/users/{user}/beatmapsets/{type}` endpoint * * Documentation: {@link https://osujs.mario564.com/current/get-user-beatmaps} * @param user ID of the user to get their beatmapsets * @param type Type of beatmapsets to return * @param options * @returns An array of a user's beatmapsets */ getUserBeatmaps<T extends UserBeatmapsType>(user: number, type: T, options?: GetUserBeatmapsOptions): Promise<T extends 'most_played' ? BeatmapPlaycount[] : (Beatmapset & { beatmaps: (Beatmap & { checksum: string | null; })[]; })[]>; /** * Makes a GET request to the `/users/{user}/{mode?}` endpoint * * Documentation: {@link https://osujs.mario564.com/current/get-user} * @param user ID or username of the user to get * @param options * @returns A user */ getUser(user: number | string, options?: GetUserOptions): Promise<UserExtended>; /** * Makes a GET request to the `/users` endpoint * * Documentation: {@link https://osujs.mario564.com/current/get-users} * @returns An array of users */ getUsers(options?: GetUsersOptions): Promise<(UserCompact & { country: Country; cover: Cover; groups: UserGroup[]; statistics_rulesets: StatisticsRulesets; })[]>; } /** * Class that wraps all wiki related endpoints */ declare class Wiki<TPolyfillFetch extends typeof polyfillFetch | undefined = undefined> extends Base<TPolyfillFetch> { /** * @param accessToken OAuth access token * @param options.polyfillFetch In case developing with a Node.js version prior to 18, you need to pass a polyfill for the fetch API. Install `node-fetch` */ constructor(accessToken: string, options?: { polyfillFetch?: TPolyfillFetch; }); /** * Makes a GET request to the `/wiki/{locale}/{path}` endpoint * * Documentation: {@link https://osujs.mario564.com/current/get-wiki-page} * @param locale Two-letter language code of the wiki page * @param path Path to the wiki page * @returns The wiki page */ getWikiPage(locale: string, path: string): Promise<WikiPage>; } /** * Class that wraps all comment related en