├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── api ├── v1 │ ├── form │ │ ├── beatmap │ │ │ ├── category.ts │ │ │ ├── creator.ts │ │ │ └── scores.ts │ │ ├── match.ts │ │ └── user │ │ │ ├── best.ts │ │ │ ├── details.ts │ │ │ └── recent.ts │ └── routes │ │ ├── beatmap │ │ ├── creator.ts │ │ ├── diff.ts │ │ ├── scores.ts │ │ └── set.ts │ │ ├── match.ts │ │ └── user │ │ ├── details.ts │ │ └── scores-category.ts └── v2 │ ├── assets_backgrounds.ts │ ├── assets_dataFiles.ts │ ├── beatmaps_actions.ts │ ├── beatmaps_details.ts │ ├── beatmaps_discussions_list.ts │ ├── beatmaps_discussions_posts.ts │ ├── beatmaps_discussions_votes.ts │ ├── beatmaps_download.ts │ ├── beatmaps_events_list.ts │ ├── beatmaps_lookup.ts │ ├── beatmaps_packs_details.ts │ ├── beatmaps_packs_list.ts │ ├── changelogs_details.ts │ ├── changelogs_list.ts │ ├── chat_actions.ts │ ├── chat_channels_list.ts │ ├── chat_details.ts │ ├── chat_list.ts │ ├── chat_messages.ts │ ├── chat_updates.ts │ ├── comments_actions.ts │ ├── comments_details.ts │ ├── comments_list.ts │ ├── forums_details.ts │ ├── forums_list.ts │ ├── forums_topics_actions.ts │ ├── forums_topics_details.ts │ ├── forums_topics_list.ts │ ├── groups_details.ts │ ├── groups_history.ts │ ├── matches_details.ts │ ├── matches_list.ts │ ├── me_details.ts │ ├── me_download_quota.ts │ ├── me_friends.ts │ ├── news_details.ts │ ├── news_list.ts │ ├── notifications_actions.ts │ ├── notifications_list.ts │ ├── ranking_list.ts │ ├── rooms_details.ts │ ├── rooms_leaderboard.ts │ ├── rooms_list.ts │ ├── rooms_scores.ts │ ├── scores_details.ts │ ├── scores_download.ts │ ├── scores_list.ts │ ├── search.ts │ ├── session_actions.ts │ ├── spotlights_list.ts │ ├── users_activity.ts │ ├── users_beatmaps.ts │ ├── users_details.ts │ ├── users_events.ts │ ├── users_kudosu.ts │ ├── users_list.ts │ ├── users_lookup.ts │ └── wiki_details.ts ├── changes ├── 2.1.2.md ├── 2.5.0.md ├── 2.7.0.md └── 2.7.2.md ├── index.ts ├── migration.md ├── package.json ├── routes ├── v1.ts └── v2.ts ├── tools ├── accuracy.ts ├── country.ts ├── index.ts ├── mods.ts ├── net-pp.ts ├── objects.ts └── rank.ts ├── tsconfig.json ├── tslint.json ├── types ├── enums.ts ├── index.ts ├── mods.ts ├── tools.ts └── v2 │ ├── assets_backgrounds.ts │ ├── assets_datafiles.ts │ ├── beatmaps_details_difficulty.ts │ ├── beatmaps_details_set.ts │ ├── beatmaps_discussions_list.ts │ ├── beatmaps_discussions_posts.ts │ ├── beatmaps_discussions_votes.ts │ ├── beatmaps_download.ts │ ├── beatmaps_events_list.ts │ ├── beatmaps_lookup_attributes.ts │ ├── beatmaps_lookup_difficulties.ts │ ├── beatmaps_lookup_difficulty.ts │ ├── beatmaps_lookup_set.ts │ ├── beatmaps_packs_details.ts │ ├── beatmaps_packs_list.ts │ ├── changelogs_details.ts │ ├── changelogs_list_all.ts │ ├── changelogs_list_lookup.ts │ ├── chat_actions_join.ts │ ├── chat_actions_keepalive.ts │ ├── chat_actions_new.ts │ ├── chat_actions_send.ts │ ├── chat_channels_list.ts │ ├── chat_details.ts │ ├── chat_list.ts │ ├── chat_messages.ts │ ├── chat_updates.ts │ ├── comments_actions_delete.ts │ ├── comments_actions_edit.ts │ ├── comments_actions_new.ts │ ├── comments_actions_unvote.ts │ ├── comments_actions_vote.ts │ ├── comments_details.ts │ ├── comments_list.ts │ ├── forums_details.ts │ ├── forums_list.ts │ ├── forums_topics_actions_create.ts │ ├── forums_topics_actions_edit_post.ts │ ├── forums_topics_actions_edit_topic.ts │ ├── forums_topics_actions_reply.ts │ ├── forums_topics_details.ts │ ├── forums_topics_list.ts │ ├── groups_details.ts │ ├── groups_history.ts │ ├── matches_detaIls.ts │ ├── matches_list.ts │ ├── me_details.ts │ ├── me_download_quota.ts │ ├── me_friends.ts │ ├── news_details.ts │ ├── news_list.ts │ ├── notifications_list.ts │ ├── ranking_list_charts.ts │ ├── ranking_list_country.ts │ ├── ranking_list_kudosu.ts │ ├── ranking_list_performance.ts │ ├── ranking_list_score.ts │ ├── rooms_details.ts │ ├── rooms_leaderboard.ts │ ├── rooms_list.ts │ ├── rooms_scores_all.ts │ ├── rooms_scores_single.ts │ ├── rooms_scores_user_highest.ts │ ├── scores_details.ts │ ├── scores_download.ts │ ├── scores_list_latest_ranked.ts │ ├── scores_list_leaderboard.ts │ ├── scores_list_user_beatmap_all.ts │ ├── scores_list_user_beatmap_best.ts │ ├── scores_list_user_best.ts │ ├── scores_list_user_firsts.ts │ ├── scores_list_user_pinned.ts │ ├── scores_list_user_recent.ts │ ├── scores_user_beamap.ts │ ├── search_all.ts │ ├── spotlights_list.ts │ ├── users_activity.ts │ ├── users_beatmaps.ts │ ├── users_details.ts │ ├── users_events.ts │ ├── users_kudosu.ts │ ├── users_list.ts │ ├── users_lookup.ts │ └── wiki_details.ts └── utility ├── auth.ts ├── handleErrors.ts ├── listeners.ts └── request.ts /.gitignore: -------------------------------------------------------------------------------- 1 | /test 2 | /dist 3 | /wiki 4 | /node_modules 5 | index.js 6 | package-lock.json 7 | .ts 8 | 1.ts -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /src 3 | /test 4 | .gitignore 5 | package-lock.json 6 | tsconfig.json 7 | tslint.json -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 cyperdark 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /api/v1/form/beatmap/scores.ts: -------------------------------------------------------------------------------- 1 | import { calculate_accuracy, calculate_mods } from "../../../../tools/index"; 2 | 3 | const name = (data: any, mode: any) => { 4 | const info = []; 5 | 6 | for (let i = 0; i < data.length; i++) { 7 | const d = data[i]; 8 | 9 | const score: any = { 10 | date: d.date, 11 | rank: d.rank, 12 | user: { 13 | id: +d.user_id, 14 | name: d.username, 15 | }, 16 | score: { 17 | id: +d.score_id, 18 | total: +d.score, 19 | }, 20 | combo: { 21 | max: +d.maxcombo, 22 | full: +d.perfect, 23 | }, 24 | hits: { 25 | 300: +d.count300, 26 | geki: +d.countgeki, 27 | 100: +d.count100, 28 | katu: +d.countkatu, 29 | 50: +d.count50, 30 | 0: +d.countmiss, 31 | }, 32 | mods: { 33 | id: +d.enabled_mods, 34 | name: calculate_mods(+(d.enabled_mods || '0')).name || '', 35 | }, 36 | accuracy: 0, 37 | pp: parseFloat(d.pp), 38 | replay: +d.replay_available, 39 | }; 40 | 41 | score.accuracy = calculate_accuracy(score.hits, mode).accuracy || 0; 42 | 43 | 44 | info.push(score); 45 | }; 46 | 47 | return info; 48 | }; 49 | 50 | export default name; -------------------------------------------------------------------------------- /api/v1/form/match.ts: -------------------------------------------------------------------------------- 1 | import { calculate_mods } from "../../../tools/index"; 2 | 3 | 4 | const modes = ['std', 'taiko', 'ctb', 'mania']; 5 | const scoring = ['Score', 'Accuracy', 'Combo', 'Score v2']; 6 | const team = ['Head to head', 'Tag Co-op', 'Team vs', 'Tag Team vs']; 7 | const teams = ['no team', 'blue', 'red']; 8 | 9 | const name = (data: any) => { 10 | const match: any = { 11 | match: { 12 | id: +data.match.match_id, 13 | name: data.match.name, 14 | time: { 15 | start: data.match.start_time, 16 | end: data.match.end_time, 17 | }, 18 | }, 19 | games: [], 20 | }; 21 | 22 | for (let i = 0; i < data.games.length; i++) { 23 | const g = data.games[i]; 24 | const game: any = { 25 | id: +g.game_id, 26 | time: { 27 | start: g.start_time, 28 | end: g.end_time, 29 | }, 30 | beatmap_id: +g.beatmap_id, 31 | mode: { 32 | id: +g.play_mode, 33 | name: modes[+g.play_mode], 34 | }, 35 | types: { 36 | match: g.match_type, 37 | scoring: { 38 | id: +g.scoring_type, 39 | name: scoring[+g.scoring_type], 40 | }, 41 | team: { 42 | id: +g.team_type, 43 | name: team[+g.team_type], 44 | }, 45 | }, 46 | mods: { 47 | id: +g.mods, 48 | name: calculate_mods(+(g.mods || '0')).name || '', 49 | }, 50 | scores: [], 51 | }; 52 | 53 | for (let s = 0; s < g.scores.length; s++) { 54 | const ss = g.scores[s]; 55 | 56 | const score: any = { 57 | team: { 58 | id: +ss.team, 59 | name: teams[+ss.team], 60 | }, 61 | slot: +ss.slot, 62 | user: { 63 | id: +ss.user_id, 64 | }, 65 | score: +ss.score, 66 | combo: { 67 | max: +ss.maxcombo, 68 | perfect: +ss.perfect, 69 | }, 70 | hits: { 71 | 300: +ss.count300, 72 | geki: +ss.countgeki, 73 | 100: +ss.count100, 74 | katu: +ss.countkatu, 75 | 50: +ss.count50, 76 | 0: +ss.countmiss, 77 | }, 78 | mods: { 79 | id: +ss.enabled_mods, 80 | name: calculate_mods(+(ss.enabled_mods || '0')).name || '', 81 | }, 82 | rank: g.rank, 83 | pass: g.pass, 84 | }; 85 | game.scores.push(score); 86 | }; 87 | 88 | match.games.push(game); 89 | }; 90 | 91 | return match; 92 | }; 93 | 94 | 95 | export default name; -------------------------------------------------------------------------------- /api/v1/form/user/best.ts: -------------------------------------------------------------------------------- 1 | import { calculate_accuracy, calculate_mods } from "../../../../tools/index"; 2 | 3 | 4 | const name = (data: any, mode: any) => { 5 | const info = []; 6 | 7 | for (let i = 0; i < data.length; i++) { 8 | const d = data[i]; 9 | 10 | const score: any = { 11 | date: d.date, 12 | beatmap: +d.beatmap_id, 13 | rank: d.rank, 14 | user: { 15 | id: +d.user_id, 16 | }, 17 | score: { 18 | id: +d.score_id, 19 | total: +d.score, 20 | }, 21 | combo: { 22 | max: +d.maxcombo, 23 | full: +d.perfect, 24 | }, 25 | hits: { 26 | 300: +d.count300, 27 | geki: +d.countgeki, 28 | 100: +d.count100, 29 | katu: +d.countkatu, 30 | 50: +d.count50, 31 | 0: +d.countmiss, 32 | }, 33 | mods: { 34 | id: +d.enabled_mods, 35 | name: calculate_mods(+(d.enabled_mods || '0')).name || '', 36 | }, 37 | accuracy: 0, 38 | pp: parseFloat(d.pp), 39 | replay: +d.replay_available, 40 | }; 41 | 42 | score.accuracy = calculate_accuracy(score.hits, mode).accuracy || 0; 43 | 44 | info.push(score); 45 | }; 46 | 47 | return info; 48 | }; 49 | 50 | 51 | export default name; -------------------------------------------------------------------------------- /api/v1/form/user/details.ts: -------------------------------------------------------------------------------- 1 | import { country_details } from "../../../../tools/index"; 2 | 3 | 4 | const parse = (num: string | number, amount: number) => parseFloat(Number(num).toFixed(amount)) 5 | 6 | const name = (data: any) => { 7 | const events = data[0].events.map((d: any) => { 8 | return { 9 | display: { 10 | html: d.display_html, 11 | pure: d.display_html.replace(/<[^>]*>?/gm, '').trim(), 12 | }, 13 | id: { 14 | diff: +d.beatmap_id, 15 | set: +d.beatmapset_id, 16 | }, 17 | date: d.date, 18 | epicfactor: +d.epicfactor, 19 | }; 20 | }); 21 | 22 | const info: any = { 23 | id: +data[0].user_id, 24 | name: data[0].username, 25 | pp: parse(data[0].pp_raw, 2), 26 | acc: parse(data[0].accuracy, 2), 27 | lvl: parse(data[0].level, 2), 28 | join: data[0].join_date, 29 | country: { 30 | flag: `https://osu.ppy.sh/images/flags/${data[0].country}.png`, 31 | short: data[0].country, 32 | full: country_details(data[0].country).name || '', 33 | }, 34 | play: { 35 | count: +data[0].playcount, 36 | time: +data[0].total_seconds_played, 37 | }, 38 | hits: { 39 | 300: +data[0].count300, 40 | 100: +data[0].count100, 41 | 50: +data[0].count50, 42 | }, 43 | score: { 44 | total: +data[0].total_score, 45 | ranked: +data[0].ranked_score, 46 | }, 47 | rank: { 48 | global: +data[0].pp_rank, 49 | country: +data[0].pp_country_rank, 50 | }, 51 | ranks: { 52 | ssh: +data[0].count_rank_ssh, 53 | ss: +data[0].count_rank_ss, 54 | sh: +data[0].count_rank_sh, 55 | s: +data[0].count_rank_s, 56 | a: +data[0].count_rank_a, 57 | }, 58 | events, 59 | }; 60 | 61 | return info; 62 | }; 63 | 64 | export default name; -------------------------------------------------------------------------------- /api/v1/form/user/recent.ts: -------------------------------------------------------------------------------- 1 | import { calculate_accuracy, calculate_mods } from "../../../../tools/index"; 2 | 3 | 4 | const name = (data: any, mode: any) => { 5 | const info = []; 6 | 7 | for (let i = 0; i < data.length; i++) { 8 | const d = data[i]; 9 | 10 | const score: any = { 11 | date: d.date, 12 | beatmap: +d.beatmap_id, 13 | rank: d.rank, 14 | user: { 15 | id: +d.user_id, 16 | }, 17 | score: { 18 | total: +d.score, 19 | }, 20 | combo: { 21 | max: +d.maxcombo, 22 | full: +d.perfect, 23 | }, 24 | hits: { 25 | 300: +d.count300, 26 | geki: +d.countgeki, 27 | 100: +d.count100, 28 | katu: +d.countkatu, 29 | 50: +d.count50, 30 | 0: +d.countmiss, 31 | }, 32 | mods: { 33 | id: +d.enabled_mods, 34 | name: calculate_mods(+(d.enabled_mods || '0')).name || '', 35 | }, 36 | accuracy: 0, 37 | }; 38 | 39 | score.accuracy = calculate_accuracy(score.hits, mode).accuracy || 0; 40 | 41 | info.push(score); 42 | }; 43 | 44 | return info; 45 | }; 46 | 47 | 48 | export default name; -------------------------------------------------------------------------------- /api/v1/routes/beatmap/scores.ts: -------------------------------------------------------------------------------- 1 | import { request } from "../../../../utility/request"; 2 | import { calculate_mods } from "../../../../tools/index"; 3 | 4 | import form from "../../form/beatmap/scores"; 5 | import { handleErrors } from "../../../../utility/handleErrors"; 6 | 7 | const _mode = [ 8 | 'osu', 9 | 'taiko', 10 | 'fruits', 11 | 'mania', 12 | ]; 13 | 14 | 15 | export const description: any = { 16 | auth: 2, 17 | title: __filename, 18 | method: 'GET', 19 | description: 'Return scores from beatmap', 20 | params: [ 21 | { 22 | type: 'number', 23 | name: 'id', 24 | optional: false, 25 | description: 'id of the beatmap', 26 | }, 27 | { 28 | type: 'string', 29 | name: 'mode', 30 | optional: true, 31 | description: '\`\`\`osu\`\`\` or \`\`\`fruits\`\`\` or \`\`\`mania\`\`\` or \`\`\`taiko\`\`\`', 32 | }, 33 | { 34 | type: 'string', 35 | name: 'converted', 36 | optional: true, 37 | description: '\`\`\`0\`\`\` or \`\`\`1\`\`\`', 38 | }, 39 | { 40 | type: 'string', 41 | name: 'hash', 42 | optional: true, 43 | description: 'beatmap file hash', 44 | }, 45 | { 46 | type: 'string', 47 | name: 'limit', 48 | optional: true, 49 | description: 'Maximum number of results', 50 | }, 51 | { 52 | type: 'string/number', 53 | name: 'mods', 54 | optional: true, 55 | description: 'Name of the mods \`\`\`HDDT\`\`\` or mods number \`\`\`72\`\`\`', 56 | }, 57 | { 58 | type: 'string', 59 | name: 'since', 60 | optional: true, 61 | description: 'Return all beatmaps ranked or loved since this date. Must be a MySQL date. In UTC', 62 | }, 63 | ], 64 | }; 65 | 66 | export interface types { 67 | (id: number, obj?: { 68 | user?: string | number, type?: 'u' | 'id', 69 | mode?: 'osu' | 'fruits' | 'mania' | 'taiko', 70 | mods?: string | number, 71 | limit?: number, 72 | }): Promise; 73 | }; 74 | 75 | export interface response { 76 | date: string; 77 | rank: string; 78 | user: { 79 | id: number; 80 | name: string; 81 | }; 82 | score: { 83 | id: number; 84 | total: number; 85 | }; 86 | combo: { 87 | max: number; 88 | full: number; 89 | }; 90 | hits: number[]; 91 | mods: { 92 | id: number; 93 | name: string; 94 | }; 95 | accuracy: number; 96 | pp: number; 97 | replay: number; 98 | } 99 | 100 | 101 | 102 | const name: types = async (id, obj = {}) => { 103 | const params = { 104 | b: id, 105 | u: obj.user, 106 | m: _mode.indexOf(obj.mode), 107 | mods: calculate_mods(obj.mods || '').number, 108 | type: obj.type, 109 | limit: obj.limit, 110 | }; 111 | if (params.m == -1) delete params.m; 112 | 113 | const data = await request(`https://osu.ppy.sh/api/get_scores`, { 114 | method: 'GET', 115 | params: params, 116 | }); 117 | 118 | if (data.error) return handleErrors(new Error(data.error)); 119 | 120 | 121 | if (data.length == 0) return []; 122 | 123 | const format = form(data, obj.mode); 124 | return format; 125 | }; 126 | 127 | 128 | export default name; -------------------------------------------------------------------------------- /api/v1/routes/match.ts: -------------------------------------------------------------------------------- 1 | import { IError } from "../../../types"; 2 | import { handleErrors } from "../../../utility/handleErrors"; 3 | import { request } from "../../../utility/request"; 4 | import form from "../form/match"; 5 | 6 | 7 | 8 | export const description: any = { 9 | auth: 1, 10 | title: __filename, 11 | method: 'GET', 12 | description: 'Return match details', 13 | params: [ 14 | { 15 | type: 'string', 16 | name: 'id', 17 | optional: false, 18 | description: 'id of the user', 19 | }, 20 | ], 21 | }; 22 | 23 | type Response = response & IError; 24 | 25 | export interface types { 26 | (id: number): Promise; 27 | }; 28 | 29 | export interface response { 30 | match: { 31 | id: number; 32 | name: string; 33 | time: { 34 | start: string; 35 | end: string; 36 | }; 37 | }; 38 | games: { 39 | id: number; 40 | time: { 41 | start: string; 42 | end: string; 43 | }; 44 | beatmap_id: number; 45 | mode: { 46 | id: number; 47 | name: string; 48 | }; 49 | types: { 50 | match: number; 51 | scoring: { 52 | id: number; 53 | name: string; 54 | }; 55 | team: { 56 | id: number; 57 | name: string; 58 | }; 59 | }; 60 | mods: { 61 | id: number; 62 | name: string; 63 | }; 64 | scores: { 65 | team: { 66 | id: number; 67 | name: string; 68 | }; 69 | slot: number; 70 | user: { 71 | id: number; 72 | }; 73 | score: number; 74 | combo: { 75 | max: number; 76 | perfect: number; 77 | }; 78 | hits: number[]; 79 | mods: { 80 | id: number; 81 | name: string; 82 | }; 83 | rank: string; 84 | pass: string; 85 | }; 86 | }; 87 | } 88 | 89 | 90 | 91 | const name: types = async (id) => { 92 | const params = { mp: id }; 93 | 94 | const data = await request(`https://osu.ppy.sh/api/get_match`, { 95 | method: 'GET', 96 | params: params, 97 | }); 98 | if (data.error) return handleErrors(new Error(data.error)) as Response; 99 | 100 | 101 | if (data.match == 0 || !data.match) { 102 | return handleErrors(new Error('Match not found')) as Response; 103 | }; 104 | 105 | const format: response = form(data); 106 | return format as Response; 107 | }; 108 | 109 | 110 | export default name; -------------------------------------------------------------------------------- /api/v1/routes/user/details.ts: -------------------------------------------------------------------------------- 1 | import { IError } from "../../../../types"; 2 | import { handleErrors } from "../../../../utility/handleErrors"; 3 | import { request } from "../../../../utility/request"; 4 | import form from "../../form/user/details"; 5 | 6 | 7 | const _mode = [ 8 | 'osu', 9 | 'taiko', 10 | 'fruits', 11 | 'mania', 12 | ]; 13 | 14 | 15 | export const description: any = { 16 | auth: 1, 17 | title: __filename, 18 | method: 'GET', 19 | description: 'Return user details', 20 | params: [ 21 | { 22 | type: 'string', 23 | name: 'user', 24 | optional: false, 25 | description: 'id of the user', 26 | }, 27 | { 28 | type: 'string', 29 | name: 'mode', 30 | optional: true, 31 | description: '\`\`\`osu\`\`\` or \`\`\`fruits\`\`\` or \`\`\`mania\`\`\` or \`\`\`taiko\`\`\`', 32 | }, 33 | { 34 | type: 'string', 35 | name: 'type', 36 | optional: true, 37 | description: '\`\`\`u\`\`\` is a user_id or a username. Use string for usernames or \`\`\`id\`\`\` for user_ids', 38 | }, 39 | { 40 | type: 'string', 41 | name: 'event_days', 42 | optional: true, 43 | description: 'Max number of days between now and last event date. Range of 1-31. Optional, default value is 1', 44 | }, 45 | ], 46 | }; 47 | 48 | type Response = response[] & IError; 49 | 50 | export interface types { 51 | (user: string | number, obj?: { 52 | mode?: 'osu' | 'fruits' | 'mania' | 'taiko', 53 | type?: 'u' | 'id', 54 | event_days?: number 55 | }): Promise; 56 | }; 57 | 58 | export interface response { 59 | id: number; 60 | name: string; 61 | pp: number; 62 | acc: number; 63 | lvl: number; 64 | join: string; 65 | country: { 66 | flag: string; 67 | short: string; 68 | full: string; 69 | }; 70 | play: { 71 | count: number; 72 | time: number; 73 | }; 74 | hits: { 75 | 50: number; 76 | 100: number; 77 | 300: number; 78 | }; 79 | score: { 80 | total: number; 81 | ranked: number; 82 | }; 83 | rank: { 84 | global: number; 85 | country: number; 86 | }; 87 | ranks: { 88 | ssh: number; 89 | ss: number; 90 | sh: number; 91 | s: number; 92 | a: number; 93 | }; 94 | events: { 95 | display: { 96 | html: string; 97 | pure: string; 98 | }; 99 | id: { 100 | diff: number; 101 | set: number; 102 | }; 103 | date: string; 104 | epicfactor: number; 105 | }; 106 | } 107 | 108 | 109 | 110 | const name: types = async (user, obj = {}) => { 111 | const params = { 112 | u: user, 113 | m: _mode.indexOf(obj.mode), 114 | type: obj.type, 115 | event_days: obj.event_days, 116 | }; 117 | if (params.m == -1) delete params.m; 118 | 119 | 120 | const data = await request(`https://osu.ppy.sh/api/get_user`, { 121 | method: 'GET', 122 | params: params, 123 | }); 124 | if (data.error) return handleErrors(new Error(data.error)) as Response; 125 | if (data.length == 0) return handleErrors(new Error('User not found')) as Response; 126 | 127 | 128 | const format = form(data); 129 | return format; 130 | }; 131 | 132 | 133 | export default name; -------------------------------------------------------------------------------- /api/v1/routes/user/scores-category.ts: -------------------------------------------------------------------------------- 1 | import { handleErrors } from "../../../../utility/handleErrors"; 2 | import { request } from "../../../../utility/request"; 3 | import form_best from "../../form/user/best"; 4 | import form_recent from "../../form/user/recent"; 5 | 6 | 7 | const _mode = [ 8 | 'osu', 9 | 'taiko', 10 | 'fruits', 11 | 'mania', 12 | ]; 13 | 14 | 15 | export const description: any = { 16 | auth: 1, 17 | title: __filename, 18 | method: 'GET', 19 | description: 'Return scores from user for a specified type', 20 | params: [ 21 | { 22 | type: 'string', 23 | name: 'user', 24 | optional: false, 25 | description: 'id of the user', 26 | }, 27 | { 28 | type: 'string', 29 | name: 'mode', 30 | optional: true, 31 | description: '\`\`\`osu\`\`\` or \`\`\`fruits\`\`\` or \`\`\`mania\`\`\` or \`\`\`taiko\`\`\`', 32 | }, 33 | { 34 | type: 'string', 35 | name: 'type', 36 | optional: true, 37 | description: '\`\`\`u\`\`\` is a user_id or a username. Use string for usernames or \`\`\`id\`\`\` for user_ids', 38 | }, 39 | { 40 | type: 'string', 41 | name: 'event_days', 42 | optional: true, 43 | description: 'Max number of days between now and last event date. Range of 1-31. Optional, default value is 1', 44 | }, 45 | ], 46 | }; 47 | 48 | type Reponse = response[]; 49 | 50 | export interface types { 51 | (user: string | number, type: 'best' | 'recent', obj?: { 52 | mode?: 'osu' | 'fruits' | 'mania' | 'taiko', 53 | type?: 'u' | 'id', 54 | limit?: number, 55 | }): Promise; 56 | }; 57 | 58 | export interface response { 59 | date: string; 60 | beatmap: number; 61 | rank: string; 62 | user: { 63 | id: number; 64 | }; 65 | score: { 66 | id: number; 67 | total: number; 68 | }; 69 | combo: { 70 | max: number; 71 | full: number; 72 | }; 73 | hits: number[]; 74 | mods: { 75 | id: number; 76 | name: string; 77 | }; 78 | accuracy: number; 79 | pp: number; 80 | replay: number; 81 | } 82 | 83 | 84 | 85 | const name: types = async (user, type, obj = {}) => { 86 | const params = { 87 | u: user, 88 | m: _mode.indexOf(obj.mode), 89 | type: obj.type, 90 | limit: obj.limit, 91 | }; 92 | if (params.m == -1) delete params.m; 93 | 94 | const data = await request(`https://osu.ppy.sh/api/get_user_${type}`, { 95 | method: 'GET', 96 | params: params, 97 | }); 98 | 99 | if (data.error) return handleErrors(new Error(data.error)); 100 | 101 | 102 | if (data.length == 0) return []; 103 | 104 | if (type == 'best') { 105 | const format = form_best(data, obj.mode); 106 | return format; 107 | }; 108 | 109 | const format = form_recent(data, obj.mode); 110 | return format; 111 | }; 112 | 113 | 114 | export default name; -------------------------------------------------------------------------------- /api/v2/assets_backgrounds.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { BeatmapsetBackground, SeasonalBackgrounds } from "../../types/v2/assets_backgrounds"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | type params = ({ 8 | type: 'seasonal'; 9 | } | { 10 | type: 'beatmapset', 11 | set_id: number; 12 | }); 13 | 14 | type Response = 15 | T extends 'seasonal' 16 | ? Promise 17 | : T extends 'beatmapset' 18 | ? BeatmapsetBackground & IError 19 | : IError; 20 | 21 | 22 | export const assets_backgrounds = (params: T, addons?: IDefaultParams): Response => { 23 | if (params?.type == 'seasonal') { 24 | return request(`https://osu.ppy.sh/api/v2/seasonal-backgrounds`, { 25 | method: 'GET', 26 | addons, 27 | }) as Response; 28 | }; 29 | 30 | 31 | if (params?.type == 'beatmapset') { 32 | if (params.set_id == null) { 33 | return handleErrors(new Error('Specify beatmapset id')) as Response; 34 | }; 35 | 36 | 37 | return { 38 | cover: `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/cover.jpg`, 39 | "cover@2x": `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/cover@2x.jpg`, 40 | card: `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/card.jpg`, 41 | "card@2x": `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/card@2x.jpg`, 42 | list: `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/list.jpg`, 43 | "list@2x": `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/list@2x.jpg`, 44 | slimcover: `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/slimcover.jpg`, 45 | "slimcover@2x": `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/slimcover@2x.jpg`, 46 | raw: `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/raw.jpg`, 47 | fullsize: `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/fullsize.jpg`, 48 | } as Response; 49 | }; 50 | 51 | 52 | return handleErrors(new Error(`Unsupported type: ${(params as any)?.type}`)) as Response; 53 | }; -------------------------------------------------------------------------------- /api/v2/assets_dataFiles.ts: -------------------------------------------------------------------------------- 1 | import { IError } from "../../types"; 2 | import { AssetsDatafilesResponse } from "../../types/v2/assets_datafiles"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | type Response = AssetsDatafilesResponse & IError; 8 | 9 | 10 | export const assets_dataFiles = async (): Promise => { 11 | const data = await request(`https://data.ppy.sh/`, { 12 | method: 'GET', 13 | }); 14 | 15 | if (data.error) return handleErrors(new Error(data.error)) as Response; 16 | 17 | 18 | const array = data.split('\n') 19 | .filter((r: string) => r.includes(` r != null); 25 | 26 | 27 | return { files: array } as Response; 28 | }; -------------------------------------------------------------------------------- /api/v2/beatmaps_actions.ts: -------------------------------------------------------------------------------- 1 | import { request } from "../../utility/request"; 2 | import { IDefaultParams, IError } from "../../types"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | // import { postDataObject } from "../../tools"; 5 | 6 | 7 | type params = ({ 8 | type: 'favourite'; 9 | 10 | /** beatmap set id */ 11 | id: number; 12 | status: boolean; 13 | } | { 14 | type: 'tag'; 15 | 16 | /** beatmap id */ 17 | id: number; 18 | /** tag name */ 19 | name: string; 20 | status: boolean; 21 | }); 22 | 23 | 24 | type Response = 25 | T extends 'favourite' 26 | ? string & IError 27 | : T extends 'tag' 28 | ? string & IError 29 | : IError; 30 | 31 | 32 | export const beatmaps_actions = async (params: T, addons?: IDefaultParams): Promise> => { 33 | if (params.type == 'favourite' || params.type == 'tag') { 34 | return handleErrors(new Error(`currently osu! api does not support this action`)) as Response; 35 | }; 36 | 37 | // if (params.id == null) { 38 | // if (params.type == 'favourite') return handleErrors(new Error(`Specify beatmapset id`)) as Response; 39 | // return handleErrors(new Error(`Specify beatmap id`)) as Response; 40 | // }; 41 | 42 | 43 | // const object: any = {}; 44 | // let url = 'https://osu.ppy.sh/api/v2'; 45 | // let method = 'POST'; 46 | 47 | 48 | // switch (params.type) { 49 | // case 'favourite': { 50 | // url += `/beatmapsets/${params.id}/favourites`; 51 | // object['action'] = params.status == true ? 'favourite' : 'unfavourite'; 52 | // break; 53 | // }; 54 | 55 | // case 'tag': { 56 | // if (params.name == null || params.name == '') return handleErrors(new Error(`Specify tag name`)) as Response; 57 | 58 | // url += `/beatmaps/${params.id}/tags/${params.name}`; 59 | // method = params.status == true ? 'PUT' : 'DELETE'; 60 | // break; 61 | // } 62 | 63 | // default: 64 | // return handleErrors(new Error(`Unsupported type: ${(params as any).type}`)) as Response; 65 | // }; 66 | 67 | 68 | // const data = await request(url, { 69 | // method: method, 70 | // params: object, 71 | // addons, 72 | // }); 73 | // if (data.error) return handleErrors(new Error(data.error)) as Response; 74 | 75 | 76 | // return data as Response; 77 | }; -------------------------------------------------------------------------------- /api/v2/beatmaps_details.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { beatmaps_details_difficulty_response } from "../../types/v2/beatmaps_details_difficulty"; 3 | import { beatmaps_details_set_response } from "../../types/v2/beatmaps_details_set"; 4 | import { handleErrors } from "../../utility/handleErrors"; 5 | import { request } from "../../utility/request"; 6 | 7 | 8 | type params = ({ 9 | type: 'difficulty'; 10 | id: number; 11 | } | { 12 | type: 'set'; 13 | id: number; 14 | }); 15 | 16 | 17 | type Response = 18 | T extends 'difficulty' 19 | ? beatmaps_details_difficulty_response & IError 20 | : T extends 'set' 21 | ? beatmaps_details_set_response & IError 22 | : IError; 23 | 24 | 25 | export const beatmaps_details = async (params: T, addons?: IDefaultParams): Promise> => { 26 | if (params.id == null) { 27 | return handleErrors(new Error(`Specify ${params.type} id`)) as Response; 28 | }; 29 | 30 | 31 | const object: any = {}; 32 | let url = 'https://osu.ppy.sh/api/v2'; 33 | let method = 'GET'; 34 | 35 | 36 | switch (params.type) { 37 | case 'difficulty': 38 | url += `/beatmaps/${params.id}`; 39 | break; 40 | 41 | case 'set': 42 | url += `/beatmapsets/${params.id}`; 43 | break; 44 | 45 | default: 46 | return handleErrors(new Error(`Unsupported type: ${(params as any).type}`)) as Response; 47 | }; 48 | 49 | 50 | const data = await request(url, { 51 | method: method, 52 | params: object, 53 | addons 54 | }); 55 | 56 | if (data.error) return handleErrors(new Error(data.error)) as Response; 57 | 58 | 59 | return data as Response; 60 | }; -------------------------------------------------------------------------------- /api/v2/beatmaps_discussions_list.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { BeatmapsDiscussionsListResponse } from "../../types/v2/beatmaps_discussions_list"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | 8 | export const beatmaps_discussions_list = async (params: { 9 | only_unresolved?: boolean; 10 | user?: number; 11 | beatmap_id?: number; 12 | beatmapset_id?: number; 13 | beatmapset_status?: 'all' | 'ranked' | 'qualified' | 'disqualified' | 'never_qualified' | 'loved'; 14 | message_types?: ('suggestion' | 'problem' | 'mapper_note' | 'praise' | 'hype' | 'review' | 'all')[]; 15 | limit?: number; 16 | sort?: 'id_desc' | 'id_asc'; 17 | cursor_string?: string; 18 | }, addons?: IDefaultParams): Promise => { 19 | const data = await request(`https://osu.ppy.sh/api/v2/beatmapsets/discussions`, { 20 | method: 'GET', 21 | params, 22 | addons 23 | }); 24 | 25 | if (data.error) return handleErrors(new Error(data.error)); 26 | 27 | 28 | return data; 29 | }; -------------------------------------------------------------------------------- /api/v2/beatmaps_discussions_posts.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { BeatmapsDiscussionsPostsResponse } from "../../types/v2/beatmaps_discussions_posts"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | 8 | export const beatmaps_discussions_posts = async (params: { 9 | discussion_id?: number; 10 | sort?: 'id_desc' | 'id_asc'; 11 | types?: ('first' | 'reply' | 'system')[]; 12 | user?: number; 13 | 14 | limit?: number; 15 | cursor_string?: string; 16 | }, addons?: IDefaultParams): Promise => { 17 | if (params?.discussion_id) { 18 | // @ts-ignore 19 | params.beatmapset_discussion_id = params.discussion_id; 20 | delete params.discussion_id; 21 | }; 22 | 23 | if (Array.isArray(params?.types)) { 24 | // @ts-ignore 25 | params['types[]'] = params.types; 26 | delete params.types; 27 | }; 28 | 29 | 30 | const data = await request(`https://osu.ppy.sh/api/v2/beatmapsets/discussions/posts`, { 31 | method: 'GET', 32 | params, 33 | addons 34 | }); 35 | 36 | if (data.error) return handleErrors(new Error(data.error)); 37 | 38 | return data; 39 | }; -------------------------------------------------------------------------------- /api/v2/beatmaps_discussions_votes.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { BeatmapsDiscussionsVotesResponse } from "../../types/v2/beatmaps_discussions_votes"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | 8 | export const beatmaps_discussions_votes = async (params: { 9 | discussion_id?: number; 10 | sort?: 'id_desc' | 'id_asc'; 11 | score?: '1' | '-1'; 12 | 13 | user?: number; 14 | receiver?: number; 15 | 16 | limit?: number; 17 | cursor_string?: string; 18 | }, addons?: IDefaultParams): Promise => { 19 | if (params?.discussion_id) { 20 | // @ts-ignore 21 | params.beatmapset_discussion_id = params.discussion_id; 22 | delete params.discussion_id; 23 | }; 24 | 25 | 26 | const data = await request(`https://osu.ppy.sh/api/v2/beatmapsets/discussions/votes`, { 27 | method: 'GET', 28 | params, 29 | addons 30 | }); 31 | 32 | if (data.error) return handleErrors(new Error(data.error)); 33 | 34 | return data; 35 | }; -------------------------------------------------------------------------------- /api/v2/beatmaps_events_list.ts: -------------------------------------------------------------------------------- 1 | import { BeatmapsEvents } from "../../types/v2/beatmaps_events_list"; 2 | import { IDefaultParams, IError, beatmap_events_types } from "../../types"; 3 | import { request } from "../../utility/request"; 4 | import { handleErrors } from "../../utility/handleErrors"; 5 | 6 | 7 | 8 | export const beatmaps_events_list = async (obj: { 9 | user: string | number, 10 | types: (beatmap_events_types)[]; 11 | min_date: string; 12 | max_date: string; 13 | }, addons?: IDefaultParams): Promise => { 14 | let url = 'https://osu.ppy.sh/api/v2/beatmapsets/events'; 15 | 16 | 17 | const data = await request(url, { 18 | method: 'GET', 19 | params: obj, 20 | addons 21 | }); 22 | 23 | if (data.error) return handleErrors(new Error(data.error)); 24 | 25 | return data; 26 | }; -------------------------------------------------------------------------------- /api/v2/beatmaps_packs_details.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { beatmaps_packs_details_response } from "../../types/v2/beatmaps_packs_details"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | type Response = beatmaps_packs_details_response & IError; 8 | 9 | 10 | export const beatmap_packs_details = async (pack_tag: string, addons?: IDefaultParams): Promise => { 11 | if (pack_tag == null) { 12 | return handleErrors(new Error('Specify beatmap pack tag')) as Response; 13 | }; 14 | 15 | 16 | const data = await request(`https://osu.ppy.sh/api/v2/beatmaps/packs/${pack_tag}`, { 17 | method: 'GET', 18 | addons, 19 | }); 20 | 21 | if (data.error) return handleErrors(new Error(data.error)); 22 | 23 | return data; 24 | }; -------------------------------------------------------------------------------- /api/v2/beatmaps_packs_list.ts: -------------------------------------------------------------------------------- 1 | import { IBeatmapPackType, IDefaultParams, IError } from "../../types"; 2 | import { BeatmapsPacksListResponse } from "../../types/v2/beatmaps_packs_list"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | type Response = BeatmapsPacksListResponse & IError; 8 | 9 | 10 | export const beatmaps_packs_list = async (params: { 11 | type: IBeatmapPackType; 12 | cursor_string?: string; 13 | }, addons?: IDefaultParams): Promise => { 14 | const data = await request(`https://osu.ppy.sh/api/v2/beatmaps/packs`, { 15 | method: 'GET', 16 | params, 17 | addons, 18 | }); 19 | 20 | if (data.error) return handleErrors(new Error(data.error)); 21 | 22 | return data; 23 | }; -------------------------------------------------------------------------------- /api/v2/changelogs_details.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { changelogsDetailsResponse } from "../../types/v2/changelogs_details"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | type Response = changelogsDetailsResponse[] & IError; 8 | 9 | 10 | export const changelogs_details = async (params: { 11 | stream_name: 'stable40' | 'beta40' | 'cuttingedge' | 'lazer' | 'web'; 12 | build_version: string; 13 | }, addons?: IDefaultParams): Promise => { 14 | if (params?.stream_name == null) { 15 | return handleErrors(new Error(`Specify stream name`)) as Response; 16 | }; 17 | 18 | if (params?.build_version == null) { 19 | return handleErrors(new Error(`Specify build version`)) as Response; 20 | }; 21 | 22 | 23 | const data = await request(`https://osu.ppy.sh/api/v2/changelog/${params.stream_name}/${params.build_version}`, { 24 | method: 'GET', 25 | addons, 26 | }); 27 | 28 | if (data.error) return handleErrors(new Error(data.error)); 29 | 30 | return data; 31 | }; -------------------------------------------------------------------------------- /api/v2/changelogs_list.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { ChangelogsListAllResponse } from "../../types/v2/changelogs_list_all"; 3 | import { ChangelogsListLookupResponse } from "../../types/v2/changelogs_list_lookup"; 4 | import { handleErrors } from "../../utility/handleErrors"; 5 | import { request } from "../../utility/request"; 6 | 7 | 8 | type params = ({ 9 | type: 'all'; 10 | from_build?: string; 11 | to_build?: string; 12 | 13 | stream_name?: 'stable40' | 'beta40' | 'cuttingedge' | 'lazer' | 'web'; 14 | max_id?: string; 15 | 16 | message_formats?: ('html' | 'markdown')[]; 17 | } | { 18 | type: 'lookup'; 19 | 20 | message_formats: ('html' | 'markdown')[]; 21 | changelog: 'stable40' | 'beta40' | 'cuttingedge' | 'lazer' | 'web'; 22 | key: string; 23 | }); 24 | 25 | 26 | type Response = 27 | T extends 'all' 28 | ? ChangelogsListAllResponse & IError 29 | : T extends 'lookup' 30 | ? ChangelogsListLookupResponse & IError 31 | : IError; 32 | 33 | 34 | export const changelogs_list = async (params: T, addons?: IDefaultParams) => { 35 | let object: any = {}; 36 | let url = 'https://osu.ppy.sh/api/v2'; 37 | let method = 'GET'; 38 | 39 | 40 | switch (params?.type) { 41 | case 'all': 42 | url += '/changelog'; 43 | 44 | if (params?.from_build != null) object.from = params.from_build; 45 | if (params?.to_build != null) object.to = params.to_build; 46 | 47 | if (params?.stream_name != null) object.stream = params.stream_name; 48 | if (params?.max_id != null) object.max_id = params.max_id; 49 | if (params?.message_formats != null) object['message_formats[]'] = params.message_formats; 50 | break; 51 | 52 | case 'lookup': 53 | url += `/changelog/${params.changelog}`; 54 | 55 | if (params?.changelog != null == null) { 56 | return handleErrors(new Error(`Specify changelog stream`)) as Response; 57 | }; 58 | 59 | 60 | if (params?.message_formats != null) object['message_formats[]'] = params.message_formats; 61 | if (params?.key != null) object['key'] = params.key; 62 | break; 63 | 64 | default: 65 | return handleErrors(new Error(`Unsupported type: ${(params as any)?.type}`)) as Response; 66 | }; 67 | 68 | 69 | const data = await request(url, { 70 | method: method, 71 | params: object, 72 | addons 73 | }); 74 | 75 | if (data.error) return handleErrors(new Error(data.error)) as Response; 76 | 77 | 78 | return data as Response; 79 | }; -------------------------------------------------------------------------------- /api/v2/chat_channels_list.ts: -------------------------------------------------------------------------------- 1 | import {IDefaultParams, IError} from "../../types"; 2 | import { chatChannelsListResponse } from "../../types/v2/chat_channels_list"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | 8 | export const chat_channels_list = async (addons?: IDefaultParams): Promise => { 9 | const data = await request(`https://osu.ppy.sh/api/v2/chat/channels`, { 10 | method: 'GET', 11 | addons, 12 | }); 13 | 14 | if (data.error) return handleErrors(new Error(data.error)); 15 | 16 | return data; 17 | }; -------------------------------------------------------------------------------- /api/v2/chat_details.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { ChatDetailsResponse } from "../../types/v2/chat_details"; 3 | import { credentials } from "../../utility/auth"; 4 | import { handleErrors } from "../../utility/handleErrors"; 5 | import { request } from "../../utility/request"; 6 | 7 | 8 | type Response = ChatDetailsResponse & IError; 9 | 10 | 11 | export const chat_details = async (params: { channel_id: number }, addons?: IDefaultParams): Promise => { 12 | if (credentials.type != 'lazer' && credentials.type != 'cli') { 13 | return handleErrors(new Error(`Login via lazer or cli to use this endpoint`)) as Response; 14 | }; 15 | 16 | if (credentials.type == 'cli' && !credentials.scopes.includes('chat.read')) { 17 | return handleErrors(new Error(`Requires "chat.read" scope`)) as Response; 18 | }; 19 | 20 | if (params?.channel_id == null) { 21 | return handleErrors(new Error(`Specify channel id`)) as Response; 22 | }; 23 | 24 | 25 | const data = await request(`https://osu.ppy.sh/api/v2/chat/channels/${params.channel_id}`, { 26 | method: 'GET', 27 | addons, 28 | }); 29 | 30 | if (data.error) return handleErrors(new Error(data.error)); 31 | 32 | return data; 33 | }; -------------------------------------------------------------------------------- /api/v2/chat_list.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { ChatListResponse } from "../../types/v2/chat_list"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | type Response = ChatListResponse[] & IError; 8 | 9 | 10 | export const chat_list = async (params: { 11 | unread?: boolean; 12 | sort?: 'date_desc' | 'date_asc'; 13 | }, addons?: IDefaultParams): Promise => { 14 | let data = await request(`https://osu.ppy.sh/api/v2/chat/presence/`, { 15 | method: 'GET', 16 | addons 17 | }); 18 | 19 | if (data.error) return handleErrors(new Error(data.error)); 20 | 21 | 22 | if (params?.sort == 'date_asc') 23 | data.sort((a: any, b: any) => a.last_message_id - b.last_message_id); 24 | else 25 | data.sort((a: any, b: any) => b.last_message_id - a.last_message_id); 26 | 27 | 28 | if (params?.unread == true) 29 | data = data.filter((r: any) => r.last_read_id != r.last_message_id); 30 | 31 | 32 | return data; 33 | }; -------------------------------------------------------------------------------- /api/v2/chat_messages.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { ChatMessagesResponse } from "../../types/v2/chat_messages"; 3 | import { credentials } from "../../utility/auth"; 4 | import { handleErrors } from "../../utility/handleErrors"; 5 | import { request } from "../../utility/request"; 6 | 7 | 8 | type Response = ChatMessagesResponse[] & IError; 9 | 10 | 11 | export const chat_messages = async (params: { 12 | channel_id: number; 13 | limit?: number; 14 | since?: number; 15 | until?: number; 16 | return_object?: boolean; 17 | }, addons?: IDefaultParams): Promise => { 18 | if (credentials.type != 'lazer' && credentials.type != 'cli') { 19 | return handleErrors(new Error(`Login via lazer or cli to use this endpoint`)) as Response; 20 | }; 21 | 22 | if (credentials.type == 'cli' && !credentials.scopes.includes('chat.read')) { 23 | return handleErrors(new Error(`Requires "chat.read" scope`)) as Response; 24 | }; 25 | 26 | if (params?.channel_id == null) { 27 | return handleErrors(new Error(`Specify channel id`)) as Response; 28 | }; 29 | 30 | 31 | const data = await request(`https://osu.ppy.sh/api/v2/chat/channels/${params.channel_id}/messages`, { 32 | method: 'GET', 33 | params, 34 | addons, 35 | }); 36 | 37 | if (data.error) return handleErrors(new Error(data.error)); 38 | 39 | return data; 40 | }; -------------------------------------------------------------------------------- /api/v2/chat_updates.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { ChatUpdatesResponse } from "../../types/v2/chat_updates"; 3 | import { credentials } from "../../utility/auth"; 4 | import { handleErrors } from "../../utility/handleErrors"; 5 | import { request } from "../../utility/request"; 6 | 7 | 8 | type Response = ChatUpdatesResponse & IError; 9 | 10 | 11 | export const chat_updates = async (params: { 12 | after_id: number; 13 | includes?: ('presence' | 'silences' | 'messages')[]; 14 | history_since?: number; 15 | }, addons?: IDefaultParams): Promise => { 16 | if (credentials.type != 'lazer') { 17 | return handleErrors(new Error(`Login via lazer to use this endpoint`)) as Response 18 | }; 19 | 20 | if (params?.after_id == null) { 21 | return handleErrors(new Error(`Specify after_id`)) as Response 22 | }; 23 | 24 | 25 | const obj: any = {}; 26 | if (params?.history_since) obj['history_since'] = params.history_since; 27 | if (params?.includes) obj['includes[]'] = params.includes; 28 | if (params?.after_id) obj['since'] = params.after_id; 29 | 30 | 31 | const data = await request(`https://osu.ppy.sh/api/v2/chat/updates`, { 32 | method: 'GET', 33 | params: obj, 34 | addons, 35 | }); 36 | 37 | 38 | if (data.error) return handleErrors(new Error(data.error)); 39 | return data; 40 | }; -------------------------------------------------------------------------------- /api/v2/comments_details.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { CommentsDetailsResponse } from "../../types/v2/comments_details"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | type Response = CommentsDetailsResponse & IError; 8 | 9 | 10 | export const comments_details = async (comment_id: string, addons?: IDefaultParams): Promise => { 11 | if (comment_id == null) { 12 | return handleErrors(new Error(`Specify comment id`)) as Response; 13 | }; 14 | 15 | 16 | const data = await request(`https://osu.ppy.sh/api/v2/comments/${comment_id}`, { 17 | method: 'GET', 18 | addons, 19 | }); 20 | 21 | if (data.error) return handleErrors(new Error(data.error)); 22 | 23 | 24 | return data; 25 | }; -------------------------------------------------------------------------------- /api/v2/comments_list.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { CommentsListResponse } from "../../types/v2/comments_list"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | type Response = CommentsListResponse & IError; 8 | 9 | 10 | export const comments_list = async (params: { 11 | type?: 'news_post' | 'beatmapset' | 'Build'; 12 | id?: string; 13 | 14 | parent_id?: string; 15 | after_id?: string; 16 | 17 | cursor?: { 18 | id: number; 19 | created_at: string; 20 | }; 21 | sort?: 'new' | 'old' | 'top'; 22 | }, addons?: IDefaultParams): Promise => { 23 | const data = await request(`https://osu.ppy.sh/api/v2/comments`, { 24 | method: 'GET', 25 | params: { 26 | after: params.after_id, 27 | commentable_type: params.type, 28 | commentable_id: params.id, 29 | 'cursor[id]': params.cursor?.id, 30 | 'cursor[created_at]': params.cursor?.created_at, 31 | parent_id: params.parent_id, 32 | sort: params.sort, 33 | }, 34 | addons, 35 | }); 36 | 37 | if (data.error) return handleErrors(new Error(data.error)); 38 | 39 | return data; 40 | }; -------------------------------------------------------------------------------- /api/v2/forums_details.ts: -------------------------------------------------------------------------------- 1 | import { request } from "../../utility/request"; 2 | import { IDefaultParams, IError } from "../../types"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { forums_details_response } from "../../types/v2/forums_details"; 5 | 6 | 7 | type Response = forums_details_response & IError; 8 | 9 | 10 | export async function forums_details(params: { 11 | id: number; 12 | }, addons?: IDefaultParams): Promise { 13 | if (params?.id == null) { 14 | return handleErrors(new Error(`Specify forum id`)) as Response; 15 | }; 16 | 17 | 18 | const data = await request(`https://osu.ppy.sh/api/v2/forums/${params.id}`, { 19 | method: 'GET', 20 | params: {}, 21 | addons, 22 | }); 23 | 24 | 25 | if (data.error) return handleErrors(new Error(data.error)); 26 | return data; 27 | }; -------------------------------------------------------------------------------- /api/v2/forums_list.ts: -------------------------------------------------------------------------------- 1 | import { request } from "../../utility/request"; 2 | import { IDefaultParams, IError } from "../../types"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { forums_list_response } from "../../types/v2/forums_list"; 5 | 6 | 7 | type Response = forums_list_response[] & IError; 8 | 9 | 10 | export async function forums_list(params?: { 11 | id: number; 12 | }, addons?: IDefaultParams): Promise { 13 | const data = await request(`https://osu.ppy.sh/api/v2/forums`, { 14 | method: 'GET', 15 | params: {}, 16 | addons, 17 | }); 18 | 19 | 20 | if (data.error) return handleErrors(new Error(data.error)); 21 | 22 | if (Array.isArray(data.forums)) return data.forums; 23 | return data; 24 | } -------------------------------------------------------------------------------- /api/v2/forums_topics_details.ts: -------------------------------------------------------------------------------- 1 | import { request } from "../../utility/request"; 2 | import { IDefaultParams, IError } from "../../types"; 3 | import { ForumsTopicsDetailsResponse } from "../../types/v2/forums_topics_details"; 4 | import { handleErrors } from "../../utility/handleErrors"; 5 | 6 | 7 | type Response = ForumsTopicsDetailsResponse & IError; 8 | 9 | 10 | export const forums_topics_details = async (params: { 11 | id: number 12 | 13 | start_id?: string, 14 | end_id?: string, 15 | 16 | limit?: number, 17 | sort?: 'id_asc' | 'id_desc', 18 | 19 | cursor_string?: string, 20 | }, addons?: IDefaultParams): Promise => { 21 | if (params?.id == null) { 22 | return handleErrors(new Error('Specify topic id')) as Response 23 | }; 24 | 25 | 26 | const data = await request(`https://osu.ppy.sh/api/v2/forums/topics/${params.id}`, { 27 | method: 'GET', 28 | params: { 29 | start: params.start_id, 30 | end: params.end_id, 31 | 32 | sort: params.sort, 33 | limit: params.limit, 34 | 35 | cursor_string: params.cursor_string, 36 | }, 37 | addons, 38 | }); 39 | 40 | if (data.error) return handleErrors(new Error(data.error)); 41 | 42 | 43 | return data; 44 | }; -------------------------------------------------------------------------------- /api/v2/forums_topics_list.ts: -------------------------------------------------------------------------------- 1 | import { request } from "../../utility/request"; 2 | import { IDefaultParams, IError } from "../../types"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { forums_topics_list_response } from "../../types/v2/forums_topics_list"; 5 | 6 | 7 | type Response = forums_topics_list_response & IError; 8 | 9 | 10 | export const forums_topics_list = async (params: { 11 | id: number 12 | 13 | sort?: 'new' | 'old', 14 | limit?: number; 15 | cursor_string?: string, 16 | }, addons?: IDefaultParams): Promise => { 17 | if (params?.id == null) { 18 | return handleErrors(new Error('Specify forum id')) as Response 19 | }; 20 | 21 | 22 | const data = await request(`https://osu.ppy.sh/api/v2/forums/topics`, { 23 | method: 'GET', 24 | params: { 25 | forum_id: params.id, 26 | sort: params.sort, 27 | limit: params.limit, 28 | cursor_string: params.cursor_string, 29 | }, 30 | addons, 31 | }); 32 | 33 | 34 | if (data.error) return handleErrors(new Error(data.error)); 35 | return data; 36 | }; -------------------------------------------------------------------------------- /api/v2/groups_details.ts: -------------------------------------------------------------------------------- 1 | import { request } from "../../utility/request"; 2 | import { IDefaultParams, IError } from "../../types"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { GroupsDetailsResponse } from "../../types/v2/groups_details"; 5 | 6 | 7 | type Response = GroupsDetailsResponse & IError; 8 | 9 | 10 | export const groups_details = async (params: { 11 | id: '4' | '7' | '11' | '16' | '22' | '28' | '31' | '32' 12 | }, addons?: IDefaultParams): Promise => { 13 | if (params?.id == null) { 14 | return handleErrors(new Error(`Specify group id`)) as Response; 15 | }; 16 | 17 | const data = await request(`https://osu.ppy.sh/groups/${params.id}`, { 18 | method: 'GET', 19 | addons 20 | }); 21 | 22 | if (data.error) return handleErrors(new Error(data.error)); 23 | 24 | 25 | try { 26 | const parse_group = JSON.parse(data.split('')[0]); 27 | const parse_users = JSON.parse(data.split('')[0]); 28 | 29 | 30 | parse_group.users = parse_users; 31 | return parse_group; 32 | } catch (error) { 33 | return handleErrors(error as any); 34 | }; 35 | }; -------------------------------------------------------------------------------- /api/v2/groups_history.ts: -------------------------------------------------------------------------------- 1 | import { request } from "../../utility/request"; 2 | import { IDefaultParams, IError } from "../../types"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { GroupsHistoryResponse } from "../../types/v2/groups_history"; 5 | 6 | 7 | type Response = GroupsHistoryResponse & IError; 8 | 9 | 10 | export const groups_history = async (params: { 11 | user?: string | number; 12 | group?: 'gmt' | 'nat' | 'dev' | 'alumni' | 'support' | 'bng' | 'loved' | 'bng_limited'; 13 | sort?: 'id_desc' | 'id_asc'; 14 | max_date?: string; 15 | min_date?: string; 16 | }, addons?: IDefaultParams): Promise => { 17 | const data = await request(`https://osu.ppy.sh/groups/history`, { 18 | method: 'GET', 19 | params, 20 | addons 21 | }); 22 | 23 | 24 | if (data.error) return handleErrors(new Error(data.error)); 25 | return data; 26 | }; -------------------------------------------------------------------------------- /api/v2/matches_details.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { MatchesDetailsResponse } from "../../types/v2/matches_detaIls"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | type Response = MatchesDetailsResponse & IError; 7 | 8 | export const matches_details = async ( 9 | params: { match_id: number; before?: number; after?: number; limit?: number }, 10 | addons?: IDefaultParams 11 | ): Promise => { 12 | if (params?.match_id == null) { 13 | return handleErrors(new Error("Specify match id")) as Response; 14 | } 15 | 16 | const data = await request(`https://osu.ppy.sh/api/v2/matches/${params.match_id}`, { 17 | method: "GET", 18 | params: { 19 | before: params.before, 20 | after: params.after, 21 | limit: params.limit != null ? Math.max(101, params.limit) : undefined, 22 | }, 23 | addons, 24 | }); 25 | 26 | if (data.error) return handleErrors(new Error(data.error)); 27 | 28 | return data; 29 | }; 30 | -------------------------------------------------------------------------------- /api/v2/matches_list.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { MatchesListResponse } from "../../types/v2/matches_list"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | type Response = MatchesListResponse & IError; 8 | 9 | 10 | export const matches_list = async (params: { 11 | limit?: number; 12 | sort?: 'id_desc' | 'id_asc', 13 | /** 14 | * Use cursor.match_id 15 | */ 16 | after_id: number; 17 | }, addons?: IDefaultParams): Promise => { 18 | const data = await request(`https://osu.ppy.sh/api/v2/matches`, { 19 | method: 'GET', 20 | params: { 21 | limit: params?.limit, 22 | sort: params?.sort, 23 | 'cursor[match_id]': params?.after_id, 24 | }, 25 | addons, 26 | }); 27 | 28 | if (data.error) return handleErrors(new Error(data.error)); 29 | 30 | 31 | return data; 32 | }; -------------------------------------------------------------------------------- /api/v2/me_details.ts: -------------------------------------------------------------------------------- 1 | import { credentials } from "../../utility/auth"; 2 | import { IDefaultParams, IError, Modes_names } from "../../types"; 3 | import { MeDetailsResponse } from "../../types/v2/me_details"; 4 | import { request } from "../../utility/request"; 5 | import { handleErrors } from "../../utility/handleErrors"; 6 | 7 | 8 | type Response = MeDetailsResponse & IError; 9 | 10 | 11 | export const me_details = async (params?: { mode?: Modes_names }, addons?: IDefaultParams): Promise => { 12 | if (credentials.type != 'lazer' && credentials.type != 'cli' && (addons?.authKey == null && addons?.authKey == '')) { 13 | return handleErrors(new Error('Login via lazer or cli to use this endpoint')) as Response 14 | }; 15 | 16 | 17 | let url = 'https://osu.ppy.sh/api/v2/me'; 18 | if (params?.mode) url += `/${params.mode}`; 19 | 20 | const data = await request(url, { 21 | method: 'GET', 22 | addons, 23 | }); 24 | 25 | if (data.error) return handleErrors(new Error(data.error)); 26 | 27 | 28 | return data; 29 | }; -------------------------------------------------------------------------------- /api/v2/me_download_quota.ts: -------------------------------------------------------------------------------- 1 | import { credentials } from "../../utility/auth"; 2 | import { IError, IDefaultParams } from "../../types"; 3 | import { MedownloadquotaResponse } from "../../types/v2/me_download_quota"; 4 | import { request } from "../../utility/request"; 5 | import { handleErrors } from "../../utility/handleErrors"; 6 | 7 | 8 | type Response = MedownloadquotaResponse & IError; 9 | 10 | 11 | export const me_download_quota = async (addons?: IDefaultParams): Promise => { 12 | if (credentials.type != 'lazer') { 13 | return handleErrors(new Error('Login via lazer to use this endpoint')) as Response 14 | }; 15 | 16 | 17 | const data = await request(`https://osu.ppy.sh/api/v2/me/download-quota-check`, { 18 | method: 'GET', 19 | addons, 20 | }); 21 | 22 | if (data.error) return handleErrors(new Error(data.error)); 23 | 24 | return data; 25 | }; -------------------------------------------------------------------------------- /api/v2/me_friends.ts: -------------------------------------------------------------------------------- 1 | import { credentials } from "../../utility/auth"; 2 | import { IDefaultParams, IError } from "../../types"; 3 | import { request } from "../../utility/request"; 4 | import { MeFriendsResponse } from "../../types/v2/me_friends"; 5 | import { handleErrors } from "../../utility/handleErrors"; 6 | 7 | 8 | type Response = MeFriendsResponse[] & IError; 9 | 10 | 11 | export const me_friends = async (addons?: IDefaultParams): Promise => { 12 | if (credentials.type != 'lazer' && credentials.type != 'cli') { 13 | return handleErrors(new Error('Login via lazer or cli to use this endpoint')) as Response 14 | }; 15 | 16 | if (credentials.type == 'cli' && !credentials.scopes.includes('friends.read')) { 17 | return handleErrors(new Error(`Requires "friends.read" scope`)) as Response 18 | }; 19 | 20 | 21 | const data = await request(`https://osu.ppy.sh/api/v2/friends`, { 22 | method: 'GET', 23 | addons, 24 | }); 25 | 26 | if (data.error) return handleErrors(new Error(data.error)); 27 | 28 | return data; 29 | }; -------------------------------------------------------------------------------- /api/v2/news_details.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { NewsDetailsResponse } from "../../types/v2/news_details"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | type Response = NewsDetailsResponse & IError; 8 | 9 | 10 | export const news_details = async (params: { 11 | news_id: string; 12 | key: 'id' | 'slug' | null; 13 | }, addons?: IDefaultParams): Promise => { 14 | if (params.news_id == null) { 15 | return handleErrors(new Error('Specify a query')) as Response 16 | }; 17 | 18 | 19 | const data = await request(`https://osu.ppy.sh/api/v2/news/${params.news_id}`, { 20 | method: 'GET', 21 | params: { key: (params.key === 'slug' ? undefined : params.key) }, 22 | addons, 23 | }); 24 | 25 | if (data.error) return handleErrors(new Error(data.error)); 26 | 27 | return data; 28 | }; -------------------------------------------------------------------------------- /api/v2/news_list.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { NewsListResponse } from "../../types/v2/news_list"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | type Response = NewsListResponse & IError; 8 | 9 | 10 | export const news_list = async (params: { 11 | from_year?: string; 12 | limit?: string; 13 | cursor_string?: string; 14 | } = {}, addons?: IDefaultParams): Promise => { 15 | const object: any = { 16 | year: params?.from_year, 17 | limit: params?.limit, 18 | cursor_string: params?.cursor_string, 19 | }; 20 | 21 | 22 | const data = await request(`https://osu.ppy.sh/api/v2/news`, { 23 | method: 'GET', 24 | params: object, 25 | addons, 26 | }); 27 | 28 | if (data.error) return handleErrors(new Error(data.error)); 29 | 30 | 31 | return data; 32 | }; -------------------------------------------------------------------------------- /api/v2/notifications_actions.ts: -------------------------------------------------------------------------------- 1 | import { request } from "../../utility/request"; 2 | import { IDefaultParams, IError } from "../../types"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | 5 | 6 | type params = ({ 7 | type: 'mark_as_read'; 8 | 9 | // ids: number[]; 10 | 11 | identities?: { 12 | category?: string; 13 | object_id?: string 14 | object_type?: string 15 | }[]; 16 | 17 | notifications?: { 18 | category?: string; 19 | id?: number; 20 | object_id?: string; 21 | object_type?: string; 22 | }[] 23 | }); 24 | 25 | 26 | type Response = 27 | T extends 'mark_as_read' 28 | ? "" & IError 29 | : IError; 30 | 31 | 32 | export const notifications_actions = async (params: T, addons?: IDefaultParams): Promise => { 33 | const object: any = {}; 34 | let url = 'https://osu.ppy.sh/api/v2'; 35 | let method = 'GET'; 36 | 37 | 38 | switch (params?.type) { 39 | case 'mark_as_read': 40 | url += '/notifications/mark-read'; 41 | method = 'POST'; 42 | 43 | if (!Array.isArray(params.notifications) && !Array.isArray(params.identities)) { 44 | return handleErrors(new Error(`Missing on of parameters`)) as Response; 45 | }; 46 | 47 | // params.ids.forEach((r, index) => object[`identities[${index}][id]`] = r); 48 | 49 | if (Array.isArray(params?.notifications)) { 50 | object['notifications'] = params.notifications; 51 | }; 52 | 53 | if (Array.isArray(params?.identities)) { 54 | object['identities'] = params.identities; 55 | }; 56 | break; 57 | 58 | default: 59 | return handleErrors(new Error(`Unsupported type: ${(params as any).type}`)) as Response; 60 | }; 61 | 62 | 63 | const data = await request(url, { 64 | method: method, 65 | data: JSON.stringify(object), 66 | addons, 67 | }); 68 | 69 | if (data.error) return handleErrors(new Error(data.error)) as Response; 70 | 71 | 72 | return data as Response; 73 | }; -------------------------------------------------------------------------------- /api/v2/notifications_list.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { NotificationsListResponse } from "../../types/v2/notifications_list"; 3 | import { credentials } from "../../utility/auth"; 4 | import { handleErrors } from "../../utility/handleErrors"; 5 | import { request } from "../../utility/request"; 6 | 7 | 8 | type Response = NotificationsListResponse & IError; 9 | 10 | 11 | export const notifications_list = async (params: { 12 | max_id: string; 13 | unread_only: boolean; 14 | }, addons?: IDefaultParams): Promise => { 15 | if (credentials.type != 'lazer') { 16 | return handleErrors(new Error(`Login via lazer to use this endpoint`)) as Response 17 | }; 18 | 19 | 20 | const data = await request(`https://osu.ppy.sh/api/v2/notifications`, { 21 | method: 'GET', 22 | params: { 23 | max_id: params?.max_id 24 | }, 25 | addons, 26 | }); 27 | if (data.error) return handleErrors(new Error(data.error)); 28 | 29 | 30 | if (params?.unread_only == true && !('error' in data)) 31 | data.notifications = data.notifications.filter((r: any) => r.is_read == false); 32 | 33 | return data; 34 | }; -------------------------------------------------------------------------------- /api/v2/rooms_details.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { RoomsDetailsResponse } from "../../types/v2/rooms_details"; 3 | import { credentials } from "../../utility/auth"; 4 | import { handleErrors } from "../../utility/handleErrors"; 5 | import { request } from "../../utility/request"; 6 | 7 | 8 | type Response = RoomsDetailsResponse & IError; 9 | 10 | 11 | export const rooms_details = async (params: { id: number | 'latest' }, addons?: IDefaultParams): Promise => { 12 | if (credentials.type != 'lazer' && credentials.type != 'cli') { 13 | return handleErrors(new Error(`Login via lazer or cli to use this endpoint`)) as Response; 14 | }; 15 | 16 | if (params.id == null) { 17 | return handleErrors(new Error(`Specify room id`)) as Response; 18 | }; 19 | 20 | 21 | const data = await request(`https://osu.ppy.sh/api/v2/rooms/${params.id}`, { 22 | method: 'GET', 23 | addons, 24 | }); 25 | 26 | if (data.error) return handleErrors(new Error(data.error)); 27 | 28 | 29 | return data; 30 | }; -------------------------------------------------------------------------------- /api/v2/rooms_leaderboard.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { RoomsLeaderboardResponse } from "../../types/v2/rooms_leaderboard"; 3 | import { credentials } from "../../utility/auth"; 4 | import { handleErrors } from "../../utility/handleErrors"; 5 | import { request } from "../../utility/request"; 6 | 7 | 8 | type Response = RoomsLeaderboardResponse & IError; 9 | 10 | 11 | export const rooms_leaderboard = async (params: { 12 | id: number; 13 | limit?: number; 14 | }, addons?: IDefaultParams): Promise => { 15 | if (credentials.type != 'lazer' && credentials.type != 'cli') { 16 | return handleErrors(new Error(`Login via lazer or cli to use this endpoint`)) as Response; 17 | }; 18 | 19 | if (params?.id == null) { 20 | return handleErrors(new Error(`Specify room id`)) as Response; 21 | }; 22 | 23 | 24 | const data = await request(`https://osu.ppy.sh/api/v2/rooms/${params.id}/leaderboard`, { 25 | method: 'GET', 26 | params: { limit: params?.limit }, 27 | addons, 28 | }); 29 | 30 | if (data.error) return handleErrors(new Error(data.error)); 31 | 32 | 33 | return data; 34 | }; -------------------------------------------------------------------------------- /api/v2/rooms_list.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { RoomsListResponse } from "../../types/v2/rooms_list"; 3 | import { credentials } from "../../utility/auth"; 4 | import { handleErrors } from "../../utility/handleErrors"; 5 | import { request } from "../../utility/request"; 6 | 7 | 8 | type Response = RoomsListResponse & IError; 9 | 10 | 11 | export const rooms_list = async (params: { 12 | type?: 'playlists' | 'realtime'; 13 | status?: 'all' | 'active' | 'ended' | 'participated' | 'owned'; 14 | 15 | query?: string; 16 | 17 | limit?: number; 18 | sort?: 'ended' | 'created'; 19 | 20 | cursor_string?: string; 21 | }, addons?: IDefaultParams): Promise => { 22 | if (credentials.type != 'lazer' && credentials.type != 'cli') { 23 | return handleErrors(new Error(`Login via lazer or cli to use this endpoint`)) as Response 24 | }; 25 | 26 | if (addons == null) 27 | addons = { apiVersion: '99999999' } 28 | 29 | 30 | let data = await request(`https://osu.ppy.sh/api/v2/rooms`, { 31 | method: 'GET', 32 | params: { 33 | type_group: params?.type, 34 | mode: params?.status, 35 | sort: params?.sort, 36 | limit: params?.limit, 37 | cursor_string: params?.cursor_string, 38 | }, 39 | addons, 40 | }); 41 | 42 | if (data.error) return handleErrors(new Error(data.error)); 43 | 44 | if (params?.query && !('error' in data)) { 45 | if (data.rooms) data.rooms = data.rooms.filter((r: any) => r.name.toLowerCase().includes(params?.query.trim().toLowerCase())) 46 | else data = data.filter((r: any) => r.name.toLowerCase().includes(params?.query.trim().toLowerCase())) 47 | }; 48 | 49 | 50 | return data; 51 | }; -------------------------------------------------------------------------------- /api/v2/rooms_scores.ts: -------------------------------------------------------------------------------- 1 | import { request } from "../../utility/request"; 2 | import { IDefaultParams, IError } from "../../types"; 3 | import { RoomsScoresSingleResponse } from "../../types/v2/rooms_scores_single"; 4 | import { RoomScoresUserHighestResponse } from "../../types/v2/rooms_scores_user_highest"; 5 | import { RoomsScoresAllResponse } from "../../types/v2/rooms_scores_all"; 6 | import { handleErrors } from "../../utility/handleErrors"; 7 | import { credentials } from "../../utility/auth"; 8 | 9 | 10 | type params = ({ 11 | type: 'all'; 12 | 13 | id: number; 14 | playlist_id: number; 15 | 16 | limit?: number; 17 | sort?: 'score_asc' | 'score_desc'; 18 | 19 | cursor_string?: string; 20 | } | { 21 | type: 'single'; 22 | 23 | id: number; 24 | playlist_id: number; 25 | score_id: number; 26 | } | { 27 | type: 'user_highest'; 28 | 29 | id: number; 30 | playlist_id: number; 31 | user_id: number; 32 | }); 33 | 34 | 35 | type Response = 36 | T extends 'all' 37 | ? RoomsScoresAllResponse & IError 38 | : T extends 'single' 39 | ? RoomsScoresSingleResponse & IError 40 | : T extends 'user_highest' 41 | ? RoomScoresUserHighestResponse & IError 42 | : IError; 43 | 44 | 45 | export const rooms_scores = async (params: T, addons?: IDefaultParams): Promise> => { 46 | if (credentials.type != 'lazer' && credentials.type != 'cli') { 47 | return handleErrors(new Error(`Login via lazer or cli to use this endpoint`)) as Response; 48 | }; 49 | 50 | 51 | let object: any = {}; 52 | let url = 'https://osu.ppy.sh/api/v2'; 53 | let method = 'GET'; 54 | 55 | 56 | if (params?.id == null) { 57 | return handleErrors(new Error(`Specify room id`)) as Response; 58 | }; 59 | 60 | if (params?.playlist_id == null) { 61 | return handleErrors(new Error(`Specify playlist id`)) as Response; 62 | }; 63 | 64 | 65 | switch (params?.type) { 66 | case 'all': 67 | url += `/rooms/${params.id}/playlist/${params.playlist_id}/scores`; 68 | 69 | if (params?.limit != null) object.limit = params.limit; 70 | if (params?.sort != null) object.sort = params.sort; 71 | if (params?.cursor_string != null) object.cursor_string = params.cursor_string; 72 | break; 73 | 74 | case 'single': 75 | url += `/rooms/${params.id}/playlist/${params.playlist_id}/scores/${params.score_id}`; 76 | 77 | break; 78 | 79 | case 'user_highest': 80 | url += `/rooms/${params.id}/playlist/${params.playlist_id}/scores/users/${params.user_id}`; 81 | 82 | break; 83 | 84 | default: 85 | return handleErrors(new Error(`Unsupported type: ${(params as any).type}`)) as Response; 86 | }; 87 | 88 | 89 | const data = await request(url, { 90 | method: method, 91 | params: object, 92 | addons, 93 | }); 94 | 95 | if (data.error) return handleErrors(new Error(data.error)) as Response; 96 | 97 | 98 | return data as Response; 99 | }; -------------------------------------------------------------------------------- /api/v2/scores_details.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError, Modes_names } from "../../types"; 2 | import { scores_details_response } from "../../types/v2/scores_details"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | type Response = scores_details_response & IError; 8 | 9 | 10 | export const scores_details = async (params: { 11 | id: number; 12 | mode?: Modes_names; 13 | }, addons?: IDefaultParams): Promise => { 14 | if (params?.id == null) { 15 | return handleErrors(new Error('Specify score id')) as Response; 16 | }; 17 | 18 | 19 | const url = params.mode ? `https://osu.ppy.sh/api/v2/scores/${params.mode}/${params.id}` : `https://osu.ppy.sh/api/v2/scores/${params.id}`; 20 | 21 | const data = await request(url, { 22 | method: 'GET', 23 | addons, 24 | }); 25 | 26 | if (data.error) return handleErrors(new Error(data.error)); 27 | 28 | 29 | return data; 30 | }; -------------------------------------------------------------------------------- /api/v2/scores_download.ts: -------------------------------------------------------------------------------- 1 | import { IError, Modes_names } from "../../types"; 2 | import { ScoresDownloadResponse } from "../../types/v2/scores_download"; 3 | import { credentials } from "../../utility/auth"; 4 | import { handleErrors } from "../../utility/handleErrors"; 5 | import { download } from "../../utility/request"; 6 | 7 | 8 | type Response = ScoresDownloadResponse & IError; 9 | 10 | 11 | export const scores_download = async (params: { 12 | id: number; 13 | mode?: Modes_names; 14 | file_path: string; 15 | }): Promise => { 16 | if (credentials.type != 'lazer' && credentials.type != 'cli') { 17 | return handleErrors(new Error(`Login via lazer or cli to use this endpoint`)) as Response; 18 | }; 19 | 20 | if (params?.id == null) { 21 | return handleErrors(new Error(`Specify score id`)) as Response; 22 | }; 23 | 24 | if (params?.file_path == null) { 25 | return handleErrors(new Error(`Specify file_path`)) as Response; 26 | }; 27 | 28 | 29 | const url = params.mode ? `https://osu.ppy.sh/api/v2/scores/${params.mode}/${params.id}` : `https://osu.ppy.sh/api/v2/scores/${params.id}`; 30 | 31 | const data = await download(`${url}/download`, params.file_path, { 32 | _callback: false, 33 | }); 34 | 35 | if (data.error) return handleErrors(new Error(data.error)); 36 | 37 | 38 | return data; 39 | }; -------------------------------------------------------------------------------- /api/v2/search.ts: -------------------------------------------------------------------------------- 1 | import { beatmap_category, beatmap_sorting, beatmap_statuses, Modes_names, beatmap_genres, beatmap_languages, beatmap_ranks, beatmap_extra, IDefaultParams, IError } from "../../types"; 2 | import { Genres_enum, Languages_enum, GamemodeEnum } from "../../types/enums"; 3 | import { SearchBeatmaps, SearchWiki } from '../../types/v2/search_all'; 4 | import { handleErrors } from "../../utility/handleErrors"; 5 | import { request } from "../../utility/request"; 6 | 7 | 8 | type params = ({ 9 | type: 'site'; 10 | location?: 'all' | 'user' | 'wiki_page'; 11 | query?: string; 12 | page?: number; 13 | } | { 14 | _played?: boolean; 15 | _nsfw?: boolean; 16 | 17 | type: 'beatmaps'; 18 | query?: string; 19 | mode?: Modes_names | number; 20 | status?: beatmap_statuses; 21 | category?: (beatmap_category)[]; 22 | 23 | genre?: beatmap_genres | number; 24 | language?: beatmap_languages | number; 25 | 26 | achieved_rank?: (beatmap_ranks)[]; 27 | 28 | extra?: (beatmap_extra)[]; 29 | sort?: beatmap_sorting; 30 | 31 | cursor_string?: string; 32 | }); 33 | 34 | type Response = 35 | T extends 'site' 36 | ? SearchWiki & IError 37 | : T extends 'beatmaps' 38 | ? SearchBeatmaps & IError 39 | : IError; 40 | 41 | 42 | export const search_all = async (params: T, addons?: IDefaultParams): Promise> => { 43 | const object: any = {}; 44 | let url = 'https://osu.ppy.sh/api/v2'; 45 | 46 | 47 | switch (params?.type) { 48 | case 'site': 49 | url += '/search'; 50 | 51 | 52 | if (params?.location != null) object.mode = params.location; 53 | if (params?.query != null) object.query = params.query; 54 | if (params?.page != null) object.page = params.page; 55 | break; 56 | 57 | case 'beatmaps': 58 | url += '/beatmapsets/search'; 59 | 60 | if (params?._played != null) object.played = params._played ? 'played' : 'unplayed'; 61 | if (params?._nsfw != null) object.nsfw = params._nsfw; 62 | 63 | if (params?.query != null) object.q = params.query; 64 | if (params?.mode != null) object.m = typeof params.mode == 'number' ? params.mode : GamemodeEnum[params.mode]; 65 | if (params?.status != null) object.s = params.status; 66 | if (params?.category != null) object.c = params.category.join('.'); 67 | 68 | if (params?.genre != null) object.g = typeof params.genre == 'number' ? params.genre : Genres_enum[params.genre]; 69 | if (params?.language != null) object.l = typeof params.language == 'number' ? params.language : Languages_enum[params.language]; 70 | 71 | if (params?.achieved_rank != null) object.r = params.achieved_rank.join('.'); 72 | 73 | if (params?.extra != null) object.e = params.extra.join('.'); 74 | 75 | if (params?.sort != null) object.sort = params.sort; 76 | if (params?.cursor_string != null) object.cursor_string = params.cursor_string; 77 | break; 78 | }; 79 | 80 | 81 | const data = await request(url, { 82 | method: 'GET', 83 | params: object, 84 | addons 85 | }); 86 | 87 | if (data.error) return handleErrors(new Error(data.error)) as Response; 88 | 89 | 90 | return data as Response; 91 | }; -------------------------------------------------------------------------------- /api/v2/session_actions.ts: -------------------------------------------------------------------------------- 1 | import { request } from "../../utility/request"; 2 | import { IDefaultParams, IError } from "../../types"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { credentials } from "../../utility/auth"; 5 | 6 | 7 | type params = ({ 8 | type: 'verify'; 9 | code: string, 10 | } | { 11 | type: 'reissue'; 12 | } | { 13 | type: 'delete'; 14 | }); 15 | 16 | 17 | type Response = 18 | T extends 'verify' 19 | ? "" & IError 20 | : T extends 'reissue' 21 | ? { message: string } & IError 22 | : T extends 'delete' 23 | ? '' & IError 24 | : IError; 25 | 26 | 27 | // FIXME? 28 | export const session_actions = async (params: T, addons?: IDefaultParams): Promise> => { 29 | let url = 'https://osu.ppy.sh/api/v2'; 30 | let method = 'POST'; 31 | 32 | const headers: any = {}; 33 | let body: any = ''; 34 | 35 | 36 | switch (params?.type) { 37 | case 'verify': 38 | if (credentials.type != 'lazer') { 39 | return handleErrors(new Error(`Login via lazer to use this endpoint`)) as Response; 40 | }; 41 | 42 | if (params?.code == null) { 43 | return handleErrors(new Error(`Specify verification code`)) as Response; 44 | }; 45 | 46 | url += `/session/verify`; 47 | 48 | 49 | const boundary = `----WebKitFormBoundary${Math.random().toString(16).substring(2)}`; 50 | body += `--${boundary}\r\n`; 51 | body += 'Content-Disposition: form-data; name="verification_key"\r\n\r\n'; 52 | body += `${params.code}\r\n`; 53 | body += `--${boundary}--\r\n`; 54 | 55 | headers['Content-Type'] = `multipart/form-data; boundary=${boundary}`; 56 | headers['Content-Length'] = Buffer.byteLength(body); 57 | break; 58 | 59 | case 'reissue': 60 | if (credentials.type != 'lazer') { 61 | return handleErrors(new Error(`Login via lazer to use this endpoint`)) as Response; 62 | }; 63 | 64 | url += `/session/verify/reissue`; 65 | 66 | break; 67 | 68 | case 'delete': 69 | url += `/oauth/tokens/current`; 70 | method = 'DELETE'; 71 | 72 | break; 73 | }; 74 | 75 | 76 | const data = await request(url, { 77 | method: method, 78 | data: body, 79 | headers: headers, 80 | addons, 81 | }); 82 | 83 | if (data.error) return handleErrors(new Error(data.error)) as Response; 84 | 85 | 86 | return data as Response; 87 | }; -------------------------------------------------------------------------------- /api/v2/spotlights_list.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { SpotlightsListResponse } from "../../types/v2/spotlights_list"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | type Response = SpotlightsListResponse[] & IError; 8 | 9 | 10 | export const spotlights_list = async (addons?: IDefaultParams): Promise => { 11 | const data = await request(`https://osu.ppy.sh/api/v2/spotlights`, { 12 | method: 'GET', 13 | addons, 14 | }); 15 | 16 | if (data.error) return handleErrors(new Error(data.error)); 17 | 18 | 19 | return data.spotlights; 20 | }; -------------------------------------------------------------------------------- /api/v2/users_activity.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { UsersActivityResponse } from "../../types/v2/users_activity"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | type Response = UsersActivityResponse[] & IError; 8 | 9 | 10 | export const users_activity = async (params: { 11 | id: number; 12 | limit?: number; 13 | offset?: number; 14 | }, addons?: IDefaultParams): Promise => { 15 | if (params?.id == null) { 16 | return handleErrors(new Error(`Specify user id`)) as Response; 17 | }; 18 | 19 | 20 | const data = await request(`https://osu.ppy.sh/api/v2/users/${params.id}/recent_activity`, { 21 | method: 'GET', 22 | params: { 23 | limit: params.limit, 24 | offset: params.offset, 25 | }, 26 | addons, 27 | }); 28 | 29 | if (data.error) return handleErrors(new Error(data.error)); 30 | 31 | 32 | return data; 33 | }; -------------------------------------------------------------------------------- /api/v2/users_beatmaps.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { UsersBeatmapsResponse } from "../../types/v2/users_beatmaps"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | type Response = UsersBeatmapsResponse[] & IError; 8 | 9 | 10 | export const users_beatmaps = async (params: { 11 | type: 'favourite' | 'graveyard' | 'guest' | 'loved' | 'most_played' | 'nominated' | 'pending' | 'ranked'; 12 | id: number; 13 | 14 | limit?: number; 15 | offset?: number; 16 | }, addons?: IDefaultParams): Promise => { 17 | if (params?.id == null) { 18 | return handleErrors(new Error(`Specify user id`)) as Response; 19 | }; 20 | 21 | if (params?.type == null) { 22 | return handleErrors(new Error(`Specify beatmaps type`)) as Response; 23 | }; 24 | 25 | 26 | const data = await request(`https://osu.ppy.sh/api/v2/users/${params.id}/beatmapsets/${params.type}`, { 27 | method: 'GET', 28 | params: { 29 | limit: params.limit, 30 | offset: params.offset, 31 | }, 32 | addons, 33 | }); 34 | 35 | if (data.error) return handleErrors(new Error(data.error)); 36 | 37 | 38 | return data; 39 | }; -------------------------------------------------------------------------------- /api/v2/users_details.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError, Modes_names } from "../../types"; 2 | import { UsersDetailsResponse } from "../../types/v2/users_details"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | type Response = UsersDetailsResponse & IError; 8 | 9 | 10 | export const users_details = async (params: { 11 | user?: number | string; 12 | mode?: Modes_names; 13 | key?: 'id' | 'username' | '@'; 14 | }, addons?: IDefaultParams): Promise => { 15 | if (params?.user == null) { 16 | return handleErrors(new Error('Specify user id or name')) as Response; 17 | }; 18 | 19 | let key = params?.key; 20 | let user = params.user; 21 | if (key == '@') user = `@${user}`; 22 | 23 | 24 | const data = await request(`https://osu.ppy.sh/api/v2/users/${user}${params.mode ? `/${params.mode}` : ''}`, { 25 | method: 'GET', 26 | params: { key: key }, 27 | addons, 28 | }); 29 | 30 | if (data.error) return handleErrors(new Error(data.error)); 31 | 32 | return data; 33 | }; -------------------------------------------------------------------------------- /api/v2/users_events.ts: -------------------------------------------------------------------------------- 1 | import { request } from "../../utility/request"; 2 | import { UsersEventsResponse } from '../../types/v2/users_events'; 3 | import { IDefaultParams, IError } from "../../types"; 4 | import { handleErrors } from "../../utility/handleErrors"; 5 | 6 | 7 | type Response = UsersEventsResponse & IError; 8 | 9 | 10 | export const users_events = async ({ sort, cursor_string, type }: { 11 | type?: ('achievement' | 'beatmapsetApprove' | 'beatmapsetDelete' | 'beatmapsetRevive' | 'beatmapsetUpdate' | 'beatmapsetUpload' | 'rank' | 'rankLost' | 'userSupportAgain' | 'userSupportFirst' | 'userSupportGift' | 'usernameChange')[] 12 | sort?: 'id_desc' | 'id_asc', 13 | cursor_string?: string; 14 | } = {}, addons?: IDefaultParams): Promise => { 15 | const data: any = await request(`https://osu.ppy.sh/api/v2/events`, { 16 | method: 'GET', 17 | params: { sort: sort, cursor_string: cursor_string }, 18 | addons, 19 | }); 20 | 21 | if (data.error) return handleErrors(new Error(data.error)); 22 | 23 | 24 | if (type != null && !Array.isArray(type)) { 25 | return handleErrors(new Error(`Events Type must be an Array of types. Example: ['achievement', 'rank']`)) as Response; 26 | }; 27 | 28 | 29 | if (type) { 30 | const sorted = data.events.filter((r: any) => type.includes(r.type)); 31 | data.events = sorted; 32 | }; 33 | 34 | 35 | return data; 36 | }; -------------------------------------------------------------------------------- /api/v2/users_kudosu.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { UsersKudosuResponse } from "../../types/v2/users_kudosu"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | type Response = UsersKudosuResponse[] & IError; 8 | 9 | 10 | export const users_kudosu = async (params: { 11 | id: number; 12 | limit?: number; 13 | offset?: number; 14 | }, addons?: IDefaultParams): Promise => { 15 | if (params?.id == null) { 16 | return handleErrors(new Error('Specify user id')) as Response; 17 | }; 18 | 19 | 20 | const data = await request(`https://osu.ppy.sh/api/v2/users/${params.id}/kudosu`, { 21 | method: 'GET', 22 | params: { 23 | limit: params.limit, 24 | offset: params.offset, 25 | }, 26 | addons, 27 | }); 28 | 29 | if (data.error) return handleErrors(new Error(data.error)); 30 | 31 | 32 | return data; 33 | }; -------------------------------------------------------------------------------- /api/v2/users_list.ts: -------------------------------------------------------------------------------- 1 | import { request } from "../../utility/request"; 2 | import { IDefaultParams, IError } from "../../types"; 3 | import { UsersLisResponse } from "../../types/v2/users_list"; 4 | import { handleErrors } from "../../utility/handleErrors"; 5 | 6 | 7 | type Response = UsersLisResponse[] & IError; 8 | 9 | 10 | export const users_list = async (params: { ids: number[], include_variants?: boolean }, addons?: IDefaultParams): Promise => { 11 | if ((params?.ids || [])?.length == 0) { 12 | return handleErrors(new Error(`Specify at least one user id`)) as Response; 13 | }; 14 | 15 | if (params.ids.length > 50) { 16 | return handleErrors(new Error("No more than 50 users can be requested at once.")) as Response; 17 | }; 18 | 19 | const data = await request(`https://osu.ppy.sh/api/v2/users`, { 20 | method: 'GET', 21 | params: { 22 | 'ids[]': params.ids, 23 | include_variant_statistics: params.include_variants, 24 | }, 25 | addons 26 | }); 27 | 28 | if (data.error) return handleErrors(new Error(data.error)); 29 | 30 | 31 | if (data.users) return data.users; 32 | return data; 33 | }; -------------------------------------------------------------------------------- /api/v2/users_lookup.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { UsersLookupResponse } from "../../types/v2/users_lookup"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | type Response = UsersLookupResponse[] & IError; 8 | 9 | 10 | export const users_lookup = async (params: { 11 | ids: (string | number)[]; 12 | }, addons?: IDefaultParams): Promise => { 13 | if ((params?.ids || [])?.length == 0) { 14 | return handleErrors(new Error(`Specify at least one user id`)) as Response; 15 | }; 16 | 17 | if (params.ids.length > 50) { 18 | return handleErrors(new Error("No more than 50 users can be requested at once.")) as Response; 19 | }; 20 | 21 | 22 | const data = await request(`https://osu.ppy.sh/api/v2/users/lookup`, { 23 | method: 'GET', 24 | params: { 25 | 'ids[]': params.ids, 26 | }, 27 | addons, 28 | }); 29 | 30 | 31 | if (data.error) return handleErrors(new Error(data.error)); 32 | return data?.users || data; 33 | }; -------------------------------------------------------------------------------- /api/v2/wiki_details.ts: -------------------------------------------------------------------------------- 1 | import { IDefaultParams, IError } from "../../types"; 2 | import { WikiDetailsResponse } from "../../types/v2/wiki_details"; 3 | import { handleErrors } from "../../utility/handleErrors"; 4 | import { request } from "../../utility/request"; 5 | 6 | 7 | type Response = WikiDetailsResponse & IError; 8 | 9 | 10 | export const wiki_details = async (params: { 11 | locale: string; 12 | path_name: string; 13 | }, addons?: IDefaultParams): Promise => { 14 | if (params?.locale == null) { 15 | return handleErrors(new Error(`Specify locale code. Example: en`)) as Response; 16 | }; 17 | 18 | if (params?.path_name == null) { 19 | return handleErrors(new Error(`Specify wiki page path`)) as Response; 20 | }; 21 | 22 | 23 | const data = await request(`https://osu.ppy.sh/api/v2/wiki/${params.locale}/${params.path_name}`, { 24 | method: 'GET', 25 | addons, 26 | }); 27 | 28 | if (data.error) return handleErrors(new Error(data.error)); 29 | 30 | 31 | return data; 32 | }; -------------------------------------------------------------------------------- /changes/2.1.2.md: -------------------------------------------------------------------------------- 1 | # Moved 2 | ## Auth 3 | ### ![#ff7b7b](https://via.placeholder.com/15/ff7b7b/000000?text=+) 4 | ```js 5 | const { v2 } = require('osu-api-extended') 6 | 7 | const main = async () => { 8 | // Auth via client 9 | await v2.login('CLIENT_ID', 'CLIENT_SECRET') 10 | 11 | // Auth via lazer credentials 12 | await v2.login_lazer('YOUR_LOGIN', 'YOUR_PASSWORD') 13 | 14 | // Auth via oauth2 15 | await v2.authorize('CLIENT_ID', 'CLIENT_SECRET', 'CALLBACK_URL') 16 | 17 | const data = await v2.beatmap.get(2379651) 18 | console.log(data) 19 | } 20 | 21 | main() 22 | ``` 23 | ### ![#7bff8b](https://via.placeholder.com/15/7bff8b/000000?text=+) 24 | ```js 25 | const { v2, auth } = require('osu-api-extended') 26 | 27 | const main = async () => { 28 | // Auth via client 29 | await auth.login('CLIENT_ID', 'CLIENT_SECRET') 30 | 31 | // Auth via lazer credentials 32 | await auth.login_lazer('YOUR_LOGIN', 'YOUR_PASSWORD') 33 | 34 | // Auth via oauth2 35 | await auth.authorize('CLIENT_ID', 'CLIENT_SECRET', 'CALLBACK_URL') 36 | 37 | const data = await v2.beatmap.get(2379651) 38 | console.log(data) 39 | } 40 | 41 | main() 42 | ``` 43 | # New 44 | ## Endpoints 45 | 46 | ### Return all player scores from beatmap 47 | ```js 48 | await v2.beatmap.scores.user_all(2097898, 7562902, 'osu'); 49 | ``` -------------------------------------------------------------------------------- /changes/2.7.0.md: -------------------------------------------------------------------------------- 1 | # Changes 2 | 3 | ### mods.name 4 | Now it's returns empty string for nomod instead of NM 5 | 6 |
7 | 8 | # New endpoints 9 | 10 | ## v2 11 | 12 | Chat: [new](/cyperdark/osu-api-extended/wiki/v2.chat.new) | [channels.join](/cyperdark/osu-api-extended/wiki/v2.chat.channels.join) | [channels.leave](/cyperdark/osu-api-extended/wiki/v2.chat.channels.leave) 13 | 14 | Comments: [edit](/cyperdark/osu-api-extended/wiki/v2.comments.edit) | [new](/cyperdark/osu-api-extended/wiki/v2.comments.new) | [remove](/cyperdark/osu-api-extended/wiki/v2.comments.remove) | [vote](/cyperdark/osu-api-extended/wiki/v2.comments.vote) 15 | 16 | Forum: [post.edit](/cyperdark/osu-api-extended/wiki/v2.forums.post.edit) 17 | | [topic.edit](/cyperdark/osu-api-extended/wiki/v2.forums.topic.edit) | [topic.new](/cyperdark/osu-api-extended/wiki/v2.forums.topic.new) | [topic.reply](/cyperdark/osu-api-extended/wiki/v2.forums.topic.reply) 18 | 19 | Rooms: [details](/cyperdark/osu-api-extended/wiki/v2.room.details) | [leaderboard](/cyperdark/osu-api-extended/wiki/v2.room.leaderboard) | [rooms.list](/cyperdark/osu-api-extended/wiki/v2.rooms.list) 20 | 21 |
22 | 23 | # Endpoints changes 24 | 25 | ```diff 26 | - v2.backgrounds.seasonal 27 | + v2.assets.seasonalBackgrounds 28 | ``` 29 | 30 | ```diff 31 | - v2.beatmap.attributes 32 | + v2.beatmap.id.attributes 33 | ``` 34 | 35 | ```diff 36 | - v2.beatmap.diff 37 | + v2.beatmap.id.details 38 | ``` 39 | 40 | ```diff 41 | - v2.beatmap.download 42 | + v2.beatmap.set.download 43 | ``` 44 | 45 | ```diff 46 | - v2.beatmap.events 47 | + v2.beatmaps.events 48 | ``` 49 | 50 | ```diff 51 | - v2.beatmap.favourites 52 | + v2.beatmap.set.addToFavourites 53 | ``` 54 | 55 | ```diff 56 | - v2.beatmap.favourites 57 | + v2.beatmap.set.addToFavourites 58 | ``` 59 | 60 | ```diff 61 | - v2.beatmap.leaderboard 62 | + v2.scores.beatmap 63 | ``` 64 | 65 | ```diff 66 | - v2.beatmap.list 67 | + v2.beatmaps.details 68 | ``` 69 | 70 | ```diff 71 | - v2.beatmap.lookup.diff 72 | + v2.beatmap.id.lookup 73 | ``` 74 | 75 | ```diff 76 | - v2.beatmap.lookup.set 77 | + v2.beatmap.set.lookup 78 | ``` 79 | 80 | ```diff 81 | - v2.beatmap.search 82 | + v2.beatmaps.search 83 | ``` 84 | 85 | ```diff 86 | - v2.beatmap.set 87 | + v2.beatmap.set.details 88 | ``` 89 | 90 | ```diff 91 | - v2.chat.channel.messages.readed 92 | + v2.chat.channels.messages.markAsReaded 93 | ``` 94 | 95 | ```diff 96 | - v2.group.list 97 | + v2.users.groups.list 98 | ``` 99 | 100 | ```diff 101 | - v2.news.details 102 | + v2.site.news.details 103 | ``` 104 | 105 | ```diff 106 | - v2.news.list 107 | + v2.site.news.list 108 | ``` 109 | 110 | ```diff 111 | - v2.user.list 112 | + v2.users.details 113 | ``` 114 | 115 | ```diff 116 | - v2.user.scores.beatmap.best 117 | - v2.user.scores.beatmap.all 118 | + v2.scores.user.beatmap 119 | ``` 120 | 121 | ```diff 122 | - v2.user.scores.category 123 | + v2.scores.user.category 124 | ``` 125 | 126 | ```diff 127 | - v2.ranking.details 128 | + v2.site.ranking.details 129 | ``` 130 | 131 |
132 |
133 | 134 | ## Temporary removed 135 | - v2.chat.presense 136 | - v2.notifications.readed -------------------------------------------------------------------------------- /changes/2.7.2.md: -------------------------------------------------------------------------------- 1 | # New 2 | 3 | - Added `mods.enums` (for sorting and etc.) 4 | - Added `build_url` & `auth.authorize` (user auth via link + server) 5 | 6 |
7 | 8 | # Changes 9 | 10 | - Renamed `auth.authorize` to `auth.authorize_cli` 11 | - Types fixes 12 | - Remove `open` dependencie. Now using `execSync` 13 | - Added scores to `auth` 14 | 15 |
16 | 17 | ## v2.scores.user.category 18 | 19 | - Use `boolean` instead of `string` 20 | - Added mods filter. Use `mods.enums` 21 | - Added `mods_id` field 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "osu-api-extended", 3 | "version": "3.1.4", 4 | "description": "Advanced osu! api wrapper cover all V2 and V1 endpoints, and provide useful tools", 5 | "main": "dist/index.js", 6 | "types": "dist/index.d.ts", 7 | "files": [ 8 | "dist/*" 9 | ], 10 | "scripts": { 11 | "build": "tsc", 12 | "tester": "node test/test_new.js" 13 | }, 14 | "keywords": [ 15 | "osu", 16 | "api", 17 | "v1", 18 | "v2", 19 | "difficulty", 20 | "accuracy", 21 | "extended", 22 | "replay", 23 | "diff", 24 | "file", 25 | "rank", 26 | "node", 27 | "js" 28 | ], 29 | "repository": { 30 | "type": "git", 31 | "url": "https://github.com/cyperdark/osu-api-extended.git" 32 | }, 33 | "author": "cyperdark", 34 | "license": "MIT", 35 | "devDependencies": { 36 | "@types/node": "^16.11.7", 37 | "typescript": "^4.5.2" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /routes/v1.ts: -------------------------------------------------------------------------------- 1 | import beatmap_set, { types as beatmap_set_type, description as beatmap_set_desc } from "../api/v1/routes/beatmap/set"; 2 | import beatmap_diff, { types as beatmap_diff_type, description as beatmap_diff_desc } from "../api/v1/routes/beatmap/diff"; 3 | import beatmap_creator, { types as beatmap_creator_type, description as beatmap_creator_desc } from "../api/v1/routes/beatmap/creator"; 4 | import beatmap_scores, { types as beatmap_scores_type, description as beatmap_scores_desc } from "../api/v1/routes/beatmap/scores"; 5 | 6 | export const beatmap: { 7 | set: beatmap_set_type, 8 | diff: beatmap_diff_type, 9 | creator: beatmap_creator_type, 10 | scores: beatmap_scores_type 11 | } = { 12 | set: beatmap_set, 13 | diff: beatmap_diff, 14 | creator: beatmap_creator, 15 | scores: beatmap_scores 16 | }; 17 | 18 | 19 | import user_details, { types as user_details_type, description as user_details_desc } from "../api/v1/routes/user/details"; 20 | import user_scores_category, { types as user_scores_category_type, description as user_scores_category_desc } from "../api/v1/routes/user/scores-category"; 21 | 22 | export const user: { 23 | details: user_details_type, 24 | scores: { 25 | category: user_scores_category_type, 26 | } 27 | } = { 28 | details: user_details, 29 | scores: { 30 | category: user_scores_category, 31 | } 32 | }; 33 | 34 | 35 | import match_details, { types as match_details_type, description as match_details_desc } from "../api/v1/routes/match"; 36 | export const match: match_details_type = match_details; 37 | 38 | 39 | /** 40 | * @deprecated 41 | */ 42 | export const replay = () => { 43 | return 'USE API V2' 44 | }; 45 | 46 | 47 | export const desc: { 48 | beatmap_set: object, 49 | beatmap_diff: object, 50 | beatmap_creator: object, 51 | beatmap_scores: object, 52 | user_details: object, 53 | user_scores_category: object, 54 | match: object, 55 | } = { 56 | beatmap_set: beatmap_set_desc, 57 | beatmap_diff: beatmap_diff_desc, 58 | beatmap_creator: beatmap_creator_desc, 59 | beatmap_scores: beatmap_scores_desc, 60 | user_details: user_details_desc, 61 | user_scores_category: user_scores_category_desc, 62 | match: match_details_desc, 63 | }; -------------------------------------------------------------------------------- /tools/country.ts: -------------------------------------------------------------------------------- 1 | import { IError } from "../types"; 2 | import { CountryCodes, CountryNames } from "../types/enums"; 3 | import { CountryResponse } from "../types/tools"; 4 | import { handleErrors } from "../utility/handleErrors"; 5 | 6 | 7 | type Response = CountryResponse & IError; 8 | 9 | /** 10 | * Get more information about the country by providing an name/code. 11 | * 12 | *   13 | * 14 | * ### Parameters 15 | * - `name` - Name of the country or country code 16 | * 17 | *   18 | * 19 | * ### Usage Example 20 | * ```js 21 | * const { tools } = require('osu-api-extended'); 22 | * 23 | * function main() { 24 | * try { 25 | * const result = tools.country_details('US'); 26 | * // or 27 | * const result = tools.country_details('United States'); 28 | * if (result.error != null) { 29 | * console.log(result.error); 30 | * return; 31 | * }; 32 | * 33 | * 34 | * console.log(result); 35 | * } catch (error) { 36 | * console.log(error); 37 | * }; 38 | * }; 39 | * 40 | * main(); 41 | * ``` 42 | */ 43 | export const country_details = (name: string): Response => { 44 | if (name == null || name == '') { 45 | return handleErrors(new Error('Specify country code or country name')) as Response; 46 | }; 47 | 48 | 49 | if (name.length == 2) { 50 | const find = (CountryNames as any)[name.toUpperCase()]; 51 | if (find == null) { 52 | return handleErrors(new Error('Country not found')) as Response; 53 | }; 54 | 55 | 56 | return { 57 | code: name.toUpperCase(), 58 | name: find, 59 | } as Response; 60 | }; 61 | 62 | 63 | const find = (CountryCodes as any)[name]; 64 | if (find == null) { 65 | return handleErrors(new Error('Country not found')) as Response; 66 | }; 67 | 68 | 69 | return { 70 | code: name, 71 | name: find, 72 | } as Response; 73 | }; -------------------------------------------------------------------------------- /tools/index.ts: -------------------------------------------------------------------------------- 1 | import { handleErrors } from "../utility/handleErrors"; 2 | 3 | export { beatmaps_download as download_beatmaps } from "../api/v2/beatmaps_download"; 4 | export { calculate_accuracy } from "./accuracy"; 5 | export { calculate_mods } from "./mods"; 6 | export { country_details } from "./country"; 7 | export { calculate_rank } from "./rank"; 8 | export { calculate_total_passed_objects, calculate_hits } from "./objects"; 9 | export { calculate_net_pp } from "./net-pp"; 10 | 11 | 12 | 13 | export const calculate_pp = () => { 14 | return handleErrors(new Error('Use rosu-pp-js instead')); 15 | }; 16 | 17 | /** 18 | * Builder that returns a link an 'user', a score, a beatmap, etc. 19 | * 20 | *   21 | * 22 | * ### Parameters 23 | * - `params._direct?` - Return osu direct link for type `beatmap` and `beatmapset` 24 | * - `params.mode?` - Return legacy link for type `score` 25 | * - `params.type` - Type of the link 26 | * - `params.value` - Link url value, for example `beatmap id` or `user id` 27 | * 28 | *   29 | * 30 | * ### Usage Example 31 | * ```js 32 | * const { tools } = require('osu-api-extended'); 33 | * 34 | * function main() { 35 | * try { 36 | * const result = tools.build_url({ type: 'beatmap', value: 4397592 }); 37 | * 38 | * console.log(result); 39 | * } catch (error) { 40 | * console.log(error); 41 | * }; 42 | * }; 43 | * 44 | * main(); 45 | * ``` 46 | */ 47 | export const build_url = (params: { 48 | _direct?: boolean; 49 | mode?: 'osu' | 'fruits' | 'mania' | 'taiko'; 50 | 51 | type: 'beatmap' | 'beatmapset' | 'editor_timing' | 'news' | 'match' | 'avatar' | 'user' | 'badge' | 'score'; 52 | value: any; 53 | }) => { 54 | const { _direct, type, mode, value } = params || {}; 55 | 56 | switch (type) { 57 | case 'beatmap': 58 | return _direct == true ? `osu://b/${value}` : `https://osu.ppy.sh/b/${value}`; 59 | 60 | case 'beatmapset': 61 | return _direct == true ? `osu://s/${value}` : `https://osu.ppy.sh/s/${value}`; 62 | 63 | 64 | case 'news': 65 | return `https://osu.ppy.sh/home/news/${value}`; 66 | 67 | 68 | case 'editor_timing': 69 | return `osu://edit/${value}`; 70 | 71 | 72 | case 'match': 73 | return `https://osu.ppy.sh/community/matches/${value}`; 74 | 75 | 76 | case 'avatar': 77 | return `https://a.ppy.sh/${value}`; 78 | 79 | case 'user': 80 | return `https://osu.ppy.sh/users/${value}`; 81 | 82 | 83 | case 'badge': 84 | return `https://assets.ppy.sh/profile-badges/${value}`; 85 | 86 | 87 | case 'score': 88 | return `https://osu.ppy.sh/scores/${mode ? "/" + mode : ''}${value}`; 89 | 90 | 91 | default: 92 | return `Unsupported type: ${params?.type}`; 93 | }; 94 | }; 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | // const postDataArray = (field_name: string, array: any[]) => { 106 | // const data = array.map((data, index) => { 107 | // return postDataObject(`${field_name}[${index}]`, data); 108 | // }).join('&'); 109 | 110 | 111 | // return data; 112 | // }; 113 | 114 | // const postDataObject = (field_name: string, object: object) => { 115 | // return Object.entries(object).map(([key, value]) => { 116 | // if (field_name == '') 117 | // return `${key}=${encodeURIComponent(value as any)}`; 118 | 119 | // return `${field_name}[${key}]=${encodeURIComponent(value as any)}`; 120 | // }).join('&'); 121 | // }; -------------------------------------------------------------------------------- /tools/net-pp.ts: -------------------------------------------------------------------------------- 1 | import type { IError, Modes_names } from "../types"; 2 | import { handleErrors } from "../utility/handleErrors"; 3 | 4 | import { scores_list_user_user_best_response } from "../types/v2/scores_list_user_best"; 5 | 6 | 7 | type Response = { 8 | pp: number; 9 | totalNow: number; 10 | totalBefore: number; 11 | } & IError; 12 | 13 | 14 | /** 15 | * Calculate how much raw pp you would gain from a play 16 | * 17 | *   18 | * 19 | * ### Parameters 20 | * - `scores` - Plays pp or Array of scores 21 | * - `pp` - Amount of play pp 22 | * 23 | *   24 | * 25 | * ### Usage Example 26 | * ```js 27 | * const { tools } = require('osu-api-extended'); 28 | * 29 | * function main() { 30 | * try { 31 | * const plays = [1000, 900, 800, 700]; 32 | * const scores = [{ id: 123, pp: 1000 }, { id: 123, pp: 555 }, { id: 123, pp: 234 }, { id: 123, pp: 100 }]; 33 | * const result = tools.calculate_net_pp(plays, 400); 34 | * // or 35 | * const result = tools.calculate_net_pp(scores, 400); 36 | * if (result.error != null) { 37 | * console.log(result.error); 38 | * return; 39 | * }; 40 | * 41 | * 42 | * console.log(result); 43 | * } catch (error) { 44 | * console.log(error); 45 | * }; 46 | * }; 47 | * 48 | * main(); 49 | * ``` 50 | */ 51 | export const calculate_net_pp = (scores: scores_list_user_user_best_response[] | number[], pp: number): Response => { 52 | if (!Array.isArray(scores)) { 53 | return handleErrors(new Error(`Provide array of scores or plays pp`)) as Response; 54 | }; 55 | 56 | if (!isFinite(pp) || pp == null) { 57 | return handleErrors(new Error(`Specify play pp`)) as Response; 58 | }; 59 | 60 | 61 | const pp_values = typeof scores[0] == 'number' ? scores : (scores as any[]).map(r => r.pp); 62 | pp_values.sort((a, b) => b - a); 63 | 64 | // weight the user's current scores. (see https://osu.ppy.sh/wiki/en/Performance_points/Weighting_system) 65 | const weighted_before = pp_values.slice(0, 100).map((x, i) => x * Math.pow(0.95, i)); 66 | // sum up the total pp value of the user's current scores. 67 | const total_pp_old = weighted_before.reduce((a, b) => a + b, 0); 68 | 69 | 70 | if (pp_values.length >= 100 && pp < Math.min(pp_values[pp_values.length - 1])) 71 | return { 72 | pp: 0, 73 | totalNow: total_pp_old, 74 | totalBefore: total_pp_old, 75 | } as Response; 76 | 77 | 78 | // Push new pp 79 | pp_values.push(pp); 80 | pp_values.sort((a, b) => b - a); 81 | 82 | 83 | // weight the new scores. (see https://osu.ppy.sh/wiki/en/Performance_points/Weighting_system) 84 | const weighted_after = pp_values.slice(0, 100).map((x, i) => x * Math.pow(0.95, i)); 85 | // sum up the total pp value of the user's new simulated scores. 86 | const total_pp_new = weighted_after.reduce((a, b) => a + b, 0); 87 | 88 | 89 | return { 90 | pp: total_pp_new - total_pp_old, 91 | totalNow: total_pp_new, 92 | totalBefore: total_pp_old, 93 | } as Response; 94 | }; -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "tslint:recommended", 4 | "tslint-config-prettier" 5 | ], 6 | "rules": { 7 | "semicolon": true, 8 | "no-console": true, 9 | "max-classes-per-file": false, 10 | "one-variable-per-declaration": false, 11 | "prefer-for-of": false, 12 | "no-var-requires": false 13 | } 14 | } -------------------------------------------------------------------------------- /types/tools.ts: -------------------------------------------------------------------------------- 1 | export interface ModsResponse { 2 | number: number; 3 | name: string; 4 | }; 5 | 6 | export interface CountryResponse { 7 | code: string; 8 | name: string; 9 | }; 10 | 11 | export interface AccuracyResponse { 12 | accuracy: number; 13 | fc_accuracy: number; 14 | }; 15 | 16 | export interface RankResponse { 17 | accuracy: number; 18 | rank: string; 19 | }; 20 | 21 | export type TotalObjectsResponse = { 22 | amount: number; 23 | mode: string; 24 | hits: TotalObjectsHits 25 | }; 26 | 27 | export type ConvertHitsResponse = { 28 | hits: TotalObjectsHits 29 | fc: TotalObjectsHits 30 | }; 31 | 32 | export interface TotalObjectsHits { 33 | geki: number; 34 | 300: number; 35 | katu: number; 36 | 100: number; 37 | 50: number; 38 | 0: number; 39 | }; -------------------------------------------------------------------------------- /types/v2/assets_backgrounds.ts: -------------------------------------------------------------------------------- 1 | export interface SeasonalBackgrounds { 2 | ends_at: string 3 | backgrounds: Background[] 4 | } 5 | 6 | export interface BeatmapsetBackground { 7 | cover: string 8 | "cover@2x": string 9 | card: string 10 | "card@2x": string 11 | list: string 12 | "list@2x": string 13 | slimcover: string 14 | "slimcover@2x": string 15 | raw: string 16 | fullsize: string 17 | } 18 | 19 | 20 | export interface Background { 21 | url: string 22 | user: User 23 | } 24 | 25 | export interface User { 26 | avatar_url: string 27 | country_code: string 28 | default_group: string 29 | id: number 30 | is_active: boolean 31 | is_bot: boolean 32 | is_deleted: boolean 33 | is_online: boolean 34 | is_supporter: boolean 35 | last_visit?: string 36 | pm_friends_only: boolean 37 | profile_colour: any 38 | username: string 39 | } 40 | -------------------------------------------------------------------------------- /types/v2/assets_datafiles.ts: -------------------------------------------------------------------------------- 1 | export interface AssetsDatafilesResponse { 2 | files: string[] 3 | }; -------------------------------------------------------------------------------- /types/v2/beatmaps_details_difficulty.ts: -------------------------------------------------------------------------------- 1 | export interface beatmaps_details_difficulty_response { 2 | beatmapset_id: number 3 | difficulty_rating: number 4 | id: number 5 | mode: string 6 | status: string 7 | total_length: number 8 | user_id: number 9 | version: string 10 | accuracy: number 11 | ar: number 12 | bpm: number 13 | convert: boolean 14 | count_circles: number 15 | count_sliders: number 16 | count_spinners: number 17 | cs: number 18 | deleted_at: null 19 | drain: number 20 | hit_length: number 21 | is_scoreable: boolean 22 | last_updated: string 23 | mode_int: number 24 | passcount: number 25 | playcount: number 26 | ranked: number 27 | url: string 28 | checksum: string 29 | beatmapset: Beatmapset 30 | failtimes: Failtimes 31 | max_combo: number 32 | owners: Owner[] 33 | } 34 | 35 | export interface Owner { 36 | id: number 37 | username: string 38 | } 39 | 40 | export interface Failtimes { 41 | fail: number[] 42 | exit: number[] 43 | } 44 | 45 | export interface Beatmapset { 46 | artist: string 47 | artist_unicode: string 48 | covers: Covers 49 | creator: string 50 | favourite_count: number 51 | hype: null 52 | id: number 53 | nsfw: boolean 54 | offset: number 55 | play_count: number 56 | preview_url: string 57 | source: string 58 | spotlight: boolean 59 | status: string 60 | title: string 61 | title_unicode: string 62 | track_id: null 63 | user_id: number 64 | video: boolean 65 | bpm: number 66 | can_be_hyped: boolean 67 | deleted_at: null 68 | discussion_enabled: boolean 69 | discussion_locked: boolean 70 | is_scoreable: boolean 71 | last_updated: string 72 | legacy_thread_url: string 73 | nominations_summary: Nominationssummary 74 | ranked: number 75 | ranked_date: string 76 | storyboard: boolean 77 | submitted_date: string 78 | tags: string 79 | availability: Availability 80 | ratings: number[] 81 | } 82 | 83 | export interface Availability { 84 | download_disabled: boolean 85 | more_information: null 86 | } 87 | 88 | export interface Nominationssummary { 89 | current: number 90 | eligible_main_rulesets: string[] 91 | required_meta: Requiredmeta 92 | } 93 | 94 | export interface Requiredmeta { 95 | main_ruleset: number 96 | non_main_ruleset: number 97 | } 98 | 99 | export interface Covers { 100 | cover: string 101 | 'cover@2x': string 102 | card: string 103 | 'card@2x': string 104 | list: string 105 | 'list@2x': string 106 | slimcover: string 107 | 'slimcover@2x': string 108 | } -------------------------------------------------------------------------------- /types/v2/beatmaps_discussions_posts.ts: -------------------------------------------------------------------------------- 1 | export interface BeatmapsDiscussionsPostsResponse { 2 | beatmapsets: Beatmapset[] 3 | discussions: Discussion[] 4 | posts: Post[] 5 | users: User[] 6 | cursor: Cursor 7 | cursor_string: string 8 | } 9 | 10 | export interface Beatmapset { 11 | artist: string 12 | artist_unicode: string 13 | covers: Covers 14 | creator: string 15 | favourite_count: number 16 | hype?: Hype 17 | id: number 18 | nsfw: boolean 19 | offset: number 20 | play_count: number 21 | preview_url: string 22 | source: string 23 | spotlight: boolean 24 | status: string 25 | title: string 26 | title_unicode: string 27 | track_id: any 28 | user_id: number 29 | video: boolean 30 | } 31 | 32 | export interface Covers { 33 | cover: string 34 | "cover@2x": string 35 | card: string 36 | "card@2x": string 37 | list: string 38 | "list@2x": string 39 | slimcover: string 40 | "slimcover@2x": string 41 | } 42 | 43 | export interface Hype { 44 | current: number 45 | required: number 46 | } 47 | 48 | export interface Discussion { 49 | id: number 50 | beatmapset_id: number 51 | beatmap_id?: number 52 | user_id: number 53 | deleted_by_id: any 54 | message_type: string 55 | parent_id: any 56 | timestamp?: number 57 | resolved: boolean 58 | can_be_resolved: boolean 59 | can_grant_kudosu: boolean 60 | created_at: string 61 | updated_at: string 62 | deleted_at: any 63 | last_post_at: string 64 | kudosu_denied: boolean 65 | } 66 | 67 | export interface Post { 68 | beatmapset_discussion_id: number 69 | created_at: string 70 | deleted_at: any 71 | deleted_by_id: any 72 | id: number 73 | last_editor_id: any 74 | message: string 75 | system: boolean 76 | updated_at: string 77 | user_id: number 78 | } 79 | 80 | export interface User { 81 | avatar_url: string 82 | country_code: string 83 | default_group: string 84 | id: number 85 | is_active: boolean 86 | is_bot: boolean 87 | is_deleted: boolean 88 | is_online: boolean 89 | is_supporter: boolean 90 | last_visit?: string 91 | pm_friends_only: boolean 92 | profile_colour?: string 93 | username: string 94 | } 95 | 96 | export interface Cursor { 97 | page: number 98 | limit: number 99 | } 100 | -------------------------------------------------------------------------------- /types/v2/beatmaps_discussions_votes.ts: -------------------------------------------------------------------------------- 1 | export interface BeatmapsDiscussionsVotesResponse { 2 | discussions: Discussion[] 3 | users: User[] 4 | votes: Vote[] 5 | cursor?: Cursor 6 | cursor_string?: string 7 | } 8 | 9 | export interface Discussion { 10 | id: number 11 | beatmapset_id: number 12 | beatmap_id?: number 13 | user_id: number 14 | deleted_by_id: any 15 | message_type: string 16 | parent_id: any 17 | timestamp?: number 18 | resolved: boolean 19 | can_be_resolved: boolean 20 | can_grant_kudosu: boolean 21 | created_at: string 22 | updated_at: string 23 | deleted_at: any 24 | last_post_at: string 25 | kudosu_denied: boolean 26 | } 27 | 28 | export interface User { 29 | avatar_url: string 30 | country_code: string 31 | default_group: string 32 | id: number 33 | is_active: boolean 34 | is_bot: boolean 35 | is_deleted: boolean 36 | is_online: boolean 37 | is_supporter: boolean 38 | last_visit?: string 39 | pm_friends_only: boolean 40 | profile_colour?: string 41 | username: string 42 | groups: Group[] 43 | } 44 | 45 | export interface Group { 46 | colour: string 47 | has_listing: boolean 48 | has_playmodes: boolean 49 | id: number 50 | identifier: string 51 | is_probationary: boolean 52 | name: string 53 | short_name: string 54 | playmodes: string[] 55 | } 56 | 57 | export interface Vote { 58 | beatmapset_discussion_id: number 59 | created_at: string 60 | id: number 61 | score: number 62 | updated_at: string 63 | user_id: number 64 | } 65 | 66 | export interface Cursor { 67 | page: number 68 | limit: number 69 | } 70 | -------------------------------------------------------------------------------- /types/v2/beatmaps_download.ts: -------------------------------------------------------------------------------- 1 | import { IError } from ".."; 2 | 3 | export type BeatmapsDownloadResponse = { 4 | status: string, 5 | destination?: string, 6 | /** 7 | * Time in milliseconds 8 | */ 9 | elapsed_time?: number 10 | } & IError; -------------------------------------------------------------------------------- /types/v2/beatmaps_events_list.ts: -------------------------------------------------------------------------------- 1 | export interface BeatmapsEvents { 2 | events: Event[] 3 | reviewsConfig: ReviewsConfig 4 | users: User2[] 5 | } 6 | 7 | export interface Event { 8 | id: number 9 | type: string 10 | comment?: Comment 11 | created_at: string 12 | user_id?: number 13 | beatmapset: Beatmapset 14 | discussion?: Discussion 15 | } 16 | 17 | export interface Comment { 18 | beatmap_discussion_id?: number 19 | beatmap_discussion_post_id?: number 20 | new_vote?: NewVote 21 | votes?: Vote[] 22 | old?: string 23 | new?: string 24 | } 25 | 26 | export interface NewVote { 27 | user_id: number 28 | score: number 29 | } 30 | 31 | export interface Vote { 32 | user_id: number 33 | score: number 34 | } 35 | 36 | export interface Beatmapset { 37 | artist: string 38 | artist_unicode: string 39 | covers: Covers 40 | creator: string 41 | favourite_count: number 42 | hype?: Hype 43 | id: number 44 | nsfw: boolean 45 | offset: number 46 | play_count: number 47 | preview_url: string 48 | source: string 49 | spotlight: boolean 50 | status: string 51 | title: string 52 | title_unicode: string 53 | track_id?: number 54 | user_id: number 55 | video: boolean 56 | user: User 57 | } 58 | 59 | export interface Covers { 60 | cover: string 61 | "cover@2x": string 62 | card: string 63 | "card@2x": string 64 | list: string 65 | "list@2x": string 66 | slimcover: string 67 | "slimcover@2x": string 68 | } 69 | 70 | export interface Hype { 71 | current: number 72 | required: number 73 | } 74 | 75 | export interface User { 76 | avatar_url: string 77 | country_code: string 78 | default_group: string 79 | id: number 80 | is_active: boolean 81 | is_bot: boolean 82 | is_deleted: boolean 83 | is_online: boolean 84 | is_supporter: boolean 85 | last_visit?: string 86 | pm_friends_only: boolean 87 | profile_colour: any 88 | username: string 89 | } 90 | 91 | export interface Discussion { 92 | id: number 93 | beatmapset_id: number 94 | beatmap_id?: number 95 | user_id: number 96 | deleted_by_id: any 97 | message_type: string 98 | parent_id?: any 99 | timestamp?: number 100 | resolved: boolean 101 | can_be_resolved: boolean 102 | can_grant_kudosu: boolean 103 | created_at: string 104 | updated_at: string 105 | deleted_at: any 106 | last_post_at: string 107 | kudosu_denied: boolean 108 | starting_post: StartingPost 109 | } 110 | 111 | export interface StartingPost { 112 | beatmapset_discussion_id: number 113 | created_at: string 114 | deleted_at: any 115 | deleted_by_id: any 116 | id: number 117 | last_editor_id?: number 118 | message: string 119 | system: boolean 120 | updated_at: string 121 | user_id: number 122 | } 123 | 124 | export interface ReviewsConfig { 125 | max_blocks: number 126 | } 127 | 128 | export interface User2 { 129 | avatar_url: string 130 | country_code: string 131 | default_group: string 132 | id: number 133 | is_active: boolean 134 | is_bot: boolean 135 | is_deleted: boolean 136 | is_online: boolean 137 | is_supporter: boolean 138 | last_visit?: string 139 | pm_friends_only: boolean 140 | profile_colour?: string 141 | username: string 142 | groups: Group[] 143 | } 144 | 145 | export interface Group { 146 | colour: string 147 | has_listing: boolean 148 | has_playmodes: boolean 149 | id: number 150 | identifier: string 151 | is_probationary: boolean 152 | name: string 153 | short_name: string 154 | playmodes?: string[] 155 | } 156 | -------------------------------------------------------------------------------- /types/v2/beatmaps_lookup_attributes.ts: -------------------------------------------------------------------------------- 1 | export interface BeatmapsLookupAttributes { 2 | star_rating: number 3 | max_combo: number 4 | aim_difficulty?: number 5 | speed_difficulty?: number 6 | speed_note_count?: number 7 | flashlight_difficulty?: number 8 | slider_factor?: number 9 | approach_rate?: number 10 | overall_difficulty?: number 11 | stamina_difficulty?: number 12 | rhythm_difficulty?: number 13 | colour_difficulty?: number 14 | peak_difficulty?: number 15 | great_hit_window?: number 16 | } 17 | -------------------------------------------------------------------------------- /types/v2/beatmaps_lookup_difficulties.ts: -------------------------------------------------------------------------------- 1 | export interface beatmaps_lookup_difficulties_response { 2 | beatmapset_id: number 3 | difficulty_rating: number 4 | id: number 5 | mode: string 6 | status: string 7 | total_length: number 8 | user_id: number 9 | version: string 10 | accuracy: number 11 | ar: number 12 | bpm: number 13 | convert: boolean 14 | count_circles: number 15 | count_sliders: number 16 | count_spinners: number 17 | cs: number 18 | deleted_at: null 19 | drain: number 20 | hit_length: number 21 | is_scoreable: boolean 22 | last_updated: string 23 | mode_int: number 24 | passcount: number 25 | playcount: number 26 | ranked: number 27 | url: string 28 | checksum: string 29 | beatmapset: Beatmapset 30 | failtimes: Failtimes 31 | max_combo: number 32 | owners: Owner[] 33 | } 34 | 35 | export interface Owner { 36 | id: number 37 | username: string 38 | } 39 | 40 | export interface Failtimes { 41 | fail: number[] 42 | exit: number[] 43 | } 44 | 45 | export interface Beatmapset { 46 | artist: string 47 | artist_unicode: string 48 | covers: Covers 49 | creator: string 50 | favourite_count: number 51 | hype: null 52 | id: number 53 | nsfw: boolean 54 | offset: number 55 | play_count: number 56 | preview_url: string 57 | source: string 58 | spotlight: boolean 59 | status: string 60 | title: string 61 | title_unicode: string 62 | track_id: null 63 | user_id: number 64 | video: boolean 65 | bpm: number 66 | can_be_hyped: boolean 67 | deleted_at: null 68 | discussion_enabled: boolean 69 | discussion_locked: boolean 70 | is_scoreable: boolean 71 | last_updated: string 72 | legacy_thread_url: string 73 | nominations_summary: Nominationssummary 74 | ranked: number 75 | ranked_date: string 76 | storyboard: boolean 77 | submitted_date: string 78 | tags: string 79 | availability: Availability 80 | ratings: number[] 81 | } 82 | 83 | export interface Availability { 84 | download_disabled: boolean 85 | more_information: null 86 | } 87 | 88 | export interface Nominationssummary { 89 | current: number 90 | eligible_main_rulesets: string[] 91 | required_meta: Requiredmeta 92 | } 93 | 94 | export interface Requiredmeta { 95 | main_ruleset: number 96 | non_main_ruleset: number 97 | } 98 | 99 | export interface Covers { 100 | cover: string 101 | 'cover@2x': string 102 | card: string 103 | 'card@2x': string 104 | list: string 105 | 'list@2x': string 106 | slimcover: string 107 | 'slimcover@2x': string 108 | } -------------------------------------------------------------------------------- /types/v2/beatmaps_lookup_difficulty.ts: -------------------------------------------------------------------------------- 1 | export interface beatmaps_lookup_difficulty_response { 2 | beatmapset_id: number 3 | difficulty_rating: number 4 | id: number 5 | mode: string 6 | status: string 7 | total_length: number 8 | user_id: number 9 | version: string 10 | accuracy: number 11 | ar: number 12 | bpm: number 13 | convert: boolean 14 | count_circles: number 15 | count_sliders: number 16 | count_spinners: number 17 | cs: number 18 | deleted_at: null 19 | drain: number 20 | hit_length: number 21 | is_scoreable: boolean 22 | last_updated: string 23 | mode_int: number 24 | passcount: number 25 | playcount: number 26 | ranked: number 27 | url: string 28 | checksum: string 29 | beatmapset: Beatmapset 30 | failtimes: Failtimes 31 | max_combo: number 32 | owners: Owner[] 33 | } 34 | 35 | export interface Owner { 36 | id: number 37 | username: string 38 | } 39 | 40 | export interface Failtimes { 41 | fail: number[] 42 | exit: number[] 43 | } 44 | 45 | export interface Beatmapset { 46 | artist: string 47 | artist_unicode: string 48 | covers: Covers 49 | creator: string 50 | favourite_count: number 51 | hype: null 52 | id: number 53 | nsfw: boolean 54 | offset: number 55 | play_count: number 56 | preview_url: string 57 | source: string 58 | spotlight: boolean 59 | status: string 60 | title: string 61 | title_unicode: string 62 | track_id: null 63 | user_id: number 64 | video: boolean 65 | bpm: number 66 | can_be_hyped: boolean 67 | deleted_at: null 68 | discussion_enabled: boolean 69 | discussion_locked: boolean 70 | is_scoreable: boolean 71 | last_updated: string 72 | legacy_thread_url: string 73 | nominations_summary: Nominationssummary 74 | ranked: number 75 | ranked_date: string 76 | storyboard: boolean 77 | submitted_date: string 78 | tags: string 79 | availability: Availability 80 | ratings: number[] 81 | } 82 | 83 | export interface Availability { 84 | download_disabled: boolean 85 | more_information: null 86 | } 87 | 88 | export interface Nominationssummary { 89 | current: number 90 | eligible_main_rulesets: string[] 91 | required_meta: Requiredmeta 92 | } 93 | 94 | export interface Requiredmeta { 95 | main_ruleset: number 96 | non_main_ruleset: number 97 | } 98 | 99 | export interface Covers { 100 | cover: string 101 | 'cover@2x': string 102 | card: string 103 | 'card@2x': string 104 | list: string 105 | 'list@2x': string 106 | slimcover: string 107 | 'slimcover@2x': string 108 | } -------------------------------------------------------------------------------- /types/v2/beatmaps_lookup_set.ts: -------------------------------------------------------------------------------- 1 | export interface beatmaps_lookup_set_response { 2 | artist: string 3 | artist_unicode: string 4 | covers: Covers 5 | creator: string 6 | favourite_count: number 7 | hype: null 8 | id: number 9 | nsfw: boolean 10 | offset: number 11 | play_count: number 12 | preview_url: string 13 | source: string 14 | spotlight: boolean 15 | status: string 16 | title: string 17 | title_unicode: string 18 | track_id: number 19 | user_id: number 20 | video: boolean 21 | bpm: number 22 | can_be_hyped: boolean 23 | deleted_at: null 24 | discussion_enabled: boolean 25 | discussion_locked: boolean 26 | is_scoreable: boolean 27 | last_updated: string 28 | legacy_thread_url: string 29 | nominations_summary: Nominationssummary 30 | ranked: number 31 | ranked_date: null 32 | storyboard: boolean 33 | submitted_date: string 34 | tags: string 35 | availability: Availability 36 | beatmaps: Beatmap[] 37 | converts: any[] 38 | current_nominations: any[] 39 | description: Description 40 | genre: Genre 41 | language: Genre 42 | pack_tags: any[] 43 | ratings: number[] 44 | recent_favourites: any[] 45 | related_users: Relateduser[] 46 | related_tags: any[] 47 | user: Relateduser 48 | } 49 | 50 | export interface Relateduser { 51 | avatar_url: string 52 | country_code: string 53 | default_group: string 54 | id: number 55 | is_active: boolean 56 | is_bot: boolean 57 | is_deleted: boolean 58 | is_online: boolean 59 | is_supporter: boolean 60 | last_visit: string 61 | pm_friends_only: boolean 62 | profile_colour: null 63 | username: string 64 | } 65 | 66 | export interface Genre { 67 | id: number 68 | name: string 69 | } 70 | 71 | export interface Description { 72 | description: string 73 | } 74 | 75 | export interface Beatmap { 76 | beatmapset_id: number 77 | difficulty_rating: number 78 | id: number 79 | mode: string 80 | status: string 81 | total_length: number 82 | user_id: number 83 | version: string 84 | accuracy: number 85 | ar: number 86 | bpm: number 87 | convert: boolean 88 | count_circles: number 89 | count_sliders: number 90 | count_spinners: number 91 | cs: number 92 | deleted_at: null 93 | drain: number 94 | hit_length: number 95 | is_scoreable: boolean 96 | last_updated: string 97 | mode_int: number 98 | passcount: number 99 | playcount: number 100 | ranked: number 101 | url: string 102 | checksum: string 103 | failtimes: Failtimes 104 | max_combo: number 105 | owners: Owner[] 106 | top_tag_ids: any[] 107 | } 108 | 109 | export interface Owner { 110 | id: number 111 | username: string 112 | } 113 | 114 | export interface Failtimes { 115 | exit: number[] 116 | fail: number[] 117 | } 118 | 119 | export interface Availability { 120 | download_disabled: boolean 121 | more_information: null 122 | } 123 | 124 | export interface Nominationssummary { 125 | current: number 126 | eligible_main_rulesets: string[] 127 | required_meta: Requiredmeta 128 | } 129 | 130 | export interface Requiredmeta { 131 | main_ruleset: number 132 | non_main_ruleset: number 133 | } 134 | 135 | export interface Covers { 136 | cover: string 137 | 'cover@2x': string 138 | card: string 139 | 'card@2x': string 140 | list: string 141 | 'list@2x': string 142 | slimcover: string 143 | 'slimcover@2x': string 144 | } -------------------------------------------------------------------------------- /types/v2/beatmaps_packs_details.ts: -------------------------------------------------------------------------------- 1 | export interface beatmaps_packs_details_response { 2 | author: string 3 | date: string 4 | name: string 5 | no_diff_reduction: boolean 6 | ruleset_id: null 7 | tag: string 8 | url: string 9 | beatmapsets: Beatmapset[] 10 | user_completion_data: Usercompletiondata 11 | } 12 | 13 | export interface Usercompletiondata { 14 | completed: boolean 15 | beatmapset_ids: any[] 16 | } 17 | 18 | export interface Beatmapset { 19 | artist: string 20 | artist_unicode: string 21 | covers: Covers 22 | creator: string 23 | favourite_count: number 24 | hype: null 25 | id: number 26 | nsfw: boolean 27 | offset: number 28 | play_count: number 29 | preview_url: string 30 | source: string 31 | spotlight: boolean 32 | status: string 33 | title: string 34 | title_unicode: string 35 | track_id: null | number 36 | user_id: number 37 | video: boolean 38 | bpm: number 39 | can_be_hyped: boolean 40 | deleted_at: null 41 | discussion_enabled: boolean 42 | discussion_locked: boolean 43 | is_scoreable: boolean 44 | last_updated: string 45 | legacy_thread_url: string 46 | nominations_summary: Nominationssummary 47 | ranked: number 48 | ranked_date: string 49 | storyboard: boolean 50 | submitted_date: string 51 | tags: string 52 | availability: Availability 53 | } 54 | 55 | export interface Availability { 56 | download_disabled: boolean 57 | more_information: null | string 58 | } 59 | 60 | export interface Nominationssummary { 61 | current: number 62 | eligible_main_rulesets: string[] 63 | required_meta: Requiredmeta 64 | } 65 | 66 | export interface Requiredmeta { 67 | main_ruleset: number 68 | non_main_ruleset: number 69 | } 70 | 71 | export interface Covers { 72 | cover: string 73 | 'cover@2x': string 74 | card: string 75 | 'card@2x': string 76 | list: string 77 | 'list@2x': string 78 | slimcover: string 79 | 'slimcover@2x': string 80 | } -------------------------------------------------------------------------------- /types/v2/beatmaps_packs_list.ts: -------------------------------------------------------------------------------- 1 | export interface BeatmapsPacksListResponse { 2 | beatmap_packs: BeatmapPack[] 3 | cursor: Cursor 4 | cursor_string: string 5 | } 6 | 7 | export interface BeatmapPack { 8 | author: string 9 | date: string 10 | name: string 11 | no_diff_reduction: boolean 12 | ruleset_id?: number 13 | tag: string 14 | url: string 15 | } 16 | 17 | export interface Cursor { 18 | pack_id: number 19 | } -------------------------------------------------------------------------------- /types/v2/changelogs_details.ts: -------------------------------------------------------------------------------- 1 | export interface changelogsDetailsResponse { 2 | created_at: string 3 | display_version: string 4 | id: number 5 | users: number 6 | version: string 7 | youtube_id: any 8 | update_stream: UpdateStream 9 | changelog_entries: ChangelogEntry[] 10 | versions: Versions 11 | } 12 | 13 | export interface UpdateStream { 14 | id: number 15 | name: string 16 | display_name: string 17 | is_featured: boolean 18 | } 19 | 20 | export interface ChangelogEntry { 21 | id: number 22 | repository: string 23 | github_pull_request_id: number 24 | github_url: string 25 | url: any 26 | type: string 27 | category: string 28 | title: string 29 | major: boolean 30 | created_at: string 31 | github_user: GithubUser 32 | message: any 33 | message_html: any 34 | } 35 | 36 | export interface GithubUser { 37 | display_name: string 38 | github_url: string 39 | github_username: string 40 | id: number 41 | osu_username?: string 42 | user_id?: number 43 | user_url?: string 44 | } 45 | 46 | export interface Versions { 47 | next: Next 48 | previous: Previous 49 | } 50 | 51 | export interface Next { 52 | created_at: string 53 | display_version: string 54 | id: number 55 | users: number 56 | version: string 57 | youtube_id: any 58 | update_stream: UpdateStream2 59 | } 60 | 61 | export interface UpdateStream2 { 62 | id: number 63 | name: string 64 | display_name: string 65 | is_featured: boolean 66 | } 67 | 68 | export interface Previous { 69 | created_at: string 70 | display_version: string 71 | id: number 72 | users: number 73 | version: string 74 | youtube_id: any 75 | update_stream: UpdateStream3 76 | } 77 | 78 | export interface UpdateStream3 { 79 | id: number 80 | name: string 81 | display_name: string 82 | is_featured: boolean 83 | } 84 | -------------------------------------------------------------------------------- /types/v2/changelogs_list_all.ts: -------------------------------------------------------------------------------- 1 | export interface ChangelogsListAllResponse { 2 | streams: Stream[] 3 | builds: Build[] 4 | search: Search 5 | } 6 | 7 | export interface Stream { 8 | id: number 9 | name: string 10 | display_name: string 11 | is_featured: boolean 12 | latest_build: LatestBuild 13 | user_count: number 14 | } 15 | 16 | export interface LatestBuild { 17 | created_at: string 18 | display_version: string 19 | id: number 20 | users: number 21 | version: string 22 | youtube_id?: string 23 | update_stream: UpdateStream 24 | } 25 | 26 | export interface UpdateStream { 27 | id: number 28 | name: string 29 | display_name: string 30 | is_featured: boolean 31 | } 32 | 33 | export interface Build { 34 | created_at: string 35 | display_version: string 36 | id: number 37 | users: number 38 | version: string 39 | youtube_id?: string 40 | update_stream: UpdateStream2 41 | changelog_entries: ChangelogEntry[] 42 | } 43 | 44 | export interface UpdateStream2 { 45 | id: number 46 | name: string 47 | display_name: string 48 | is_featured: boolean 49 | } 50 | 51 | export interface ChangelogEntry { 52 | id?: number 53 | repository?: string 54 | github_pull_request_id?: number 55 | github_url?: string 56 | url: any 57 | type: string 58 | category: string 59 | title: string 60 | major: boolean 61 | created_at: string 62 | github_user: GithubUser 63 | message?: string 64 | message_html?: string 65 | } 66 | 67 | export interface GithubUser { 68 | display_name: string 69 | github_url?: string 70 | github_username?: string 71 | id?: number 72 | osu_username?: string 73 | user_id?: number 74 | user_url?: string 75 | } 76 | 77 | export interface Search { 78 | stream: any 79 | from: any 80 | to: any 81 | max_id: any 82 | limit: number 83 | } 84 | -------------------------------------------------------------------------------- /types/v2/changelogs_list_lookup.ts: -------------------------------------------------------------------------------- 1 | export interface ChangelogsListLookupResponse { 2 | created_at: string 3 | display_version: string 4 | id: number 5 | users: number 6 | version: string 7 | youtube_id: any 8 | update_stream: UpdateStream 9 | changelog_entries: ChangelogEntry[] 10 | versions: Versions 11 | } 12 | 13 | export interface UpdateStream { 14 | id: number 15 | name: string 16 | display_name: string 17 | is_featured: boolean 18 | } 19 | 20 | export interface ChangelogEntry { 21 | id: number 22 | repository: string 23 | github_pull_request_id: number 24 | github_url: string 25 | url: any 26 | type: string 27 | category: string 28 | title: string 29 | major: boolean 30 | created_at: string 31 | github_user: GithubUser 32 | message: any 33 | message_html: any 34 | } 35 | 36 | export interface GithubUser { 37 | display_name: string 38 | github_url: string 39 | github_username: string 40 | id: number 41 | osu_username?: string 42 | user_id?: number 43 | user_url?: string 44 | } 45 | 46 | export interface Versions { 47 | previous: Previous 48 | } 49 | 50 | export interface Previous { 51 | created_at: string 52 | display_version: string 53 | id: number 54 | users: number 55 | version: string 56 | youtube_id: any 57 | update_stream: UpdateStream2 58 | } 59 | 60 | export interface UpdateStream2 { 61 | id: number 62 | name: string 63 | display_name: string 64 | is_featured: boolean 65 | } 66 | -------------------------------------------------------------------------------- /types/v2/chat_actions_join.ts: -------------------------------------------------------------------------------- 1 | export interface chatActionsJoinResponse { 2 | channel_id: number 3 | description: string 4 | icon: any 5 | message_length_limit: number 6 | moderated: boolean 7 | name: string 8 | type: string 9 | uuid: any 10 | current_user_attributes: CurrentUserAttributes 11 | last_message_id: number 12 | last_read_id: any 13 | users: any[] 14 | } 15 | 16 | export interface CurrentUserAttributes { 17 | can_message: boolean 18 | can_message_error: any 19 | last_read_id: any 20 | } 21 | -------------------------------------------------------------------------------- /types/v2/chat_actions_keepalive.ts: -------------------------------------------------------------------------------- 1 | // export interface ChatActionsKeepaliveResponse { 2 | // silences: Silence[] 3 | // } 4 | 5 | export interface ChatActionsKeepaliveResponse { 6 | id: number 7 | user_id: number 8 | } 9 | -------------------------------------------------------------------------------- /types/v2/chat_actions_new.ts: -------------------------------------------------------------------------------- 1 | export interface ChatActionsNewResponse { 2 | channel: Channel 3 | message: Message 4 | new_channel_id: number 5 | } 6 | 7 | export interface Channel { 8 | channel_id: number 9 | description: string 10 | icon: string 11 | message_length_limit: number 12 | moderated: boolean 13 | name: string 14 | type: string 15 | uuid: any 16 | last_message_id: number 17 | users: number[] 18 | } 19 | 20 | export interface Message { 21 | channel_id: number 22 | content: string 23 | is_action: boolean 24 | message_id: number 25 | sender_id: number 26 | timestamp: string 27 | type: string 28 | sender: Sender 29 | } 30 | 31 | export interface Sender { 32 | avatar_url: string 33 | country_code: string 34 | default_group: string 35 | id: number 36 | is_active: boolean 37 | is_bot: boolean 38 | is_deleted: boolean 39 | is_online: boolean 40 | is_supporter: boolean 41 | last_visit: any 42 | pm_friends_only: boolean 43 | profile_colour: any 44 | username: string 45 | } 46 | -------------------------------------------------------------------------------- /types/v2/chat_actions_send.ts: -------------------------------------------------------------------------------- 1 | export interface chatActionsSendResponse { 2 | channel_id: number 3 | content: string 4 | is_action: boolean 5 | message_id: number 6 | sender_id: number 7 | timestamp: string 8 | type: string 9 | sender: Sender 10 | } 11 | 12 | export interface Sender { 13 | avatar_url: string 14 | country_code: string 15 | default_group: string 16 | id: number 17 | is_active: boolean 18 | is_bot: boolean 19 | is_deleted: boolean 20 | is_online: boolean 21 | is_supporter: boolean 22 | last_visit: any 23 | pm_friends_only: boolean 24 | profile_colour: any 25 | username: string 26 | } 27 | -------------------------------------------------------------------------------- /types/v2/chat_channels_list.ts: -------------------------------------------------------------------------------- 1 | export interface chatChannelsListResponse { 2 | channel_id: number 3 | description: string 4 | icon: any 5 | message_length_limit: number 6 | moderated: boolean 7 | name: string 8 | type: string 9 | uuid: any 10 | } 11 | -------------------------------------------------------------------------------- /types/v2/chat_details.ts: -------------------------------------------------------------------------------- 1 | export interface ChatDetailsResponse { 2 | channel: Channel 3 | users: User[] 4 | } 5 | 6 | export interface Channel { 7 | channel_id: number 8 | description: string 9 | icon: string 10 | message_length_limit: number 11 | moderated: boolean 12 | name: string 13 | type: string 14 | uuid: any 15 | current_user_attributes: CurrentUserAttributes 16 | last_message_id: number 17 | last_read_id: number 18 | users: number[] 19 | } 20 | 21 | export interface CurrentUserAttributes { 22 | can_message: boolean 23 | can_message_error: any 24 | last_read_id: number 25 | } 26 | 27 | export interface User { 28 | avatar_url: string 29 | country_code: string 30 | default_group: string 31 | id: number 32 | is_active: boolean 33 | is_bot: boolean 34 | is_deleted: boolean 35 | is_online: boolean 36 | is_supporter: boolean 37 | last_visit?: string 38 | pm_friends_only: boolean 39 | profile_colour: any 40 | username: string 41 | country: Country 42 | cover: Cover 43 | groups: any[] 44 | } 45 | 46 | export interface Country { 47 | code: string 48 | name: string 49 | } 50 | 51 | export interface Cover { 52 | custom_url: string 53 | url: string 54 | id: any 55 | } 56 | -------------------------------------------------------------------------------- /types/v2/chat_list.ts: -------------------------------------------------------------------------------- 1 | export interface ChatListResponse { 2 | channel_id: number 3 | description: string 4 | icon?: string 5 | message_length_limit: number 6 | moderated: boolean 7 | name: string 8 | type: string 9 | uuid: any 10 | current_user_attributes: CurrentUserAttributes 11 | last_message_id: number 12 | last_read_id?: number 13 | users: number[] 14 | } 15 | 16 | export interface CurrentUserAttributes { 17 | can_message: boolean 18 | can_message_error: any 19 | last_read_id?: number 20 | } 21 | -------------------------------------------------------------------------------- /types/v2/chat_messages.ts: -------------------------------------------------------------------------------- 1 | export interface ChatMessagesResponse { 2 | channel_id: number 3 | content: string 4 | is_action: boolean 5 | message_id: number 6 | sender_id: number 7 | timestamp: string 8 | type: string 9 | sender: Sender 10 | } 11 | 12 | export interface Sender { 13 | avatar_url: string 14 | country_code: string 15 | default_group: string 16 | id: number 17 | is_active: boolean 18 | is_bot: boolean 19 | is_deleted: boolean 20 | is_online: boolean 21 | is_supporter: boolean 22 | last_visit?: string 23 | pm_friends_only: boolean 24 | profile_colour: any 25 | username: string 26 | } 27 | -------------------------------------------------------------------------------- /types/v2/chat_updates.ts: -------------------------------------------------------------------------------- 1 | export interface ChatUpdatesResponse { 2 | presence: Presence[] 3 | silences: Silence[] 4 | } 5 | 6 | export interface Silence { 7 | id: number 8 | user_id: number 9 | } 10 | 11 | 12 | export interface Presence { 13 | channel_id: number 14 | description: string 15 | icon?: string 16 | message_length_limit: number 17 | moderated: boolean 18 | name: string 19 | type: string 20 | uuid: any 21 | current_user_attributes: CurrentUserAttributes 22 | last_message_id: number 23 | last_read_id?: number 24 | users: number[] 25 | } 26 | 27 | export interface CurrentUserAttributes { 28 | can_message: boolean 29 | can_message_error?: string 30 | last_read_id?: number 31 | } 32 | -------------------------------------------------------------------------------- /types/v2/comments_actions_delete.ts: -------------------------------------------------------------------------------- 1 | export interface CommentsActionsDeleteResponse { 2 | comments: Comment[] 3 | has_more: boolean 4 | has_more_id: any 5 | included_comments: any[] 6 | pinned_comments: any[] 7 | user_votes: any[] 8 | user_follow: boolean 9 | users: User[] 10 | sort: string 11 | cursor: Cursor 12 | top_level_count: number 13 | total: number 14 | commentable_meta: CommentableMeum[] 15 | } 16 | 17 | export interface Comment { 18 | id: number 19 | parent_id: any 20 | user_id: number 21 | pinned: boolean 22 | replies_count: number 23 | votes_count: number 24 | commentable_type: string 25 | commentable_id: number 26 | legacy_name: any 27 | created_at: string 28 | updated_at: string 29 | deleted_at: string 30 | edited_at: string 31 | edited_by_id: number 32 | } 33 | 34 | export interface User { 35 | avatar_url: string 36 | country_code: string 37 | default_group: string 38 | id: number 39 | is_active: boolean 40 | is_bot: boolean 41 | is_deleted: boolean 42 | is_online: boolean 43 | is_supporter: boolean 44 | last_visit: any 45 | pm_friends_only: boolean 46 | profile_colour: any 47 | username: string 48 | } 49 | 50 | export interface Cursor { 51 | created_at: string 52 | id: number 53 | } 54 | 55 | export interface CommentableMeum { 56 | current_user_attributes?: CurrentUserAttributes 57 | id?: number 58 | type?: string 59 | title: string 60 | url?: string 61 | owner_id?: number 62 | owner_title?: string 63 | } 64 | 65 | export interface CurrentUserAttributes { 66 | can_new_comment_reason: any 67 | } 68 | -------------------------------------------------------------------------------- /types/v2/comments_actions_edit.ts: -------------------------------------------------------------------------------- 1 | export interface CommentsActionsEditResponse { 2 | comments: Comment[] 3 | has_more: boolean 4 | has_more_id: any 5 | included_comments: any[] 6 | pinned_comments: any[] 7 | user_votes: any[] 8 | user_follow: boolean 9 | users: User[] 10 | sort: string 11 | cursor: Cursor 12 | top_level_count: number 13 | total: number 14 | commentable_meta: CommentableMeum[] 15 | } 16 | 17 | export interface Comment { 18 | id: number 19 | parent_id: any 20 | user_id: number 21 | pinned: boolean 22 | replies_count: number 23 | votes_count: number 24 | commentable_type: string 25 | commentable_id: number 26 | legacy_name: any 27 | created_at: string 28 | updated_at: string 29 | deleted_at: any 30 | edited_at: string 31 | edited_by_id: number 32 | message: string 33 | message_html: string 34 | } 35 | 36 | export interface User { 37 | avatar_url: string 38 | country_code: string 39 | default_group: string 40 | id: number 41 | is_active: boolean 42 | is_bot: boolean 43 | is_deleted: boolean 44 | is_online: boolean 45 | is_supporter: boolean 46 | last_visit: any 47 | pm_friends_only: boolean 48 | profile_colour: any 49 | username: string 50 | } 51 | 52 | export interface Cursor { 53 | created_at: string 54 | id: number 55 | } 56 | 57 | export interface CommentableMeum { 58 | current_user_attributes?: CurrentUserAttributes 59 | id?: number 60 | type?: string 61 | title: string 62 | url?: string 63 | owner_id?: number 64 | owner_title?: string 65 | } 66 | 67 | export interface CurrentUserAttributes { 68 | can_new_comment_reason: any 69 | } 70 | -------------------------------------------------------------------------------- /types/v2/comments_actions_new.ts: -------------------------------------------------------------------------------- 1 | export interface CommentsActionsNewResponse { 2 | comments: Comment[] 3 | has_more: boolean 4 | has_more_id: any 5 | included_comments: any[] 6 | pinned_comments: any[] 7 | user_votes: any[] 8 | user_follow: boolean 9 | users: User[] 10 | sort: string 11 | cursor: Cursor 12 | top_level_count: number 13 | total: number 14 | commentable_meta: CommentableMeum[] 15 | } 16 | 17 | export interface Comment { 18 | id: number 19 | parent_id: any 20 | user_id: number 21 | pinned: boolean 22 | replies_count: number 23 | votes_count: number 24 | commentable_type: string 25 | commentable_id: number 26 | legacy_name: any 27 | created_at: string 28 | updated_at: string 29 | deleted_at: any 30 | edited_at: any 31 | edited_by_id: any 32 | message: string 33 | message_html: string 34 | } 35 | 36 | export interface User { 37 | avatar_url: string 38 | country_code: string 39 | default_group: string 40 | id: number 41 | is_active: boolean 42 | is_bot: boolean 43 | is_deleted: boolean 44 | is_online: boolean 45 | is_supporter: boolean 46 | last_visit: any 47 | pm_friends_only: boolean 48 | profile_colour: any 49 | username: string 50 | } 51 | 52 | export interface Cursor { 53 | created_at: string 54 | id: number 55 | } 56 | 57 | export interface CommentableMeum { 58 | current_user_attributes?: CurrentUserAttributes 59 | id?: number 60 | type?: string 61 | title: string 62 | url?: string 63 | owner_id?: number 64 | owner_title?: string 65 | } 66 | 67 | export interface CurrentUserAttributes { 68 | can_new_comment_reason: any 69 | } 70 | -------------------------------------------------------------------------------- /types/v2/comments_actions_unvote.ts: -------------------------------------------------------------------------------- 1 | export interface CommentsActionsUnvoteResponse { 2 | comments: Comment[] 3 | has_more: boolean 4 | has_more_id: any 5 | included_comments: any[] 6 | pinned_comments: any[] 7 | user_votes: any[] 8 | user_follow: boolean 9 | users: User[] 10 | sort: string 11 | cursor: Cursor 12 | top_level_count: number 13 | total: number 14 | commentable_meta: CommentableMeum[] 15 | } 16 | 17 | export interface Comment { 18 | id: number 19 | parent_id: any 20 | user_id: number 21 | pinned: boolean 22 | replies_count: number 23 | votes_count: number 24 | commentable_type: string 25 | commentable_id: number 26 | legacy_name: any 27 | created_at: string 28 | updated_at: string 29 | deleted_at: any 30 | edited_at: any 31 | edited_by_id: any 32 | message: string 33 | message_html: string 34 | } 35 | 36 | export interface User { 37 | avatar_url: string 38 | country_code: string 39 | default_group: string 40 | id: number 41 | is_active: boolean 42 | is_bot: boolean 43 | is_deleted: boolean 44 | is_online: boolean 45 | is_supporter: boolean 46 | last_visit: string 47 | pm_friends_only: boolean 48 | profile_colour: any 49 | username: string 50 | } 51 | 52 | export interface Cursor { 53 | created_at: string 54 | id: number 55 | } 56 | 57 | export interface CommentableMeum { 58 | current_user_attributes?: CurrentUserAttributes 59 | id?: number 60 | type?: string 61 | title: string 62 | url?: string 63 | owner_id?: number 64 | owner_title?: string 65 | } 66 | 67 | export interface CurrentUserAttributes { 68 | can_new_comment_reason: any 69 | } 70 | -------------------------------------------------------------------------------- /types/v2/comments_actions_vote.ts: -------------------------------------------------------------------------------- 1 | export interface CommentsActionsVoteResponse { 2 | comments: Comment[] 3 | has_more: boolean 4 | has_more_id: any 5 | included_comments: any[] 6 | pinned_comments: any[] 7 | user_votes: number[] 8 | user_follow: boolean 9 | users: User[] 10 | sort: string 11 | cursor: Cursor 12 | top_level_count: number 13 | total: number 14 | commentable_meta: CommentableMeum[] 15 | } 16 | 17 | export interface Comment { 18 | id: number 19 | parent_id: any 20 | user_id: number 21 | pinned: boolean 22 | replies_count: number 23 | votes_count: number 24 | commentable_type: string 25 | commentable_id: number 26 | legacy_name: any 27 | created_at: string 28 | updated_at: string 29 | deleted_at: any 30 | edited_at: any 31 | edited_by_id: any 32 | message: string 33 | message_html: string 34 | } 35 | 36 | export interface User { 37 | avatar_url: string 38 | country_code: string 39 | default_group: string 40 | id: number 41 | is_active: boolean 42 | is_bot: boolean 43 | is_deleted: boolean 44 | is_online: boolean 45 | is_supporter: boolean 46 | last_visit: string 47 | pm_friends_only: boolean 48 | profile_colour: any 49 | username: string 50 | } 51 | 52 | export interface Cursor { 53 | created_at: string 54 | id: number 55 | } 56 | 57 | export interface CommentableMeum { 58 | current_user_attributes?: CurrentUserAttributes 59 | id?: number 60 | type?: string 61 | title: string 62 | url?: string 63 | owner_id?: number 64 | owner_title?: string 65 | } 66 | 67 | export interface CurrentUserAttributes { 68 | can_new_comment_reason: any 69 | } 70 | -------------------------------------------------------------------------------- /types/v2/comments_details.ts: -------------------------------------------------------------------------------- 1 | export interface CommentsDetailsResponse { 2 | comments: Comment[] 3 | has_more: boolean 4 | has_more_id: number 5 | included_comments: IncludedComment[] 6 | pinned_comments: any[] 7 | user_votes: any[] 8 | user_follow: boolean 9 | users: User[] 10 | sort: string 11 | cursor: Cursor 12 | commentable_meta: CommentableMeum[] 13 | } 14 | 15 | export interface Comment { 16 | id: number 17 | parent_id: any 18 | user_id: number 19 | pinned: boolean 20 | replies_count: number 21 | votes_count: number 22 | commentable_type: string 23 | commentable_id: number 24 | legacy_name: any 25 | created_at: string 26 | updated_at: string 27 | deleted_at: any 28 | edited_at: any 29 | edited_by_id: any 30 | message: string 31 | message_html: string 32 | } 33 | 34 | export interface IncludedComment { 35 | id: number 36 | parent_id: number 37 | user_id: number 38 | pinned: boolean 39 | replies_count: number 40 | votes_count: number 41 | commentable_type: string 42 | commentable_id: number 43 | legacy_name: any 44 | created_at: string 45 | updated_at: string 46 | deleted_at: any 47 | edited_at: any 48 | edited_by_id: any 49 | message: string 50 | message_html: string 51 | } 52 | 53 | export interface User { 54 | avatar_url: string 55 | country_code: string 56 | default_group: string 57 | id: number 58 | is_active: boolean 59 | is_bot: boolean 60 | is_deleted: boolean 61 | is_online: boolean 62 | is_supporter: boolean 63 | last_visit?: string 64 | pm_friends_only: boolean 65 | profile_colour?: string 66 | username: string 67 | } 68 | 69 | export interface Cursor { 70 | created_at: string 71 | id: number 72 | } 73 | 74 | export interface CommentableMeum { 75 | current_user_attributes?: CurrentUserAttributes 76 | id?: number 77 | type?: string 78 | title: string 79 | url?: string 80 | owner_id: any 81 | owner_title: any 82 | } 83 | 84 | export interface CurrentUserAttributes { 85 | can_new_comment_reason: string 86 | } 87 | -------------------------------------------------------------------------------- /types/v2/comments_list.ts: -------------------------------------------------------------------------------- 1 | export interface CommentsListResponse { 2 | comments: Comment[] 3 | has_more: boolean 4 | has_more_id: any 5 | included_comments: any[] 6 | pinned_comments: PinnedComment[] 7 | user_votes: any[] 8 | user_follow: boolean 9 | users: User[] 10 | sort: string 11 | cursor?: Cursor 12 | top_level_count: number 13 | total: number 14 | commentable_meta: CommentableMeum[] 15 | } 16 | 17 | export interface Comment { 18 | id: number 19 | parent_id?: number 20 | user_id: number 21 | pinned: boolean 22 | replies_count: number 23 | votes_count: number 24 | commentable_type: string 25 | commentable_id: number 26 | legacy_name: any 27 | created_at: string 28 | updated_at: string 29 | deleted_at?: string 30 | edited_at?: string 31 | edited_by_id?: number 32 | message?: string 33 | message_html?: string 34 | } 35 | 36 | export interface PinnedComment { 37 | id: number 38 | parent_id: any 39 | user_id: number 40 | pinned: boolean 41 | replies_count: number 42 | votes_count: number 43 | commentable_type: string 44 | commentable_id: number 45 | legacy_name: any 46 | created_at: string 47 | updated_at: string 48 | deleted_at: any 49 | edited_at: any 50 | edited_by_id: any 51 | message: string 52 | message_html: string 53 | } 54 | 55 | export interface User { 56 | avatar_url: string 57 | country_code: string 58 | default_group: string 59 | id: number 60 | is_active: boolean 61 | is_bot: boolean 62 | is_deleted: boolean 63 | is_online: boolean 64 | is_supporter: boolean 65 | last_visit?: string 66 | pm_friends_only: boolean 67 | profile_colour?: string 68 | username: string 69 | } 70 | 71 | export interface Cursor { 72 | created_at: string 73 | id: number 74 | } 75 | 76 | export interface CommentableMeum { 77 | current_user_attributes?: CurrentUserAttributes 78 | id?: number 79 | type?: string 80 | title: string 81 | url?: string 82 | owner_id: any 83 | owner_title: any 84 | } 85 | 86 | export interface CurrentUserAttributes { 87 | can_new_comment_reason: string 88 | } 89 | -------------------------------------------------------------------------------- /types/v2/forums_details.ts: -------------------------------------------------------------------------------- 1 | export interface forums_details_response { 2 | forum: Forum 3 | topics: Topic[] 4 | pinned_topics: Pinnedtopic[] 5 | } 6 | 7 | export interface Pinnedtopic { 8 | created_at: string 9 | deleted_at: null 10 | first_post_id: number 11 | forum_id: number 12 | id: number 13 | is_locked: boolean 14 | last_post_id: number 15 | post_count: number 16 | title: string 17 | type: string 18 | updated_at: string 19 | user_id: number 20 | poll: null 21 | } 22 | 23 | export interface Topic { 24 | created_at: string 25 | deleted_at: null 26 | first_post_id: number 27 | forum_id: number 28 | id: number 29 | is_locked: boolean 30 | last_post_id: number 31 | post_count: number 32 | title: string 33 | type: string 34 | updated_at: string 35 | user_id: number 36 | poll: Poll | null 37 | } 38 | 39 | export interface Poll { 40 | allow_vote_change: boolean 41 | ended_at: string 42 | hide_incomplete_results: boolean 43 | last_vote_at: string 44 | max_votes: number 45 | started_at: string 46 | title: Title 47 | total_vote_count: number 48 | options: Option[] 49 | } 50 | 51 | export interface Option { 52 | id: number 53 | text: Title 54 | vote_count: number 55 | } 56 | 57 | export interface Title { 58 | bbcode: string 59 | html: string 60 | } 61 | 62 | export interface Forum { 63 | id: number 64 | name: string 65 | description: string 66 | subforums: Subforum[] 67 | } 68 | 69 | export interface Subforum { 70 | id: number 71 | name: string 72 | description: string 73 | subforums: any[] 74 | } -------------------------------------------------------------------------------- /types/v2/forums_list.ts: -------------------------------------------------------------------------------- 1 | export interface forums_list_response { 2 | id: number 3 | name: string 4 | description: string 5 | subforums?: forums_list_response[] 6 | } -------------------------------------------------------------------------------- /types/v2/forums_topics_actions_create.ts: -------------------------------------------------------------------------------- 1 | export interface ForumsTopicsActionsCreateResponse { 2 | topic: Topic 3 | post: Post 4 | } 5 | 6 | export interface Topic { 7 | created_at: string 8 | deleted_at: any 9 | first_post_id: number 10 | forum_id: number 11 | id: number 12 | is_locked: boolean 13 | last_post_id: number 14 | post_count: number 15 | title: string 16 | type: string 17 | updated_at: string 18 | user_id: number 19 | poll: any 20 | } 21 | 22 | export interface Post { 23 | created_at: string 24 | deleted_at: any 25 | edited_at: any 26 | edited_by_id: any 27 | forum_id: number 28 | id: number 29 | topic_id: number 30 | user_id: number 31 | body: Body 32 | } 33 | 34 | export interface Body { 35 | html: string 36 | raw: string 37 | } 38 | -------------------------------------------------------------------------------- /types/v2/forums_topics_actions_edit_post.ts: -------------------------------------------------------------------------------- 1 | export interface ForumsTopicsActionsEditPostResponse { 2 | created_at: string 3 | deleted_at: any 4 | edited_at: string 5 | edited_by_id: number 6 | forum_id: number 7 | id: number 8 | topic_id: number 9 | user_id: number 10 | body: Body 11 | } 12 | 13 | export interface Body { 14 | html: string 15 | raw: string 16 | } 17 | -------------------------------------------------------------------------------- /types/v2/forums_topics_actions_edit_topic.ts: -------------------------------------------------------------------------------- 1 | export interface ForumsTopicsActionsEditTopicResponse { 2 | created_at: string 3 | deleted_at: any 4 | first_post_id: number 5 | forum_id: number 6 | id: number 7 | is_locked: boolean 8 | last_post_id: number 9 | post_count: number 10 | title: string 11 | type: string 12 | updated_at: string 13 | user_id: number 14 | poll: any 15 | } -------------------------------------------------------------------------------- /types/v2/forums_topics_actions_reply.ts: -------------------------------------------------------------------------------- 1 | export interface ForumsTopicsActionsReplyResponse { 2 | created_at: string 3 | deleted_at: any 4 | edited_at: any 5 | edited_by_id: any 6 | forum_id: number 7 | id: number 8 | topic_id: number 9 | user_id: number 10 | body: Body 11 | } 12 | 13 | export interface Body { 14 | html: string 15 | raw: string 16 | } 17 | -------------------------------------------------------------------------------- /types/v2/forums_topics_details.ts: -------------------------------------------------------------------------------- 1 | export interface ForumsTopicsDetailsResponse { 2 | posts: Post[] 3 | search: Search 4 | topic: Topic 5 | cursor: Cursor 6 | cursor_string: string 7 | } 8 | 9 | export interface Post { 10 | created_at: string 11 | deleted_at: any 12 | edited_at?: string 13 | edited_by_id?: number 14 | forum_id: number 15 | id: number 16 | topic_id: number 17 | user_id: number 18 | body: Body 19 | } 20 | 21 | export interface Body { 22 | html: string 23 | raw: string 24 | } 25 | 26 | export interface Search { 27 | limit: number 28 | sort: string 29 | } 30 | 31 | export interface Topic { 32 | created_at: string 33 | deleted_at: any 34 | first_post_id: number 35 | forum_id: number 36 | id: number 37 | is_locked: boolean 38 | last_post_id: number 39 | post_count: number 40 | title: string 41 | type: string 42 | updated_at: string 43 | user_id: number 44 | poll: any 45 | } 46 | 47 | export interface Cursor { 48 | id: number 49 | } 50 | -------------------------------------------------------------------------------- /types/v2/forums_topics_list.ts: -------------------------------------------------------------------------------- 1 | export interface forums_topics_list_response { 2 | topics: Topic[] 3 | cursor: Cursor 4 | cursor_string: string 5 | } 6 | 7 | export interface Cursor { 8 | topic_last_post_time: string 9 | } 10 | 11 | export interface Topic { 12 | created_at: string 13 | deleted_at: null 14 | first_post_id: number 15 | forum_id: number 16 | id: number 17 | is_locked: boolean 18 | last_post_id: number 19 | post_count: number 20 | title: string 21 | type: string 22 | updated_at: null | string 23 | user_id: number 24 | poll: null 25 | } -------------------------------------------------------------------------------- /types/v2/groups_details.ts: -------------------------------------------------------------------------------- 1 | export interface GroupsDetailsResponse { 2 | colour: string 3 | has_listing: boolean 4 | has_playmodes: boolean 5 | id: number 6 | identifier: string 7 | is_probationary: boolean 8 | name: string 9 | short_name: string 10 | description: Description 11 | users: User[] 12 | } 13 | 14 | export interface Description { 15 | html: string 16 | markdown: string 17 | } 18 | 19 | export interface User { 20 | avatar_url: string 21 | country_code: string 22 | default_group: string 23 | id: number 24 | is_active: boolean 25 | is_bot: boolean 26 | is_deleted: boolean 27 | is_online: boolean 28 | is_supporter: boolean 29 | last_visit?: string 30 | pm_friends_only: boolean 31 | profile_colour: string 32 | username: string 33 | country: Country 34 | cover: Cover 35 | groups: Group[] 36 | statistics: Statistics 37 | support_level: number 38 | } 39 | 40 | export interface Country { 41 | code: string 42 | name: string 43 | } 44 | 45 | export interface Cover { 46 | custom_url: string 47 | url: string 48 | id: any 49 | } 50 | 51 | export interface Group { 52 | colour: string 53 | has_listing: boolean 54 | has_playmodes: boolean 55 | id: number 56 | identifier: string 57 | is_probationary: boolean 58 | name: string 59 | short_name: string 60 | playmodes: string[] 61 | } 62 | 63 | export interface Statistics { 64 | count_100: number 65 | count_300: number 66 | count_50: number 67 | count_miss: number 68 | level: Level 69 | global_rank?: number 70 | global_rank_exp: any 71 | pp: number 72 | pp_exp: number 73 | ranked_score: number 74 | hit_accuracy: number 75 | play_count: number 76 | play_time: number 77 | total_score: number 78 | total_hits: number 79 | maximum_combo: number 80 | replays_watched_by_others: number 81 | is_ranked: boolean 82 | grade_counts: GradeCounts 83 | } 84 | 85 | export interface Level { 86 | current: number 87 | progress: number 88 | } 89 | 90 | export interface GradeCounts { 91 | ss: number 92 | ssh: number 93 | s: number 94 | sh: number 95 | a: number 96 | } 97 | -------------------------------------------------------------------------------- /types/v2/groups_history.ts: -------------------------------------------------------------------------------- 1 | export interface GroupsHistoryResponse { 2 | events: Event[] 3 | cursor: Cursor 4 | cursor_string: string 5 | } 6 | 7 | export interface Event { 8 | created_at: string 9 | group_id: number 10 | hidden: boolean 11 | id: number 12 | type: string 13 | user_id: number 14 | user_name: string 15 | group_name: string 16 | playmodes?: string[] 17 | } 18 | 19 | export interface Cursor { 20 | id: number 21 | } 22 | -------------------------------------------------------------------------------- /types/v2/matches_detaIls.ts: -------------------------------------------------------------------------------- 1 | import { Mod } from "../mods" 2 | 3 | export interface MatchesDetailsResponse { 4 | match: Match 5 | events: Event[] 6 | users: User[] 7 | first_event_id: number 8 | latest_event_id: number 9 | current_game_id: any 10 | } 11 | 12 | export interface Match { 13 | id: number 14 | start_time: string 15 | end_time: string 16 | name: string 17 | } 18 | 19 | export interface Event { 20 | id: number 21 | detail: Detail 22 | timestamp: string 23 | user_id?: number 24 | game?: Game 25 | } 26 | 27 | export interface Detail { 28 | type: string 29 | text?: string 30 | } 31 | 32 | export interface Game { 33 | beatmap_id: number 34 | id: number 35 | start_time: string 36 | end_time: string 37 | mode: string 38 | mode_int: number 39 | scoring_type: string 40 | team_type: string 41 | mods: Mod[] 42 | beatmap?: Beatmap 43 | scores: Score[] 44 | } 45 | 46 | export interface Beatmap { 47 | beatmapset_id: number 48 | difficulty_rating: number 49 | id: number 50 | mode: string 51 | status: string 52 | total_length: number 53 | user_id: number 54 | version: string 55 | beatmapset: Beatmapset 56 | } 57 | 58 | export interface Beatmapset { 59 | artist: string 60 | artist_unicode: string 61 | covers: Covers 62 | creator: string 63 | favourite_count: number 64 | hype: any 65 | id: number 66 | nsfw: boolean 67 | offset: number 68 | play_count: number 69 | preview_url: string 70 | source: string 71 | spotlight: boolean 72 | status: string 73 | title: string 74 | title_unicode: string 75 | track_id: any 76 | user_id: number 77 | video: boolean 78 | } 79 | 80 | export interface Covers { 81 | cover: string 82 | "cover@2x": string 83 | card: string 84 | "card@2x": string 85 | list: string 86 | "list@2x": string 87 | slimcover: string 88 | "slimcover@2x": string 89 | } 90 | 91 | export interface Score { 92 | accuracy: number 93 | best_id: any 94 | created_at: string 95 | id: any 96 | max_combo: number 97 | mode: string 98 | mode_int: number 99 | mods: Mod[] 100 | passed: boolean 101 | perfect: number 102 | pp: any 103 | rank: string 104 | replay: boolean 105 | score: number 106 | statistics: Statistics 107 | type: string 108 | user_id: number 109 | current_user_attributes: CurrentUserAttributes 110 | match: Match2 111 | } 112 | 113 | export interface Statistics { 114 | count_100: number 115 | count_300: number 116 | count_50: number 117 | count_geki: number 118 | count_katu: number 119 | count_miss: number 120 | } 121 | 122 | export interface CurrentUserAttributes { 123 | pin: any 124 | } 125 | 126 | export interface Match2 { 127 | slot: number 128 | team: string 129 | pass: boolean 130 | } 131 | 132 | export interface User { 133 | avatar_url: string 134 | country_code: string 135 | default_group: string 136 | id: number 137 | is_active: boolean 138 | is_bot: boolean 139 | is_deleted: boolean 140 | is_online: boolean 141 | is_supporter: boolean 142 | last_visit?: string 143 | pm_friends_only: boolean 144 | profile_colour?: string 145 | username: string 146 | country: Country 147 | } 148 | 149 | export interface Country { 150 | code: string 151 | name: string 152 | } 153 | -------------------------------------------------------------------------------- /types/v2/matches_list.ts: -------------------------------------------------------------------------------- 1 | export interface MatchesListResponse { 2 | matches: Match[] 3 | params: Params 4 | cursor: Cursor 5 | cursor_string: string 6 | } 7 | 8 | export interface Match { 9 | id: number 10 | start_time: string 11 | end_time: string 12 | name: string 13 | } 14 | 15 | export interface Params { 16 | limit: number 17 | sort: string 18 | } 19 | 20 | export interface Cursor { 21 | match_id: number 22 | } 23 | -------------------------------------------------------------------------------- /types/v2/me_download_quota.ts: -------------------------------------------------------------------------------- 1 | export interface MedownloadquotaResponse { 2 | quota_used: number 3 | } 4 | -------------------------------------------------------------------------------- /types/v2/me_friends.ts: -------------------------------------------------------------------------------- 1 | export interface MeFriendsResponse { 2 | avatar_url: string 3 | country_code: string 4 | default_group: string 5 | id: number 6 | is_active: boolean 7 | is_bot: boolean 8 | is_deleted: boolean 9 | is_online: boolean 10 | is_supporter: boolean 11 | last_visit?: string 12 | pm_friends_only: boolean 13 | profile_colour?: string 14 | username: string 15 | country: Country 16 | cover: Cover 17 | groups: Group[] 18 | statistics: Statistics 19 | support_level: number 20 | } 21 | 22 | export interface Country { 23 | code: string 24 | name: string 25 | } 26 | 27 | export interface Cover { 28 | custom_url?: string 29 | url: string 30 | id?: string 31 | } 32 | 33 | export interface Group { 34 | colour?: string 35 | has_listing: boolean 36 | has_playmodes: boolean 37 | id: number 38 | identifier: string 39 | is_probationary: boolean 40 | name: string 41 | short_name: string 42 | playmodes?: string[] 43 | } 44 | 45 | export interface Statistics { 46 | count_100: number 47 | count_300: number 48 | count_50: number 49 | count_geki: number 50 | count_katu: number 51 | count_miss: number 52 | level: Level 53 | global_rank?: number 54 | global_rank_exp: any 55 | pp: number 56 | pp_exp: number 57 | ranked_score: number 58 | hit_accuracy: number 59 | play_count: number 60 | play_time: number 61 | total_score: number 62 | total_hits: number 63 | maximum_combo: number 64 | replays_watched_by_others: number 65 | is_ranked: boolean 66 | grade_counts: GradeCounts 67 | } 68 | 69 | export interface Level { 70 | current: number 71 | progress: number 72 | } 73 | 74 | export interface GradeCounts { 75 | ss: number 76 | ssh: number 77 | s: number 78 | sh: number 79 | a: number 80 | } 81 | -------------------------------------------------------------------------------- /types/v2/news_details.ts: -------------------------------------------------------------------------------- 1 | export interface NewsDetailsResponse { 2 | id: number 3 | author: string 4 | edit_url: string 5 | first_image: string 6 | 'first_image@2x': string 7 | published_at: string 8 | updated_at: string 9 | slug: string 10 | title: string 11 | content: string 12 | navigation: Navigation 13 | } 14 | 15 | export interface Navigation { 16 | newer: Newer 17 | older: Older 18 | } 19 | 20 | export interface Newer { 21 | id: number 22 | author: string 23 | edit_url: string 24 | first_image: string 25 | published_at: string 26 | updated_at: string 27 | slug: string 28 | title: string 29 | } 30 | 31 | export interface Older { 32 | id: number 33 | author: string 34 | edit_url: string 35 | first_image: string 36 | 'first_image@2x': string 37 | published_at: string 38 | updated_at: string 39 | slug: string 40 | title: string 41 | } 42 | -------------------------------------------------------------------------------- /types/v2/news_list.ts: -------------------------------------------------------------------------------- 1 | export interface NewsListResponse { 2 | news_posts: NewsPost[] 3 | news_sidebar: NewsSidebar 4 | search: Search 5 | cursor: Cursor 6 | cursor_string: string 7 | } 8 | 9 | export interface NewsPost { 10 | id: number 11 | author: string 12 | edit_url: string 13 | first_image: string 14 | published_at: string 15 | updated_at: string 16 | slug: string 17 | title: string 18 | preview: string 19 | } 20 | 21 | export interface NewsSidebar { 22 | current_year: number 23 | news_posts: NewsPost2[] 24 | years: number[] 25 | } 26 | 27 | export interface NewsPost2 { 28 | id: number 29 | author: string 30 | edit_url: string 31 | first_image: string 32 | published_at: string 33 | updated_at: string 34 | slug: string 35 | title: string 36 | } 37 | 38 | export interface Search { 39 | limit: number 40 | sort: string 41 | year: any 42 | } 43 | 44 | export interface Cursor { 45 | published_at: string 46 | id: number 47 | } 48 | -------------------------------------------------------------------------------- /types/v2/notifications_list.ts: -------------------------------------------------------------------------------- 1 | export interface NotificationsListResponse { 2 | notifications: Notification[] 3 | stacks: Stack[] 4 | timestamp: string 5 | types: Type[] 6 | notification_endpoint: string 7 | } 8 | 9 | export interface Notification { 10 | id: number 11 | name: string 12 | created_at: string 13 | object_type: string 14 | object_id: number 15 | source_user_id: number 16 | is_read: boolean 17 | details: Details 18 | } 19 | 20 | export interface Details { 21 | title: string 22 | username: string 23 | cover_url: string 24 | beatmapset_id: number 25 | title_unicode: string 26 | } 27 | 28 | export interface Stack { 29 | category: string 30 | cursor?: Cursor 31 | name: string 32 | object_type: string 33 | object_id: number 34 | total: number 35 | } 36 | 37 | export interface Cursor { 38 | id: number 39 | } 40 | 41 | export interface Type { 42 | cursor: Cursor2 43 | name?: string 44 | total: number 45 | } 46 | 47 | export interface Cursor2 { 48 | id: number 49 | type?: string 50 | } 51 | -------------------------------------------------------------------------------- /types/v2/ranking_list_country.ts: -------------------------------------------------------------------------------- 1 | export interface RankingListCountryResponse { 2 | cursor: Cursor 3 | ranking: Ranking[] 4 | total: number 5 | } 6 | 7 | export interface Cursor { 8 | page: number 9 | } 10 | 11 | export interface Ranking { 12 | code: string 13 | active_users: number 14 | play_count: number 15 | ranked_score: number 16 | performance: number 17 | country: Country 18 | } 19 | 20 | export interface Country { 21 | code: string 22 | name: string 23 | } 24 | -------------------------------------------------------------------------------- /types/v2/ranking_list_kudosu.ts: -------------------------------------------------------------------------------- 1 | export interface RankingListKudosuResponse { 2 | avatar_url: string 3 | country_code: string 4 | default_group: string 5 | id: number 6 | is_active: boolean 7 | is_bot: boolean 8 | is_deleted: boolean 9 | is_online: boolean 10 | is_supporter: boolean 11 | last_visit?: string 12 | pm_friends_only: boolean 13 | profile_colour?: string 14 | username: string 15 | kudosu: Kudosu 16 | } 17 | 18 | export interface Kudosu { 19 | available: number 20 | total: number 21 | } 22 | -------------------------------------------------------------------------------- /types/v2/ranking_list_performance.ts: -------------------------------------------------------------------------------- 1 | export interface RankingListPerformanceResponse { 2 | cursor: Cursor 3 | ranking: Ranking[] 4 | total: number 5 | } 6 | 7 | export interface Cursor { 8 | page: number 9 | } 10 | 11 | export interface Ranking { 12 | count_100: number 13 | count_300: number 14 | count_50: number 15 | count_geki: number 16 | count_katu: number 17 | count_miss: number 18 | level: Level 19 | global_rank: number 20 | global_rank_exp: any 21 | pp: number 22 | pp_exp: number 23 | ranked_score: number 24 | hit_accuracy: number 25 | play_count: number 26 | play_time: number 27 | total_score: number 28 | total_hits: number 29 | maximum_combo: number 30 | replays_watched_by_others: number 31 | is_ranked: boolean 32 | grade_counts: GradeCounts 33 | user: User 34 | } 35 | 36 | export interface Level { 37 | current: number 38 | progress: number 39 | } 40 | 41 | export interface GradeCounts { 42 | ss: number 43 | ssh: number 44 | s: number 45 | sh: number 46 | a: number 47 | } 48 | 49 | export interface User { 50 | avatar_url: string 51 | country_code: string 52 | default_group: string 53 | id: number 54 | is_active: boolean 55 | is_bot: boolean 56 | is_deleted: boolean 57 | is_online: boolean 58 | is_supporter: boolean 59 | last_visit?: string 60 | pm_friends_only: boolean 61 | profile_colour: any 62 | username: string 63 | country: Country 64 | cover: Cover 65 | } 66 | 67 | export interface Country { 68 | code: string 69 | name: string 70 | } 71 | 72 | export interface Cover { 73 | custom_url?: string 74 | url: string 75 | id?: string 76 | } 77 | -------------------------------------------------------------------------------- /types/v2/ranking_list_score.ts: -------------------------------------------------------------------------------- 1 | export interface RankingListScoreResponse { 2 | cursor: Cursor 3 | ranking: Ranking[] 4 | total: number 5 | } 6 | 7 | export interface Cursor { 8 | page: number 9 | } 10 | 11 | export interface Ranking { 12 | count_100: number 13 | count_300: number 14 | count_50: number 15 | count_geki: number 16 | count_katu: number 17 | count_miss: number 18 | level: Level 19 | global_rank: number 20 | global_rank_exp: any 21 | pp: number 22 | pp_exp: number 23 | ranked_score: number 24 | hit_accuracy: number 25 | play_count: number 26 | play_time: number 27 | total_score: number 28 | total_hits: number 29 | maximum_combo: number 30 | replays_watched_by_others: number 31 | is_ranked: boolean 32 | grade_counts: GradeCounts 33 | user: User 34 | } 35 | 36 | export interface Level { 37 | current: number 38 | progress: number 39 | } 40 | 41 | export interface GradeCounts { 42 | ss: number 43 | ssh: number 44 | s: number 45 | sh: number 46 | a: number 47 | } 48 | 49 | export interface User { 50 | avatar_url: string 51 | country_code: string 52 | default_group: string 53 | id: number 54 | is_active: boolean 55 | is_bot: boolean 56 | is_deleted: boolean 57 | is_online: boolean 58 | is_supporter: boolean 59 | last_visit?: string 60 | pm_friends_only: boolean 61 | profile_colour?: string 62 | username: string 63 | country: Country 64 | cover: Cover 65 | } 66 | 67 | export interface Country { 68 | code: string 69 | name: string 70 | } 71 | 72 | export interface Cover { 73 | custom_url?: string 74 | url: string 75 | id?: string 76 | } 77 | -------------------------------------------------------------------------------- /types/v2/rooms_details.ts: -------------------------------------------------------------------------------- 1 | import { Mod } from "../mods" 2 | 3 | export interface RoomsDetailsResponse { 4 | id: number 5 | name: string 6 | category: string 7 | type: string 8 | user_id: number 9 | starts_at: string 10 | ends_at: any 11 | max_attempts: any 12 | participant_count: number 13 | channel_id: number 14 | active: boolean 15 | has_password: boolean 16 | queue_mode: string 17 | auto_skip: boolean 18 | current_user_score: CurrentUserScore 19 | host: Host 20 | playlist: Playlist[] 21 | recent_participants: RecentParticipant[] 22 | } 23 | 24 | export interface CurrentUserScore { 25 | accuracy: number 26 | attempts: number 27 | completed: number 28 | pp: number 29 | room_id: number 30 | total_score: number 31 | user_id: number 32 | playlist_item_attempts: any[] 33 | } 34 | 35 | export interface Host { 36 | avatar_url: string 37 | country_code: string 38 | default_group: string 39 | id: number 40 | is_active: boolean 41 | is_bot: boolean 42 | is_deleted: boolean 43 | is_online: boolean 44 | is_supporter: boolean 45 | last_visit: string 46 | pm_friends_only: boolean 47 | profile_colour: any 48 | username: string 49 | country: Country 50 | } 51 | 52 | export interface Country { 53 | code: string 54 | name: string 55 | } 56 | 57 | export interface Playlist { 58 | id: number 59 | room_id: number 60 | beatmap_id: number 61 | ruleset_id: number 62 | allowed_mods: Mod[] 63 | required_mods: Mod[] 64 | expired: boolean 65 | owner_id: number 66 | playlist_order?: number 67 | played_at?: string 68 | beatmap: Beatmap 69 | } 70 | 71 | export interface Settings { } 72 | 73 | export interface Beatmap { 74 | beatmapset_id: number 75 | difficulty_rating: number 76 | id: number 77 | mode: string 78 | status: string 79 | total_length: number 80 | user_id: number 81 | version: string 82 | beatmapset: Beatmapset 83 | checksum: string 84 | max_combo: number 85 | } 86 | 87 | export interface Beatmapset { 88 | artist: string 89 | artist_unicode: string 90 | covers: Covers 91 | creator: string 92 | favourite_count: number 93 | hype: any 94 | id: number 95 | nsfw: boolean 96 | offset: number 97 | play_count: number 98 | preview_url: string 99 | source: string 100 | spotlight: boolean 101 | status: string 102 | title: string 103 | title_unicode: string 104 | track_id?: number 105 | user_id: number 106 | video: boolean 107 | } 108 | 109 | export interface Covers { 110 | cover: string 111 | "cover@2x": string 112 | card: string 113 | "card@2x": string 114 | list: string 115 | "list@2x": string 116 | slimcover: string 117 | "slimcover@2x": string 118 | } 119 | 120 | export interface RecentParticipant { 121 | avatar_url: string 122 | country_code: string 123 | default_group: string 124 | id: number 125 | is_active: boolean 126 | is_bot: boolean 127 | is_deleted: boolean 128 | is_online: boolean 129 | is_supporter: boolean 130 | last_visit: string 131 | pm_friends_only: boolean 132 | profile_colour: any 133 | username: string 134 | } 135 | -------------------------------------------------------------------------------- /types/v2/rooms_leaderboard.ts: -------------------------------------------------------------------------------- 1 | export interface RoomsLeaderboardResponse { 2 | leaderboard: Leaderboard[] 3 | user_score: any 4 | } 5 | 6 | export interface Leaderboard { 7 | accuracy: number 8 | attempts: number 9 | completed: number 10 | pp: number 11 | room_id: number 12 | total_score: number 13 | user_id: number 14 | user: User 15 | } 16 | 17 | export interface User { 18 | avatar_url: string 19 | country_code: string 20 | default_group: string 21 | id: number 22 | is_active: boolean 23 | is_bot: boolean 24 | is_deleted: boolean 25 | is_online: boolean 26 | is_supporter: boolean 27 | last_visit: null | string 28 | pm_friends_only: boolean 29 | profile_colour: any 30 | username: string 31 | country: Country 32 | } 33 | 34 | export interface Country { 35 | code: string 36 | name: string 37 | } -------------------------------------------------------------------------------- /types/v2/rooms_list.ts: -------------------------------------------------------------------------------- 1 | import { Mod } from "../mods" 2 | 3 | export interface RoomsListResponse { 4 | rooms: Room[] 5 | cursor: Cursor 6 | cursor_string: string 7 | } 8 | 9 | export interface Room { 10 | id: number 11 | name: string 12 | category: string 13 | type: string 14 | user_id: number 15 | starts_at: string 16 | ends_at: any 17 | max_attempts: any 18 | participant_count: number 19 | channel_id: number 20 | active: boolean 21 | has_password: boolean 22 | queue_mode: string 23 | auto_skip: boolean 24 | current_playlist_item: CurrentPlaylistItem 25 | difficulty_range: DifficultyRange 26 | host: Host 27 | playlist_item_stats: PlaylistItemStats 28 | recent_participants: RecentParticipant[] 29 | } 30 | 31 | export interface CurrentPlaylistItem { 32 | id: number 33 | room_id: number 34 | beatmap_id: number 35 | ruleset_id: number 36 | allowed_mods: Mod[] 37 | required_mods: Mod[] 38 | expired: boolean 39 | owner_id: number 40 | playlist_order: number 41 | played_at: any 42 | beatmap: Beatmap 43 | } 44 | 45 | export interface Beatmap { 46 | beatmapset_id: number 47 | difficulty_rating: number 48 | id: number 49 | mode: string 50 | status: string 51 | total_length: number 52 | user_id: number 53 | version: string 54 | beatmapset: Beatmapset 55 | } 56 | 57 | export interface Beatmapset { 58 | artist: string 59 | artist_unicode: string 60 | covers: Covers 61 | creator: string 62 | favourite_count: number 63 | hype: any 64 | id: number 65 | nsfw: boolean 66 | offset: number 67 | play_count: number 68 | preview_url: string 69 | source: string 70 | spotlight: boolean 71 | status: string 72 | title: string 73 | title_unicode: string 74 | track_id: any 75 | user_id: number 76 | video: boolean 77 | } 78 | 79 | export interface Covers { 80 | cover: string 81 | "cover@2x": string 82 | card: string 83 | "card@2x": string 84 | list: string 85 | "list@2x": string 86 | slimcover: string 87 | "slimcover@2x": string 88 | } 89 | 90 | export interface DifficultyRange { 91 | max: number 92 | min: number 93 | } 94 | 95 | export interface Host { 96 | avatar_url: string 97 | country_code: string 98 | default_group: string 99 | id: number 100 | is_active: boolean 101 | is_bot: boolean 102 | is_deleted: boolean 103 | is_online: boolean 104 | is_supporter: boolean 105 | last_visit: string 106 | pm_friends_only: boolean 107 | profile_colour: any 108 | username: string 109 | country: Country 110 | } 111 | 112 | export interface Country { 113 | code: string 114 | name: string 115 | } 116 | 117 | export interface PlaylistItemStats { 118 | count_active: number 119 | count_total: number 120 | ruleset_ids: number[] 121 | } 122 | 123 | export interface RecentParticipant { 124 | avatar_url: string 125 | country_code: string 126 | default_group: string 127 | id: number 128 | is_active: boolean 129 | is_bot: boolean 130 | is_deleted: boolean 131 | is_online: boolean 132 | is_supporter: boolean 133 | last_visit: string 134 | pm_friends_only: boolean 135 | profile_colour: any 136 | username: string 137 | } 138 | 139 | export interface Cursor { 140 | id: number 141 | } 142 | -------------------------------------------------------------------------------- /types/v2/rooms_scores_all.ts: -------------------------------------------------------------------------------- 1 | import { Mod } from "../mods" 2 | 3 | export interface RoomsScoresAllResponse { 4 | params: Params 5 | scores: Score[] 6 | total: number 7 | user_score: any 8 | cursor: any 9 | cursor_string: any 10 | } 11 | 12 | export interface Params { 13 | limit: number 14 | sort: string 15 | } 16 | 17 | export interface Score { 18 | playlist_item_id: number 19 | room_id: number 20 | solo_score_id: number 21 | ranked: boolean 22 | preserve: boolean 23 | processed: boolean 24 | maximum_statistics: MaximumStatistics 25 | mods: Mod[] 26 | statistics: Statistics 27 | beatmap_id: number 28 | best_id: any 29 | id: number 30 | rank: string 31 | type: string 32 | user_id: number 33 | accuracy: number 34 | build_id: number 35 | ended_at: string 36 | has_replay: boolean 37 | is_perfect_combo: boolean 38 | legacy_perfect: boolean 39 | legacy_score_id: any 40 | legacy_total_score: number 41 | max_combo: number 42 | passed: boolean 43 | pp: number 44 | ruleset_id: number 45 | started_at: string 46 | total_score: number 47 | replay: boolean 48 | current_user_attributes: CurrentUserAttributes 49 | user: User 50 | } 51 | 52 | export interface MaximumStatistics { 53 | great: number 54 | ignore_hit: number 55 | large_bonus: number 56 | small_bonus: number 57 | large_tick_hit: number 58 | slider_tail_hit: number 59 | } 60 | 61 | export interface Statistics { 62 | perfect?: number 63 | good?: number 64 | ok?: number 65 | great?: number 66 | meh?: number 67 | miss?: number 68 | ignore_hit: number 69 | ignore_miss: number 70 | large_bonus: number 71 | small_bonus: number 72 | large_tick_hit: number 73 | slider_tail_hit: number 74 | large_tick_miss?: number 75 | } 76 | 77 | export interface CurrentUserAttributes { 78 | pin: any 79 | } 80 | 81 | export interface User { 82 | avatar_url: string 83 | country_code: string 84 | default_group: string 85 | id: number 86 | is_active: boolean 87 | is_bot: boolean 88 | is_deleted: boolean 89 | is_online: boolean 90 | is_supporter: boolean 91 | last_visit: string 92 | pm_friends_only: boolean 93 | profile_colour: any 94 | username: string 95 | country: Country 96 | cover: Cover 97 | } 98 | 99 | export interface Country { 100 | code: string 101 | name: string 102 | } 103 | 104 | export interface Cover { 105 | custom_url: any 106 | url: string 107 | id: string 108 | } 109 | -------------------------------------------------------------------------------- /types/v2/scores_download.ts: -------------------------------------------------------------------------------- 1 | export interface ScoresDownloadResponse { 2 | status: string 3 | destination: string 4 | elapsed_time: number 5 | } 6 | -------------------------------------------------------------------------------- /types/v2/scores_list_latest_ranked.ts: -------------------------------------------------------------------------------- 1 | import { Mod } from "../mods" 2 | 3 | export interface scores_list_latest_ranked_response { 4 | scores: Score[] 5 | cursor: Cursor 6 | cursor_string: string 7 | } 8 | 9 | export interface Cursor { 10 | id: number 11 | } 12 | 13 | export interface Score { 14 | classic_total_score: number 15 | preserve: boolean 16 | processed: boolean 17 | ranked: boolean 18 | maximum_statistics: Statistics 19 | mods: Mod[] 20 | statistics: Statistics 21 | total_score_without_mods: number 22 | beatmap_id: number 23 | best_id: null 24 | id: number 25 | rank: string 26 | type: string 27 | user_id: number 28 | accuracy: number 29 | build_id: null | number 30 | ended_at: string 31 | has_replay: boolean 32 | is_perfect_combo: boolean 33 | legacy_perfect: boolean 34 | legacy_score_id: null | number 35 | legacy_total_score: number 36 | max_combo: number 37 | passed: boolean 38 | pp: null | number 39 | ruleset_id: number 40 | started_at: null | string 41 | total_score: number 42 | replay: boolean 43 | current_user_attributes: Currentuserattributes 44 | index: number 45 | } 46 | 47 | export interface Currentuserattributes { 48 | pin: null 49 | } 50 | 51 | export interface Statistics { 52 | perfect?: number 53 | good?: number 54 | ok?: number 55 | great?: number 56 | meh?: number 57 | miss?: number 58 | 59 | ignore_hit?: number 60 | ignore_miss?: number 61 | large_bonus?: number 62 | large_tick_hit?: number 63 | large_tick_miss?: number 64 | legacy_combo_increase?: number 65 | small_bonus?: number 66 | small_tick_hit?: number 67 | small_tick_miss?: number 68 | } -------------------------------------------------------------------------------- /types/v2/scores_list_leaderboard.ts: -------------------------------------------------------------------------------- 1 | import { Mod } from "../mods" 2 | 3 | export interface scores_list_leaderboard_response { 4 | classic_total_score: number 5 | preserve: boolean 6 | processed: boolean 7 | ranked: boolean 8 | maximum_statistics: Statistics 9 | mods: Mod[] 10 | statistics: Statistics 11 | beatmap_id: number 12 | best_id: null 13 | id: number 14 | rank: string 15 | type: string 16 | user_id: number 17 | accuracy: number 18 | build_id: null 19 | ended_at: string 20 | has_replay: boolean 21 | is_perfect_combo: boolean 22 | legacy_perfect: boolean 23 | legacy_score_id: number 24 | legacy_total_score: number 25 | max_combo: number 26 | passed: boolean 27 | pp: null 28 | ruleset_id: number 29 | started_at: null 30 | total_score: number 31 | replay: boolean 32 | current_user_attributes: Currentuserattributes 33 | user: User 34 | index: number 35 | total_score_without_mods?: number 36 | } 37 | 38 | export interface User { 39 | avatar_url: string 40 | country_code: string 41 | default_group: string 42 | id: number 43 | is_active: boolean 44 | is_bot: boolean 45 | is_deleted: boolean 46 | is_online: boolean 47 | is_supporter: boolean 48 | last_visit: null | string 49 | pm_friends_only: boolean 50 | profile_colour: null 51 | username: string 52 | country: Country 53 | cover: Cover 54 | team: null 55 | } 56 | 57 | export interface Cover { 58 | custom_url: null | string 59 | url: string 60 | id: null | string 61 | } 62 | 63 | export interface Country { 64 | code: string 65 | name: string 66 | } 67 | 68 | export interface Currentuserattributes { 69 | pin: null 70 | } 71 | 72 | export interface Statistics { 73 | perfect?: number 74 | good?: number 75 | ok?: number 76 | great?: number 77 | meh?: number 78 | miss?: number 79 | 80 | ignore_hit?: number 81 | ignore_miss?: number 82 | large_bonus?: number 83 | large_tick_hit?: number 84 | large_tick_miss?: number 85 | legacy_combo_increase?: number 86 | small_bonus?: number 87 | small_tick_hit?: number 88 | small_tick_miss?: number 89 | } -------------------------------------------------------------------------------- /types/v2/scores_list_user_beatmap_all.ts: -------------------------------------------------------------------------------- 1 | import { Mod } from "../mods" 2 | 3 | export interface scores_list_user_beatmap_all_response { 4 | classic_total_score: number 5 | preserve: boolean 6 | processed: boolean 7 | ranked: boolean 8 | maximum_statistics: Statistics 9 | mods: Mod[] 10 | statistics: Statistics 11 | beatmap_id: number 12 | best_id: null 13 | id: number 14 | rank: string 15 | type: string 16 | user_id: number 17 | accuracy: number 18 | build_id: null 19 | ended_at: string 20 | has_replay: boolean 21 | is_perfect_combo: boolean 22 | legacy_perfect: boolean 23 | legacy_score_id: number 24 | legacy_total_score: number 25 | max_combo: number 26 | passed: boolean 27 | pp: null 28 | ruleset_id: number 29 | started_at: null 30 | total_score: number 31 | replay: boolean 32 | current_user_attributes: Currentuserattributes 33 | index: number 34 | } 35 | 36 | export interface Currentuserattributes { 37 | pin: null 38 | } 39 | 40 | export interface Statistics { 41 | perfect?: number 42 | good?: number 43 | ok?: number 44 | great?: number 45 | meh?: number 46 | miss?: number 47 | 48 | ignore_hit?: number 49 | ignore_miss?: number 50 | large_bonus?: number 51 | large_tick_hit?: number 52 | large_tick_miss?: number 53 | legacy_combo_increase?: number 54 | small_bonus?: number 55 | small_tick_hit?: number 56 | small_tick_miss?: number 57 | } -------------------------------------------------------------------------------- /types/v2/scores_list_user_beatmap_best.ts: -------------------------------------------------------------------------------- 1 | import { Mod } from "../mods" 2 | 3 | export interface scores_list_user_beatmap_best_response { 4 | position: number 5 | score: Score 6 | } 7 | 8 | export interface Score { 9 | classic_total_score: number 10 | preserve: boolean 11 | processed: boolean 12 | ranked: boolean 13 | maximum_statistics: Statistics 14 | mods: Mod[] 15 | statistics: Statistics 16 | beatmap_id: number 17 | best_id: null 18 | id: number 19 | rank: string 20 | type: string 21 | user_id: number 22 | accuracy: number 23 | build_id: null 24 | ended_at: string 25 | has_replay: boolean 26 | is_perfect_combo: boolean 27 | legacy_perfect: boolean 28 | legacy_score_id: number 29 | legacy_total_score: number 30 | max_combo: number 31 | passed: boolean 32 | pp: null 33 | ruleset_id: number 34 | started_at: null 35 | total_score: number 36 | replay: boolean 37 | current_user_attributes: Currentuserattributes 38 | beatmap: Beatmap 39 | user: User 40 | } 41 | 42 | export interface User { 43 | avatar_url: string 44 | country_code: string 45 | default_group: string 46 | id: number 47 | is_active: boolean 48 | is_bot: boolean 49 | is_deleted: boolean 50 | is_online: boolean 51 | is_supporter: boolean 52 | last_visit: string 53 | pm_friends_only: boolean 54 | profile_colour: null 55 | username: string 56 | country: Country 57 | cover: Cover 58 | team: null 59 | } 60 | 61 | export interface Cover { 62 | custom_url: string 63 | url: string 64 | id: string 65 | } 66 | 67 | export interface Country { 68 | code: string 69 | name: string 70 | } 71 | 72 | export interface Beatmap { 73 | beatmapset_id: number 74 | difficulty_rating: number 75 | id: number 76 | mode: string 77 | status: string 78 | total_length: number 79 | user_id: number 80 | version: string 81 | accuracy: number 82 | ar: number 83 | bpm: number 84 | convert: boolean 85 | count_circles: number 86 | count_sliders: number 87 | count_spinners: number 88 | cs: number 89 | deleted_at: null 90 | drain: number 91 | hit_length: number 92 | is_scoreable: boolean 93 | last_updated: string 94 | mode_int: number 95 | passcount: number 96 | playcount: number 97 | ranked: number 98 | url: string 99 | checksum: string 100 | owners: Owner[] 101 | } 102 | 103 | export interface Owner { 104 | id: number 105 | username: string 106 | } 107 | 108 | export interface Currentuserattributes { 109 | pin: null 110 | } 111 | 112 | export interface Statistics { 113 | perfect?: number 114 | good?: number 115 | ok?: number 116 | great?: number 117 | meh?: number 118 | miss?: number 119 | 120 | ignore_hit?: number 121 | ignore_miss?: number 122 | large_bonus?: number 123 | large_tick_hit?: number 124 | large_tick_miss?: number 125 | legacy_combo_increase?: number 126 | small_bonus?: number 127 | small_tick_hit?: number 128 | small_tick_miss?: number 129 | } -------------------------------------------------------------------------------- /types/v2/scores_list_user_best.ts: -------------------------------------------------------------------------------- 1 | import { Mod } from "../mods" 2 | 3 | export interface scores_list_user_user_best_response { 4 | classic_total_score: number 5 | preserve: boolean 6 | processed: boolean 7 | ranked: boolean 8 | maximum_statistics: Statistics 9 | mods: Mod[] 10 | statistics: Statistics 11 | beatmap_id: number 12 | best_id: null 13 | id: number 14 | rank: string 15 | type: string 16 | user_id: number 17 | accuracy: number 18 | build_id: null | number 19 | ended_at: string 20 | has_replay: boolean 21 | is_perfect_combo: boolean 22 | legacy_perfect: boolean 23 | legacy_score_id: null | number 24 | legacy_total_score: number 25 | max_combo: number 26 | passed: boolean 27 | pp: number 28 | ruleset_id: number 29 | started_at: null | string 30 | total_score: number 31 | replay: boolean 32 | current_user_attributes: Currentuserattributes 33 | beatmap: Beatmap 34 | beatmapset: Beatmapset 35 | user: User 36 | weight: Weight 37 | index: number 38 | total_score_without_mods?: number 39 | } 40 | 41 | export interface Weight { 42 | percentage: number 43 | pp: number 44 | } 45 | 46 | export interface User { 47 | avatar_url: string 48 | country_code: string 49 | default_group: string 50 | id: number 51 | is_active: boolean 52 | is_bot: boolean 53 | is_deleted: boolean 54 | is_online: boolean 55 | is_supporter: boolean 56 | last_visit: string 57 | pm_friends_only: boolean 58 | profile_colour: null 59 | username: string 60 | } 61 | 62 | export interface Beatmapset { 63 | artist: string 64 | artist_unicode: string 65 | covers: Covers 66 | creator: string 67 | favourite_count: number 68 | hype: null 69 | id: number 70 | nsfw: boolean 71 | offset: number 72 | play_count: number 73 | preview_url: string 74 | source: string 75 | spotlight: boolean 76 | status: string 77 | title: string 78 | title_unicode: string 79 | track_id: null | number 80 | user_id: number 81 | video: boolean 82 | } 83 | 84 | export interface Covers { 85 | cover: string 86 | 'cover@2x': string 87 | card: string 88 | 'card@2x': string 89 | list: string 90 | 'list@2x': string 91 | slimcover: string 92 | 'slimcover@2x': string 93 | } 94 | 95 | export interface Beatmap { 96 | beatmapset_id: number 97 | difficulty_rating: number 98 | id: number 99 | mode: string 100 | status: string 101 | total_length: number 102 | user_id: number 103 | version: string 104 | accuracy: number 105 | ar: number 106 | bpm: number 107 | convert: boolean 108 | count_circles: number 109 | count_sliders: number 110 | count_spinners: number 111 | cs: number 112 | deleted_at: null 113 | drain: number 114 | hit_length: number 115 | is_scoreable: boolean 116 | last_updated: string 117 | mode_int: number 118 | passcount: number 119 | playcount: number 120 | ranked: number 121 | url: string 122 | checksum: string 123 | } 124 | 125 | export interface Currentuserattributes { 126 | pin: null 127 | } 128 | 129 | export interface Statistics { 130 | perfect?: number 131 | good?: number 132 | ok?: number 133 | great?: number 134 | meh?: number 135 | miss?: number 136 | 137 | ignore_hit?: number 138 | ignore_miss?: number 139 | large_bonus?: number 140 | large_tick_hit?: number 141 | large_tick_miss?: number 142 | legacy_combo_increase?: number 143 | small_bonus?: number 144 | small_tick_hit?: number 145 | small_tick_miss?: number 146 | } -------------------------------------------------------------------------------- /types/v2/scores_list_user_firsts.ts: -------------------------------------------------------------------------------- 1 | import { Mod } from "../mods" 2 | 3 | export interface scores_list_user_user_firsts_response { 4 | classic_total_score: number 5 | preserve: boolean 6 | processed: boolean 7 | ranked: boolean 8 | maximum_statistics: Statistics 9 | mods: Mod[] 10 | statistics: Statistics 11 | total_score_without_mods: number 12 | beatmap_id: number 13 | best_id: null 14 | id: number 15 | rank: string 16 | type: string 17 | user_id: number 18 | accuracy: number 19 | build_id: null 20 | ended_at: string 21 | has_replay: boolean 22 | is_perfect_combo: boolean 23 | legacy_perfect: boolean 24 | legacy_score_id: number 25 | legacy_total_score: number 26 | max_combo: number 27 | passed: boolean 28 | pp: number 29 | ruleset_id: number 30 | started_at: null 31 | total_score: number 32 | replay: boolean 33 | current_user_attributes: Currentuserattributes 34 | beatmap: Beatmap 35 | beatmapset: Beatmapset 36 | user: User 37 | index: number 38 | } 39 | 40 | export interface User { 41 | avatar_url: string 42 | country_code: string 43 | default_group: string 44 | id: number 45 | is_active: boolean 46 | is_bot: boolean 47 | is_deleted: boolean 48 | is_online: boolean 49 | is_supporter: boolean 50 | last_visit: string 51 | pm_friends_only: boolean 52 | profile_colour: null 53 | username: string 54 | } 55 | 56 | export interface Beatmapset { 57 | artist: string 58 | artist_unicode: string 59 | covers: Covers 60 | creator: string 61 | favourite_count: number 62 | hype: null 63 | id: number 64 | nsfw: boolean 65 | offset: number 66 | play_count: number 67 | preview_url: string 68 | source: string 69 | spotlight: boolean 70 | status: string 71 | title: string 72 | title_unicode: string 73 | track_id: null 74 | user_id: number 75 | video: boolean 76 | } 77 | 78 | export interface Covers { 79 | cover: string 80 | 'cover@2x': string 81 | card: string 82 | 'card@2x': string 83 | list: string 84 | 'list@2x': string 85 | slimcover: string 86 | 'slimcover@2x': string 87 | } 88 | 89 | export interface Beatmap { 90 | beatmapset_id: number 91 | difficulty_rating: number 92 | id: number 93 | mode: string 94 | status: string 95 | total_length: number 96 | user_id: number 97 | version: string 98 | accuracy: number 99 | ar: number 100 | bpm: number 101 | convert: boolean 102 | count_circles: number 103 | count_sliders: number 104 | count_spinners: number 105 | cs: number 106 | deleted_at: null 107 | drain: number 108 | hit_length: number 109 | is_scoreable: boolean 110 | last_updated: string 111 | mode_int: number 112 | passcount: number 113 | playcount: number 114 | ranked: number 115 | url: string 116 | checksum: string 117 | } 118 | 119 | export interface Currentuserattributes { 120 | pin: null 121 | } 122 | 123 | export interface Statistics { 124 | perfect?: number 125 | good?: number 126 | ok?: number 127 | great?: number 128 | meh?: number 129 | miss?: number 130 | 131 | ignore_hit?: number 132 | ignore_miss?: number 133 | large_bonus?: number 134 | large_tick_hit?: number 135 | large_tick_miss?: number 136 | legacy_combo_increase?: number 137 | small_bonus?: number 138 | small_tick_hit?: number 139 | small_tick_miss?: number 140 | } -------------------------------------------------------------------------------- /types/v2/scores_list_user_pinned.ts: -------------------------------------------------------------------------------- 1 | import { Mod } from "../mods" 2 | 3 | export interface scores_list_user_user_pinned_response { 4 | classic_total_score: number 5 | preserve: boolean 6 | processed: boolean 7 | ranked: boolean 8 | maximum_statistics: Statistics 9 | mods: Mod[] 10 | statistics: Statistics 11 | total_score_without_mods?: number 12 | beatmap_id: number 13 | best_id: null 14 | id: number 15 | rank: string 16 | type: string 17 | user_id: number 18 | accuracy: number 19 | build_id: null 20 | ended_at: string 21 | has_replay: boolean 22 | is_perfect_combo: boolean 23 | legacy_perfect: boolean 24 | legacy_score_id: number 25 | legacy_total_score: number 26 | max_combo: number 27 | passed: boolean 28 | pp: null | number 29 | ruleset_id: number 30 | started_at: null 31 | total_score: number 32 | replay: boolean 33 | current_user_attributes: Currentuserattributes 34 | beatmap: Beatmap 35 | beatmapset: Beatmapset 36 | user: User 37 | index: number 38 | } 39 | 40 | export interface User { 41 | avatar_url: string 42 | country_code: string 43 | default_group: string 44 | id: number 45 | is_active: boolean 46 | is_bot: boolean 47 | is_deleted: boolean 48 | is_online: boolean 49 | is_supporter: boolean 50 | last_visit: string 51 | pm_friends_only: boolean 52 | profile_colour: null 53 | username: string 54 | } 55 | 56 | export interface Beatmapset { 57 | artist: string 58 | artist_unicode: string 59 | covers: Covers 60 | creator: string 61 | favourite_count: number 62 | hype: null 63 | id: number 64 | nsfw: boolean 65 | offset: number 66 | play_count: number 67 | preview_url: string 68 | source: string 69 | spotlight: boolean 70 | status: string 71 | title: string 72 | title_unicode: string 73 | track_id: null 74 | user_id: number 75 | video: boolean 76 | } 77 | 78 | export interface Covers { 79 | cover: string 80 | 'cover@2x': string 81 | card: string 82 | 'card@2x': string 83 | list: string 84 | 'list@2x': string 85 | slimcover: string 86 | 'slimcover@2x': string 87 | } 88 | 89 | export interface Beatmap { 90 | beatmapset_id: number 91 | difficulty_rating: number 92 | id: number 93 | mode: string 94 | status: string 95 | total_length: number 96 | user_id: number 97 | version: string 98 | accuracy: number 99 | ar: number 100 | bpm: number 101 | convert: boolean 102 | count_circles: number 103 | count_sliders: number 104 | count_spinners: number 105 | cs: number 106 | deleted_at: null 107 | drain: number 108 | hit_length: number 109 | is_scoreable: boolean 110 | last_updated: string 111 | mode_int: number 112 | passcount: number 113 | playcount: number 114 | ranked: number 115 | url: string 116 | checksum: string 117 | } 118 | 119 | export interface Currentuserattributes { 120 | pin: null 121 | } 122 | 123 | export interface Statistics { 124 | perfect?: number 125 | good?: number 126 | ok?: number 127 | great?: number 128 | meh?: number 129 | miss?: number 130 | 131 | ignore_hit?: number 132 | ignore_miss?: number 133 | large_bonus?: number 134 | large_tick_hit?: number 135 | large_tick_miss?: number 136 | legacy_combo_increase?: number 137 | small_bonus?: number 138 | small_tick_hit?: number 139 | small_tick_miss?: number 140 | } -------------------------------------------------------------------------------- /types/v2/scores_list_user_recent.ts: -------------------------------------------------------------------------------- 1 | import { Mod } from "../mods" 2 | 3 | export interface scores_list_user_recent_response { 4 | classic_total_score: number 5 | preserve: boolean 6 | processed: boolean 7 | ranked: boolean 8 | maximum_statistics: Statistics 9 | mods: Mod[] 10 | statistics: Statistics 11 | total_score_without_mods: number 12 | beatmap_id: number 13 | best_id: null 14 | id: number 15 | rank: string 16 | type: string 17 | user_id: number 18 | accuracy: number 19 | build_id: number 20 | ended_at: string 21 | has_replay: boolean 22 | is_perfect_combo: boolean 23 | legacy_perfect: boolean 24 | legacy_score_id: null 25 | legacy_total_score: number 26 | max_combo: number 27 | passed: boolean 28 | pp: null 29 | ruleset_id: number 30 | started_at: string 31 | total_score: number 32 | replay: boolean 33 | current_user_attributes: Currentuserattributes 34 | beatmap: Beatmap 35 | beatmapset: Beatmapset 36 | user: User 37 | index: number 38 | } 39 | 40 | export interface User { 41 | avatar_url: string 42 | country_code: string 43 | default_group: string 44 | id: number 45 | is_active: boolean 46 | is_bot: boolean 47 | is_deleted: boolean 48 | is_online: boolean 49 | is_supporter: boolean 50 | last_visit: string 51 | pm_friends_only: boolean 52 | profile_colour: null 53 | username: string 54 | } 55 | 56 | export interface Beatmapset { 57 | artist: string 58 | artist_unicode: string 59 | covers: Covers 60 | creator: string 61 | favourite_count: number 62 | hype: null 63 | id: number 64 | nsfw: boolean 65 | offset: number 66 | play_count: number 67 | preview_url: string 68 | source: string 69 | spotlight: boolean 70 | status: string 71 | title: string 72 | title_unicode: string 73 | track_id: null 74 | user_id: number 75 | video: boolean 76 | } 77 | 78 | export interface Covers { 79 | cover: string 80 | 'cover@2x': string 81 | card: string 82 | 'card@2x': string 83 | list: string 84 | 'list@2x': string 85 | slimcover: string 86 | 'slimcover@2x': string 87 | } 88 | 89 | export interface Beatmap { 90 | beatmapset_id: number 91 | difficulty_rating: number 92 | id: number 93 | mode: string 94 | status: string 95 | total_length: number 96 | user_id: number 97 | version: string 98 | accuracy: number 99 | ar: number 100 | bpm: number 101 | convert: boolean 102 | count_circles: number 103 | count_sliders: number 104 | count_spinners: number 105 | cs: number 106 | deleted_at: null 107 | drain: number 108 | hit_length: number 109 | is_scoreable: boolean 110 | last_updated: string 111 | mode_int: number 112 | passcount: number 113 | playcount: number 114 | ranked: number 115 | url: string 116 | checksum: string 117 | } 118 | 119 | export interface Currentuserattributes { 120 | pin: null 121 | } 122 | 123 | export interface Statistics { 124 | perfect?: number 125 | good?: number 126 | ok?: number 127 | great?: number 128 | meh?: number 129 | miss?: number 130 | 131 | ignore_hit?: number 132 | ignore_miss?: number 133 | large_bonus?: number 134 | large_tick_hit?: number 135 | large_tick_miss?: number 136 | legacy_combo_increase?: number 137 | small_bonus?: number 138 | small_tick_hit?: number 139 | small_tick_miss?: number 140 | } -------------------------------------------------------------------------------- /types/v2/scores_user_beamap.ts: -------------------------------------------------------------------------------- 1 | import { Mod } from "../mods"; 2 | 3 | export interface ScoresUserBeatmap { 4 | ranked: boolean; 5 | maximum_statistics: MaximumStatistics; 6 | mods: Mod[]; 7 | statistics: Statistics; 8 | beatmap_id: number; 9 | best_id: any; 10 | id: number; 11 | rank: string; 12 | type: string; 13 | user_id: number; 14 | accuracy: number; 15 | build_id?: number; 16 | ended_at: string; 17 | has_replay: boolean; 18 | legacy_perfect: any; 19 | legacy_score_id?: number; 20 | legacy_total_score: number; 21 | max_combo: number; 22 | passed: boolean; 23 | pp?: number; 24 | ruleset_id: number; 25 | started_at?: string; 26 | total_score: number; 27 | replay: boolean; 28 | current_user_attributes: CurrentUserAttributes; 29 | } 30 | 31 | export interface MaximumStatistics { 32 | great: number; 33 | legacy_combo_increase?: number; 34 | ignore_hit?: number; 35 | large_bonus?: number; 36 | small_bonus?: number; 37 | large_tick_hit?: number; 38 | } 39 | 40 | export interface Statistics { 41 | perfect?: number 42 | good?: number 43 | ok?: number 44 | great?: number 45 | meh?: number 46 | miss?: number 47 | ignore_hit?: number; 48 | ignore_miss?: number; 49 | small_bonus?: number; 50 | large_tick_miss?: number; 51 | } 52 | 53 | export interface CurrentUserAttributes { 54 | pin: any; 55 | } 56 | -------------------------------------------------------------------------------- /types/v2/search_all.ts: -------------------------------------------------------------------------------- 1 | export interface SearchWiki { 2 | user: User 3 | wiki_page: WikiPage 4 | } 5 | 6 | export interface User { 7 | data: UserData[] 8 | total: number 9 | } 10 | 11 | export interface UserData { 12 | avatar_url: string 13 | country_code: string 14 | default_group: string 15 | id: number 16 | is_active: boolean 17 | is_bot: boolean 18 | is_deleted: boolean 19 | is_online: boolean 20 | is_supporter: boolean 21 | last_visit?: string 22 | pm_friends_only: boolean 23 | profile_colour: any 24 | username: string 25 | } 26 | 27 | export interface WikiPage { 28 | data: WikiData[] 29 | total: number 30 | } 31 | 32 | export interface WikiData { 33 | available_locales: string[] 34 | layout: string 35 | locale: string 36 | markdown: string 37 | path: string 38 | subtitle?: string 39 | tags: string[] 40 | title: string 41 | } 42 | 43 | 44 | export interface SearchBeatmaps { 45 | beatmapsets: Beatmapset[] 46 | search: Search 47 | recommended_difficulty: any 48 | error: any 49 | total: number 50 | cursor: Cursor 51 | cursor_string: string 52 | } 53 | 54 | export interface Beatmapset { 55 | artist: string 56 | artist_unicode: string 57 | covers: Covers 58 | creator: string 59 | favourite_count: number 60 | hype: any 61 | id: number 62 | nsfw: boolean 63 | offset: number 64 | play_count: number 65 | preview_url: string 66 | source: string 67 | spotlight: boolean 68 | status: string 69 | title: string 70 | title_unicode: string 71 | track_id?: number 72 | user_id: number 73 | video: boolean 74 | bpm: number 75 | can_be_hyped: boolean 76 | deleted_at: any 77 | discussion_enabled: boolean 78 | discussion_locked: boolean 79 | is_scoreable: boolean 80 | last_updated: string 81 | legacy_thread_url: string 82 | nominations_summary: NominationsSummary 83 | ranked: number 84 | ranked_date: string 85 | storyboard: boolean 86 | submitted_date: string 87 | tags: string 88 | availability: Availability 89 | beatmaps: Beatmap[] 90 | pack_tags: string[] 91 | } 92 | 93 | export interface Covers { 94 | cover: string 95 | "cover@2x": string 96 | card: string 97 | "card@2x": string 98 | list: string 99 | "list@2x": string 100 | slimcover: string 101 | "slimcover@2x": string 102 | } 103 | 104 | export interface NominationsSummary { 105 | current: number 106 | required: number 107 | } 108 | 109 | export interface Availability { 110 | download_disabled: boolean 111 | more_information: any 112 | } 113 | 114 | export interface Beatmap { 115 | beatmapset_id: number 116 | difficulty_rating: number 117 | id: number 118 | mode: string 119 | status: string 120 | total_length: number 121 | user_id: number 122 | version: string 123 | accuracy: number 124 | ar: number 125 | bpm: number 126 | convert: boolean 127 | count_circles: number 128 | count_sliders: number 129 | count_spinners: number 130 | cs: number 131 | deleted_at: any 132 | drain: number 133 | hit_length: number 134 | is_scoreable: boolean 135 | last_updated: string 136 | mode_int: number 137 | passcount: number 138 | playcount: number 139 | ranked: number 140 | url: string 141 | checksum: string 142 | max_combo: number 143 | } 144 | 145 | export interface Search { 146 | sort: string 147 | } 148 | 149 | export interface Cursor { 150 | approved_date: number 151 | id: number 152 | } 153 | -------------------------------------------------------------------------------- /types/v2/spotlights_list.ts: -------------------------------------------------------------------------------- 1 | export interface SpotlightsListResponse { 2 | end_date: string 3 | id: number 4 | mode_specific: boolean 5 | name: string 6 | start_date: string 7 | type: string 8 | } 9 | -------------------------------------------------------------------------------- /types/v2/users_activity.ts: -------------------------------------------------------------------------------- 1 | export interface UsersActivityResponse { 2 | created_at: string 3 | createdAt: string 4 | id: number 5 | type: string 6 | mode: string 7 | beatmap: Beatmap 8 | user: User 9 | scoreRank?: string 10 | rank?: number 11 | } 12 | 13 | export interface Beatmap { 14 | title: string 15 | url: string 16 | } 17 | 18 | export interface User { 19 | username: string 20 | url: string 21 | } 22 | -------------------------------------------------------------------------------- /types/v2/users_beatmaps.ts: -------------------------------------------------------------------------------- 1 | export interface UsersBeatmapsResponse { 2 | artist?: string 3 | artist_unicode?: string 4 | covers?: Covers 5 | creator?: string 6 | favourite_count?: number 7 | hype?: Hype 8 | id?: number 9 | nsfw?: boolean 10 | offset?: number 11 | play_count?: number 12 | preview_url?: string 13 | source?: string 14 | spotlight?: boolean 15 | status?: string 16 | title?: string 17 | title_unicode?: string 18 | track_id?: number 19 | user_id?: number 20 | video?: boolean 21 | bpm?: number 22 | can_be_hyped?: boolean 23 | deleted_at: any 24 | discussion_enabled?: boolean 25 | discussion_locked?: boolean 26 | is_scoreable?: boolean 27 | last_updated?: string 28 | legacy_thread_url?: string 29 | nominations_summary?: NominationsSummary 30 | ranked?: number 31 | ranked_date?: string 32 | storyboard?: boolean 33 | submitted_date?: string 34 | tags?: string 35 | availability?: Availability 36 | beatmaps?: Beatmap[] 37 | beatmap_id?: number 38 | count?: number 39 | beatmap?: Beatmap2 40 | beatmapset?: Beatmapset 41 | } 42 | 43 | export interface Covers { 44 | cover: string 45 | "cover@2x": string 46 | card: string 47 | "card@2x": string 48 | list: string 49 | "list@2x": string 50 | slimcover: string 51 | "slimcover@2x": string 52 | } 53 | 54 | export interface Hype { 55 | current: number 56 | required: number 57 | } 58 | 59 | export interface NominationsSummary { 60 | current: number 61 | required: number 62 | } 63 | 64 | export interface Availability { 65 | download_disabled: boolean 66 | more_information: any 67 | } 68 | 69 | export interface Beatmap { 70 | beatmapset_id: number 71 | difficulty_rating: number 72 | id: number 73 | mode: string 74 | status: string 75 | total_length: number 76 | user_id: number 77 | version: string 78 | accuracy: number 79 | ar: number 80 | bpm: number 81 | convert: boolean 82 | count_circles: number 83 | count_sliders: number 84 | count_spinners: number 85 | cs: number 86 | deleted_at: any 87 | drain: number 88 | hit_length: number 89 | is_scoreable: boolean 90 | last_updated: string 91 | mode_int: number 92 | passcount: number 93 | playcount: number 94 | ranked: number 95 | url: string 96 | checksum: string 97 | } 98 | 99 | export interface Beatmap2 { 100 | beatmapset_id: number 101 | difficulty_rating: number 102 | id: number 103 | mode: string 104 | status: string 105 | total_length: number 106 | user_id: number 107 | version: string 108 | } 109 | 110 | export interface Beatmapset { 111 | artist: string 112 | artist_unicode: string 113 | covers: Covers2 114 | creator: string 115 | favourite_count: number 116 | hype: any 117 | id: number 118 | nsfw: boolean 119 | offset: number 120 | play_count: number 121 | preview_url: string 122 | source: string 123 | spotlight: boolean 124 | status: string 125 | title: string 126 | title_unicode: string 127 | track_id?: number 128 | user_id: number 129 | video: boolean 130 | } 131 | 132 | export interface Covers2 { 133 | cover: string 134 | "cover@2x": string 135 | card: string 136 | "card@2x": string 137 | list: string 138 | "list@2x": string 139 | slimcover: string 140 | "slimcover@2x": string 141 | } 142 | -------------------------------------------------------------------------------- /types/v2/users_events.ts: -------------------------------------------------------------------------------- 1 | import { Modes_names } from "../index"; 2 | 3 | export interface UsersEventsResponse { 4 | events: Event[]; 5 | cursor: Cursor; 6 | cursor_string: string; 7 | } 8 | 9 | export interface Cursor { 10 | event_id: number; 11 | } 12 | 13 | export interface Event { 14 | created_at: string; 15 | createdAt: string; 16 | id: number; 17 | type: 'achievement' | 'beatmapsetApprove' | 'beatmapsetDelete' | 'beatmapsetRevive' | 'beatmapsetUpdate' | 'beatmapsetUpload' | 'rank' | 'rankLost' | 'userSupportAgain' | 'userSupportFirst' | 'userSupportGift' | 'usernameChange'; 18 | scoreRank?: string; 19 | rank?: number; 20 | mode?: Modes_names; 21 | beatmap?: Beatmap; 22 | user?: User; 23 | achievement?: Achievement; 24 | beatmapset?: Beatmapset; 25 | approval?: string; 26 | } 27 | 28 | export interface Beatmap { 29 | title: string; 30 | url: string; 31 | } 32 | 33 | export interface User { 34 | username: string; 35 | url: string; 36 | previousUsername?: string; 37 | } 38 | 39 | export interface Achievement { 40 | icon_url: string; 41 | id: number; 42 | name: string; 43 | grouping: string; 44 | ordering: number; 45 | slug: string; 46 | description: string; 47 | mode: Modes_names; 48 | instructions: any; 49 | } 50 | 51 | export interface Beatmapset { 52 | title: string 53 | url: string 54 | } 55 | -------------------------------------------------------------------------------- /types/v2/users_kudosu.ts: -------------------------------------------------------------------------------- 1 | export interface UsersKudosuResponse { 2 | id: number 3 | action: string 4 | amount: number 5 | model: string 6 | created_at: string 7 | giver: any 8 | post: Post 9 | details: Details 10 | } 11 | 12 | export interface Post { 13 | url: string 14 | title: string 15 | } 16 | 17 | export interface Details { 18 | event: string 19 | } 20 | -------------------------------------------------------------------------------- /types/v2/users_lookup.ts: -------------------------------------------------------------------------------- 1 | export interface UsersLookupResponse { 2 | avatar_url: string 3 | country_code: string 4 | default_group: string 5 | id: number 6 | is_active: boolean 7 | is_bot: boolean 8 | is_deleted: boolean 9 | is_online: boolean 10 | is_supporter: boolean 11 | last_visit: string 12 | pm_friends_only: boolean 13 | profile_colour?: string 14 | username: string 15 | country: Country 16 | cover: Cover 17 | groups: Group[] 18 | } 19 | 20 | export interface Country { 21 | code: string 22 | name: string 23 | } 24 | 25 | export interface Cover { 26 | custom_url: string 27 | url: string 28 | id?: string 29 | } 30 | 31 | export interface Group { 32 | colour: string 33 | has_listing: boolean 34 | has_playmodes: boolean 35 | id: number 36 | identifier: string 37 | is_probationary: boolean 38 | name: string 39 | short_name: string 40 | playmodes: any 41 | } 42 | -------------------------------------------------------------------------------- /types/v2/wiki_details.ts: -------------------------------------------------------------------------------- 1 | export interface WikiDetailsResponse { 2 | available_locales: string[] 3 | layout: string 4 | locale: string 5 | markdown: string 6 | path: string 7 | subtitle: any 8 | tags: any[] 9 | title: string 10 | } 11 | -------------------------------------------------------------------------------- /utility/handleErrors.ts: -------------------------------------------------------------------------------- 1 | import { settings } from '../utility/auth'; 2 | 3 | 4 | export const handleErrors = (error: Error): any => { 5 | if (settings.throwErrors) { 6 | throw error; 7 | }; 8 | 9 | 10 | return { error }; 11 | }; -------------------------------------------------------------------------------- /utility/listeners.ts: -------------------------------------------------------------------------------- 1 | export const callbacks: { 2 | /** 3 | * just a hook to call a function after request made 4 | */ 5 | on_request?: (url: string, size: number) => Promise; 6 | } = {}; --------------------------------------------------------------------------------