From 90cd2e72d92015801a2e3ced7a0151c9a5565ea3 Mon Sep 17 00:00:00 2001 From: ck Date: Sun, 24 Sep 2023 09:07:37 +0300 Subject: [PATCH 001/259] export methods 1/? --- index.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 index.ts diff --git a/index.ts b/index.ts new file mode 100644 index 00000000..d7149e96 --- /dev/null +++ b/index.ts @@ -0,0 +1,11 @@ +// export * as v1 from "./api/v1/index"; +// export * as v2 from "./api/v2/index"; + +export * as country from './tools/country'; +export * as mods from './tools/mods'; + +export * as auth from './utility/auth'; + + +// export * as v1 from "./api/v1"; +export * as v2 from "./api/v2/index"; \ No newline at end of file From 5f0789622b3b45511f3bbae808e354b979991f7f Mon Sep 17 00:00:00 2001 From: ck Date: Sun, 24 Sep 2023 09:08:53 +0300 Subject: [PATCH 002/259] remove 3rd party packages --- package.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/package.json b/package.json index c19c7331..faf65e56 100644 --- a/package.json +++ b/package.json @@ -35,9 +35,5 @@ "devDependencies": { "@types/node": "^16.11.7", "typescript": "^4.5.2" - }, - "dependencies": { - "lzma-native": "^8.0.1", - "node-osr": "^1.2.1" } } From 7e04aa2e9aff817245a4bf79f15430362c96b370 Mon Sep 17 00:00:00 2001 From: ck Date: Sun, 24 Sep 2023 09:09:14 +0300 Subject: [PATCH 003/259] build changes --- package.json | 6 +++--- tsconfig.json | 40 +++++++++++++++++++--------------------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index faf65e56..14ab2bfe 100644 --- a/package.json +++ b/package.json @@ -2,14 +2,14 @@ "name": "osu-api-extended", "version": "2.8.52", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", - "main": "dist/index.js", - "types": "dist/index.d.ts", + "main": "index.js", + "types": "index.d.ts", "files": [ "dist/*" ], "scripts": { "build": "tsc", - "tester": "node test/index.js" + "tester": "node test/test_new.js" }, "keywords": [ "osu", diff --git a/tsconfig.json b/tsconfig.json index 8565e21d..f94ddec7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,11 +1,10 @@ { "compilerOptions": { /* Visit https://aka.ms/tsconfig.json to read more about this file */ - /* Basic Options */ // "incremental": true, /* Enable incremental compilation */ - "target": "ESNEXT", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ - "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ + "target": "ES6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ + "module": "CommonJS", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ // "lib": [ // "es2015", // "dom" @@ -13,12 +12,12 @@ // "allowJs": true, /* Allow javascript files to be compiled. */ // "checkJs": true, /* Report errors in .js files. */ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - "declaration": true, /* Generates corresponding '.d.ts' file. */ + "declaration": true, /* Generates corresponding '.d.ts' file. */ // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ - "sourceMap": true, /* Generates corresponding '.map' file. */ + "sourceMap": true, /* Generates corresponding '.map' file. */ // "outFile": "./", /* Concatenate and emit output to single file. */ - "outDir": "dist", /* Redirect output structure to the directory. */ - "rootDir": "src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + "outDir": "dist", /* Redirect output structure to the directory. */ + "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ // "composite": true, /* Enable project compilation */ // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ // "removeComments": true, /* Do not emit comments to output. */ @@ -26,53 +25,52 @@ // "importHelpers": true, /* Import emit helpers from 'tslib'. */ // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ - /* Strict Type-Checking Options */ - "strict": true, /* Enable all strict type-checking options. */ + "strict": true, /* Enable all strict type-checking options. */ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ - "strictNullChecks": false, /* Enable strict null checks. */ + "strictNullChecks": false, /* Enable strict null checks. */ // "strictFunctionTypes": true, /* Enable strict checking of function types. */ // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ - /* Additional Checks */ // "noUnusedLocals": true, /* Report errors on unused locals. */ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ - /* Module Resolution Options */ - "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ // "rootDirs": ["src"], /* List of root folders whose combined content represents the structure of the project at runtime. */ // "typeRoots": ["./"], /* List of folders to include type definitions from. */ // "types": [], /* Type declaration files to be included in compilation. */ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - /* Source Map Options */ // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ - /* Experimental Options */ // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ - /* Advanced Options */ - "skipLibCheck": true, /* Skip type checking of declaration files. */ - "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + "skipLibCheck": true, /* Skip type checking of declaration files. */ + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ }, - "include": ["src/**/*"], + "include": [ + "**/*" + ], "exclude": [ "node_modules", - "dist" + "dist", + "src", + "wiki", + "test" ] } \ No newline at end of file From 276b2056e0698daf1acc498d39846ffbc6195ef1 Mon Sep 17 00:00:00 2001 From: ck Date: Sun, 24 Sep 2023 09:09:38 +0300 Subject: [PATCH 004/259] api v2 routes 1/? --- api/v2/index.ts | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 api/v2/index.ts diff --git a/api/v2/index.ts b/api/v2/index.ts new file mode 100644 index 00000000..d3b84d51 --- /dev/null +++ b/api/v2/index.ts @@ -0,0 +1,41 @@ +import users_details from "./users/details"; + + +export const users = { + details: users_details, +}; + + + +import user_details from "./user/details"; + + +export const user = { + details: user_details, +}; + + + +import scores_details from "./scores/details"; +import scores_user_list from "./scores/user/list"; + +export const scores = { + details: scores_details, + user: { + /** + * @deprecated since 3.0.0. Use ***v2.scores.user.list*** instead + */ + category: scores_user_list, + list: scores_user_list, + } +}; + + + +import site_ranking_details from "./site/ranking/details"; + +export const site = { + ranking: { + details: site_ranking_details, + }, +}; \ No newline at end of file From 01705c2d406568eb56665665ffca448458fdd3c2 Mon Sep 17 00:00:00 2001 From: ck Date: Sun, 24 Sep 2023 09:10:24 +0300 Subject: [PATCH 005/259] v2 endpoints 1/? --- api/v2/scores/details.ts | 19 +++++++ api/v2/scores/user/list.ts | 94 ++++++++++++++++++++++++++++++++++ api/v2/site/ranking/details.ts | 22 ++++++++ api/v2/user/details.ts | 20 ++++++++ api/v2/users/details.ts | 18 +++++++ 5 files changed, 173 insertions(+) create mode 100644 api/v2/scores/details.ts create mode 100644 api/v2/scores/user/list.ts create mode 100644 api/v2/site/ranking/details.ts create mode 100644 api/v2/user/details.ts create mode 100644 api/v2/users/details.ts diff --git a/api/v2/scores/details.ts b/api/v2/scores/details.ts new file mode 100644 index 00000000..848a3dfb --- /dev/null +++ b/api/v2/scores/details.ts @@ -0,0 +1,19 @@ +import { request } from "../../../utility/request"; +import { gamemode_names } from "../../../utility/types"; + + + +const name = async (score_id: number, mode: gamemode_names) => { + if (mode == null) + throw new Error('Gamemode name not specified'); + + + const data = await request(`https://osu.ppy.sh/api/v2/scores/${mode}/${score_id}`, { + method: 'GET', + }); + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/scores/user/list.ts b/api/v2/scores/user/list.ts new file mode 100644 index 00000000..31138500 --- /dev/null +++ b/api/v2/scores/user/list.ts @@ -0,0 +1,94 @@ +import { request } from "../../../../utility/request"; +import { gamemode_names } from "../../../../utility/types"; +import mods from '../../../../tools/mods'; + + + +export const description = { + params: [ + { + type: 'number', + name: 'user', + optional: false, + description: 'id of the user', + }, + { + type: 'string', + name: 'type', + optional: false, + description: '\`\`\`recent\`\`\` or \`\`\`best\`\`\` or \`\`\`firsts\`\`\` or \`\`\`pinned\`\`\`', + }, + { + name: 'object', + params: [ + { + type: 'boolean', + name: 'include_fails', + options: false, + optional: true, + description: 'Only for \`\`\`recent\`\`\` scores, include scores of failed plays. Set to \`\`\`true\`\`\` to include them. Defaults to \`\`\`false\`\`\`', + }, + { + type: 'string', + name: 'mode', + optional: true, + description: '\`\`\`osu\`\`\` or \`\`\`fruits\`\`\` or \`\`\`mania\`\`\` or \`\`\`taiko\`\`\`', + }, + { + type: 'number', + name: 'mods', + options: false, + optional: true, + description: 'Use \`\`\`mods.enums\`\`\` instead of mods id or name', + }, + { + type: 'number', + name: 'limit', + optional: true, + description: 'Maximum number of results', + }, + { + type: 'string', + name: 'offset', + optional: true, + description: 'Result offset for pagination', + }, + ] + }, + ], +}; + + +const name = async (user_id: number, type: 'recent' | 'best' | 'firsts' | 'pinned', object?: { + include_fails?: boolean, + mode?: gamemode_names, + limit?: number, + offset?: number, + mods?: number +}) => { + if (object.include_fails) + // @ts-ignore + object.include_fails = object.include_fails == true ? 1 : 0; + + const data = await request(`https://osu.ppy.sh/api/v2/users/${user_id}/scores/${type}`, { + method: 'GET', + params: object, + }); + + // check if scores exists. Sometimes there can an error + if (Array.isArray(data)) { + const transform = data.map((v, i) => ({ + index: i + 1, + mods_id: mods.id(v.mods.join('')) || 0, + ...v + })); + + if (object?.mods) return transform.filter(r => (r.mods_id & object.mods) > 0); + return transform; + }; + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/site/ranking/details.ts b/api/v2/site/ranking/details.ts new file mode 100644 index 00000000..a380a97a --- /dev/null +++ b/api/v2/site/ranking/details.ts @@ -0,0 +1,22 @@ +import { gamemode_names, ranking_types, country_codes } from "../../../../utility/types"; +import { request } from "../../../../utility/request"; + + + +const name = async (mode: gamemode_names, type: ranking_types, object?: { + country?: country_codes, + "cursor[page]"?: number, + filter?: 'all' | 'friends', + spotlight_id?: number, + variant?: '4k' | '7k', +}) => { + const data = await request(`https://osu.ppy.sh/api/v2/rankings/${mode}/${type}`, { + method: 'GET', + params: object, + }); + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/user/details.ts b/api/v2/user/details.ts new file mode 100644 index 00000000..c594ae9e --- /dev/null +++ b/api/v2/user/details.ts @@ -0,0 +1,20 @@ +import { request } from "../../../utility/request"; +import { gamemode_names } from "../../../utility/types"; + + + +const name = async (user: number, { mode, key }: { mode?: gamemode_names, key?: 'id' | 'username' } = {}) => { + let url = `https://osu.ppy.sh/api/v2/users/${user}`; + if (mode != null) + url += `/${mode}`; + + const data = await request(url, { + method: 'GET', + params: { key }, + }); + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/users/details.ts b/api/v2/users/details.ts new file mode 100644 index 00000000..8c994e5e --- /dev/null +++ b/api/v2/users/details.ts @@ -0,0 +1,18 @@ +import { request } from "../../../utility/request"; + + + +const name = async (ids: number[]) => { + const data = await request(`https://osu.ppy.sh/api/v2/users`, { + method: 'GET', + params: { + ids + }, + }); + + if (data.users) return data.users; + return data; +}; + + +export default name; \ No newline at end of file From 85f1c13610624cb83f58969f71f7cb3b1a049edf Mon Sep 17 00:00:00 2001 From: ck Date: Sun, 24 Sep 2023 09:10:32 +0300 Subject: [PATCH 006/259] tools 1/? --- tools/country.ts | 315 +++++++++++++++++++++++++++++++++++++++++++++++ tools/mods.ts | 140 +++++++++++++++++++++ 2 files changed, 455 insertions(+) create mode 100644 tools/country.ts create mode 100644 tools/mods.ts diff --git a/tools/country.ts b/tools/country.ts new file mode 100644 index 00000000..dee6e9a2 --- /dev/null +++ b/tools/country.ts @@ -0,0 +1,315 @@ +export const names = { + US: "United States", + RU: "Russian Federation", + DE: "Germany", + PL: "Poland", + FR: "France", + JP: "Japan", + CA: "Canada", + BR: "Brazil", + GB: "United Kingdom", + TW: "Taiwan", + KR: "South Korea", + CN: "China", + AU: "Australia", + ID: "Indonesia", + UA: "Ukraine", + PH: "Philippines", + CL: "Chile", + FI: "Finland", + AR: "Argentina", + NL: "Netherlands", + SE: "Sweden", + SG: "Singapore", + MX: "Mexico", + MY: "Malaysia", + ES: "Spain", + IT: "Italy", + HK: "Hong Kong", + TH: "Thailand", + VN: "Vietnam", + NO: "Norway", + CZ: "Czech Republic", + TR: "Turkey", + BY: "Belarus", + AT: "Austria", + BE: "Belgium", + PT: "Portugal", + RO: "Romania", + HU: "Hungary", + DK: "Denmark", + LT: "Lithuania", + KZ: "Kazakhstan", + NZ: "New Zealand", + PE: "Peru", + CH: "Switzerland", + CO: "Colombia", + IL: "Israel", + EE: "Estonia", + BG: "Bulgaria", + SK: "Slovakia", + GR: "Greece", + LV: "Latvia", + VE: "Venezuela", + RS: "Serbia", + IE: "Ireland", + HR: "Croatia", + SA: "Saudi Arabia", + UY: "Uruguay", + ZA: "South Africa", + AE: "United Arab Emirates", + SI: "Slovenia", + IN: "India", + EC: "Ecuador", + MA: "Morocco", + CR: "Costa Rica", + MD: "Moldova", + DO: "Dominican Republic", + BN: "Brunei", + EG: "Egypt", + RE: "Reunion", + MO: "Macau", + TN: "Tunisia", + PA: "Panama", + DZ: "Algeria", + MN: "Mongolia", + PY: "Paraguay", + KW: "Kuwait", + PR: "Puerto Rico", + GE: "Georgia", + BO: "Bolivia", + SV: "El Salvador", + QA: "Qatar", + GT: "Guatemala", + LU: "Luxembourg", + UZ: "Uzbekistan", + KG: "Kyrgyzstan", + MK: "North Macedonia", + KH: "Cambodia", + BA: "Bosnia and Herzegovina", + IS: "Iceland", + JO: "Jordan", + PK: "Pakistan", + TT: "Trinidad and Tobago", + CY: "Cyprus", + HN: "Honduras", + NI: "Nicaragua", + BH: "Bahrain", + MV: "Maldives", + BD: "Bangladesh", + PF: "French Polynesia", + LB: "Lebanon", + NP: "Nepal", + IQ: "Iraq", + GU: "Guam", + AZ: "Azerbaijan", + AL: "Albania", + MT: "Malta", + MM: "Myanmar", + NC: "New Caledonia", + OM: "Oman", + IR: "Iran, Islamic Republic of", + AM: "Armenia", + GP: "Guadeloupe", + MQ: "Martinique", + JM: "Jamaica", + LA: "Lao People's Democratic Republic", + LK: "Sri Lanka", + PS: "Palestinian Territory Occupied", + MU: "Mauritius", + SY: "Syrian Arab Republic", + ME: "Montenegro", + FO: "Faroe Islands", + JE: "Jersey", + GF: "French Guiana", + MP: "Northern Mariana Islands", + IM: "Isle of Man", + SR: "Suriname", + BZ: "Belize", + BB: "Barbados", + AW: "Aruba", + LY: "Libya", + AX: "Aland Islands", + GG: "Guernsey", + MG: "Madagascar", + SD: "Sudan", + LI: "Liechtenstein", + BS: "Bahamas", + KE: "Kenya", + GL: "Greenland", + BM: "Bermuda", + EU: "Europe", + CI: "Cote D'Ivoire", + GY: "Guyana", + GI: "Gibraltar", + VI: "Virgin Islands, U.S.", + AD: "Andorra", + LC: "Saint Lucia", + TJ: "Tajikistan", + AG: "Antigua and Barbuda", + SN: "Senegal", + PM: "Saint Pierre and Miquelon", + CK: "Cook Islands", + AQ: "Antarctica", + CF: "Central African Republic", + LR: "Liberia", + ER: "Eritrea", +}; + +export const code = { + "United States": 'US', + "Russian Federation": 'RU', + "Germany": 'DE', + "Poland": 'PL', + "France": 'FR', + "Japan": 'JP', + "Canada": 'CA', + "Brazil": 'BR', + "United Kingdom": 'GB', + "Taiwan": 'TW', + "South Korea": 'KR', + "China": 'CN', + "Australia": 'AU', + "Indonesia": 'ID', + "Ukraine": 'UA', + "Philippines": 'PH', + "Chile": 'CL', + "Finland": 'FI', + "Argentina": 'AR', + "Netherlands": 'NL', + "Sweden": 'SE', + "Singapore": 'SG', + "Mexico": 'MX', + "Malaysia": 'MY', + "Spain": 'ES', + "Italy": 'IT', + "Hong Kong": 'HK', + "Thailand": 'TH', + "Vietnam": 'VN', + "Norway": 'NO', + "Czech Republic": 'CZ', + "Turkey": 'TR', + "Belarus": 'BY', + "Austria": 'AT', + "Belgium": 'BE', + "Portugal": 'PT', + "Romania": 'RO', + "Hungary": 'HU', + "Denmark": 'DK', + "Lithuania": 'LT', + "Kazakhstan": 'KZ', + "New Zealand": 'NZ', + "Peru": 'PE', + "Switzerland": 'CH', + "Colombia": 'CO', + "Israel": 'IL', + "Estonia": 'EE', + "Bulgaria": 'BG', + "Slovakia": 'SK', + "Greece": 'GR', + "Latvia": 'LV', + "Venezuela": 'VE', + "Serbia": 'RS', + "Ireland": 'IE', + "Croatia": 'HR', + "Saudi Arabia": 'SA', + "Uruguay": 'UY', + "South Africa": 'ZA', + "United Arab Emirates": 'AE', + "Slovenia": 'SI', + "India": 'IN', + "Ecuador": 'EC', + "Morocco": 'MA', + "Costa Rica": 'CR', + "Moldova": 'MD', + "Dominican Republic": 'DO', + "Brunei": 'BN', + "Egypt": 'EG', + "Reunion": 'RE', + "Macau": 'MO', + "Tunisia": 'TN', + "Panama": 'PA', + "Algeria": 'DZ', + "Mongolia": 'MN', + "Paraguay": 'PY', + "Kuwait": 'KW', + "Puerto Rico": 'PR', + "Georgia": 'GE', + "Bolivia": 'BO', + "El Salvador": 'SV', + "Qatar": 'QA', + "Guatemala": 'GT', + "Luxembourg": 'LU', + "Uzbekistan": 'UZ', + "Kyrgyzstan": 'KG', + "North Macedonia": 'MK', + "Cambodia": 'KH', + "Bosnia and Herzegovina": 'BA', + "Iceland": 'IS', + "Jordan": 'JO', + "Pakistan": 'PK', + "Trinidad and Tobago": 'TT', + "Cyprus": 'CY', + "Honduras": 'HN', + "Nicaragua": 'NI', + "Bahrain": 'BH', + "Maldives": 'MV', + "Bangladesh": 'BD', + "French Polynesia": 'PF', + "Lebanon": 'LB', + "Nepal": 'NP', + "Iraq": 'IQ', + "Guam": 'GU', + "Azerbaijan": 'AZ', + "Albania": 'AL', + "Malta": 'MT', + "Myanmar": 'MM', + "New Caledonia": 'NC', + "Oman": 'OM', + "Iran, Islamic Republic of": 'IR', + "Armenia": 'AM', + "Guadeloupe": 'GP', + "Martinique": 'MQ', + "Jamaica": 'JM', + "Lao People's Democratic Republic": 'LA', + "Sri Lanka": 'LK', + "Palestinian Territory Occupied": 'PS', + "Mauritius": 'MU', + "Syrian Arab Republic": 'SY', + "Montenegro": 'ME', + "Faroe Islands": 'FO', + "Jersey": 'JE', + "French Guiana": 'GF', + "Northern Mariana Islands": 'MP', + "Isle of Man": 'IM', + "Suriname": 'SR', + "Belize": 'BZ', + "Barbados": 'BB', + "Aruba": 'AW', + "Libya": 'LY', + "Aland Islands": 'AX', + "Guernsey": 'GG', + "Madagascar": 'MG', + "Sudan": 'SD', + "Liechtenstein": 'LI', + "Bahamas": 'BS', + "Kenya": 'KE', + "Greenland": 'GL', + "Bermuda": 'BM', + "Europe": 'EU', + "Cote D ' Ivoire": 'CI', + "Guyana": 'GY', + "Gibraltar": 'GI', + "Virgin Islands, U.S.": 'VI', + "Andorra": 'AD', + "Saint Lucia": 'LC', + "Tajikistan": 'TJ', + "Antigua and Barbuda": 'AG', + "Senegal": 'SN', + "Saint Pierre and Miquelon": 'PM', + "Cook Islands": 'CK', + "Antarctica": 'AQ', + "Central African Republic": 'CF', + "Liberia": 'LR', + "Eritrea": 'ER', +} \ No newline at end of file diff --git a/tools/mods.ts b/tools/mods.ts new file mode 100644 index 00000000..20438ca9 --- /dev/null +++ b/tools/mods.ts @@ -0,0 +1,140 @@ +const num_codes: { [key: string]: string } = { + 1: 'NF', + 2: 'EZ', + 4: 'TD', + 8: 'HD', + 16: 'HR', + 32: 'SD', + 64: 'DT', + 128: 'RX', + 256: 'HT', + 576: 'NC', + 1024: 'FL', + 2048: 'AT', + 4096: 'SO', + 8192: 'AP', + 16416: 'PF', + 32768: '4K', + 65536: '5K', + 131072: '6K', + 262144: '7K', + 524288: '8K', + 1048576: 'FI', + 2097152: 'RD', + 4194304: 'LM', + 8388608: 'Target', + 16777216: '9K', + 33554432: 'KeyCoop', + 67108864: '1K', + 134217728: '3K', + 268435456: '2K', + 536870912: 'ScoreV2', + 1073741824: 'MR', +}; + +export const enums = { + None: 0, + NoFail: 1, + Easy: 1 << 1, + TouchDevice: 1 << 2, + Hidden: 1 << 3, + HardRock: 1 << 4, + SuddenDeath: 1 << 5, + DoubleTime: 1 << 6, + Relax: 1 << 7, + HalfTime: 1 << 8, + Nightcore: 1 << 9, // DoubleTime mod + Flashlight: 1 << 10, + Autoplay: 1 << 11, + SpunOut: 1 << 12, + Relax2: 1 << 13, // Autopilot + Perfect: 1 << 14, // SuddenDeath mod + Key4: 1 << 15, + Key5: 1 << 16, + Key6: 1 << 17, + Key7: 1 << 18, + Key8: 1 << 19, + FadeIn: 1 << 20, + Random: 1 << 21, + Cinema: 1 << 22, + Target: 1 << 23, + Key9: 1 << 24, + KeyCoop: 1 << 25, + Key1: 1 << 26, + Key3: 1 << 27, + Key2: 1 << 28, + KeyMod: 521109504, + FreeModAllowed: 522171579, + ScoreIncreaseMods: 1049662 +}; + +const mods_order: { [key: string]: number } = { + nf: 0, + ez: 1, + hd: 2, + dt: 3, + nc: 3, + ht: 3, + hr: 4, + so: 5, + sd: 5, + pf: 5, + fl: 6, + td: 7, +}; + + +/** + * + * @param mods Mods number + * @returns {string} Mods name + */ +const name = (mods: number): string => { + let enabled = []; + let _mods = mods; + let converted = ''; + + const values = Object.keys(num_codes).map(a => Number(a)); + + for (let i = values.length - 1; i >= 0; i--) { + const v = values[i]; + if (_mods >= v) { + const mode = num_codes[v]; + enabled.push({ i: mods_order[mode.toLowerCase()], n: mode }); + _mods -= v; + }; + }; + + enabled = enabled.sort((a, b) => (a.i > b.i ? 1 : b.i > a.i ? -1 : 0)); + enabled.filter(r => converted += r.n); + + + // if (converted === '') return 'NM'; + return converted; +}; + +/** + * + * @param mods Mods name + * @returns {string | undefined} Mods number + */ +const id = (mods: string | number): number | undefined => { + if (!mods) return undefined; + if (typeof mods == 'number') return mods; + + let _mods = 0; + const name = mods.match(/.{1,2}/g); + if (name == null) return undefined; + + const values: string[] = Object.keys(num_codes).map((a) => a); + for (let i = 0; i < name.length; i++) { + const find = values.find((v) => num_codes[v].toLowerCase() === name[i].toLowerCase()); + _mods += parseInt(find); + }; + + return _mods; +}; + + +export { id, name, num_codes }; +export default { id, name, enums, num_codes }; \ No newline at end of file From 269ae228f5d7b66903af489b8eaf541556fe6fbf Mon Sep 17 00:00:00 2001 From: ck Date: Sun, 24 Sep 2023 09:10:49 +0300 Subject: [PATCH 007/259] utility 1/? --- utility/auth.ts | 134 ++++++++++++++++++++++++++++++++++++++++++ utility/request.ts | 142 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 276 insertions(+) create mode 100644 utility/auth.ts create mode 100644 utility/request.ts diff --git a/utility/auth.ts b/utility/auth.ts new file mode 100644 index 00000000..66ba705f --- /dev/null +++ b/utility/auth.ts @@ -0,0 +1,134 @@ +// PACKAGES +// import { execSync } from 'child_process'; +// import readln from "readline"; + + +// IMPORTS +import { request } from "./request"; +// import { gamemode_names } from './types'; + + +export type auth_scopes = [ + 'chat.read' | + 'chat.write' | + 'chat.write_manage' | + 'delegate' | + 'forum.write' | + 'friends.read' | + 'identify' | + 'public' +]; + +export type auth_login = { + access_token: string, + expires_in: number +} + +const credentials: { + type: number, + username: string, + password: string, + clientId: number, + clientSecret: string, + redirect_uri: string, + scope: auth_scopes, +} = { + type: 0, + username: '', + password: '', + clientId: 0, + clientSecret: '', + redirect_uri: '', + scope: ['public'], +}; + + +export let cache_v1: string = ''; +export let cache_v2: string = ''; + + +export const set_v1 = (v: string) => cache_v1 = v; +export const set_v2 = (v: string) => cache_v2 = v; + +const isInitial = () => cache_v2 != ''; + +const store_credentials = (type: number, obj: any) => { + if (type == 1) { + credentials.type = 1; + credentials.username = obj.username; + credentials.password = obj.password; + }; + + if (type == 2) { + credentials.type = 2; + credentials.clientId = obj.clientId; + credentials.clientSecret = obj.clientSecret; + credentials.scope = obj.scope; + }; + + if (type == 3) { + credentials.type = 3; + credentials.clientId = obj.clientId; + credentials.clientSecret = obj.clientSecret; + credentials.redirect_uri = obj.redirect_uri; + credentials.scope = obj.scope; + }; +}; + + +export const update_cache_token = async () => { + // if (credentials.type == 1) await lazer_user(credentials.username, credentials.password); + if (credentials.type == 2) await client_login(credentials.clientId, credentials.clientSecret, credentials.scope); + // if (credentials.type == 3) await cli(credentials.clientId, credentials.clientSecret, credentials.redirect_uri, credentials.scope); + + return true; +}; + +/** + * # Authorization via osu client + * - clientId - osu Client ID + * - clientSecret - osu Client Secret + * - _**(optional)**_ scopes - list of scopes + * - chat.read - Allows read chat messages on a user's behalf. + * - chat.write - Allows sending chat messages on a user's behalf. + * - chat.write_manage - Allows joining and leaving chat channels on a user's behalf. + * - delegate - Allows acting as the owner of a client; only available for Client Credentials Grant. + * - forum.write - Allows creating and editing forum posts on a user's behalf. + * - friends.read - Allows reading of the user's friend list. + * - identify - Allows reading of the public profile of the user (/me). + * - public - Allows reading of publicly available data on behalf of the user. + */ +export const client_login = async (clientId: number, clientSecret: string, scopes?: auth_scopes): Promise => { + if (scopes == null) + throw new Error('Specify scopes'); + + if (scopes != null && !Array.isArray(scopes)) + throw new Error('Scopes must be an Array'); + + + // add public scopes + if (scopes == null) + scopes = ['public']; + + + if (!isInitial()) store_credentials(2, { clientId, clientSecret, scopes }); + + const { access_token, expires_in } = await request('https://osu.ppy.sh/oauth/token', { + method: 'POST', + headers: { + "Accept": "application/json", + "Content-Type": "application/json", + }, + data: JSON.stringify({ + grant_type: 'client_credentials', + client_id: clientId, + client_secret: clientSecret, + scope: scopes.join(' '), + code: 'code', + }) + }); + + + cache_v2 = access_token; + return { access_token, expires_in }; +}; \ No newline at end of file diff --git a/utility/request.ts b/utility/request.ts new file mode 100644 index 00000000..1a8a9a29 --- /dev/null +++ b/utility/request.ts @@ -0,0 +1,142 @@ +// PACKAGES +import https from 'https'; +// import fs from "fs"; + + +// CREDENTIALS +import * as auth from "./auth"; + + +// TYPES +interface RequestParams { + method?: string; + params?: { [key: string]: any }; + headers?: { [key: string]: string }; + data?: string; +}; + +export interface RequestType { + (url: string, params: { + method: string, + data?: string, + headers?: { [key: string]: string }, + params?: object | [object, ...object[]]; + }): Promise; +}; + + +// VALUES +const TIMEOUT_MS = 60000; +let total_retries = 0; + + +const generateQueryString = (obj: any, trail: string = ''): string => { + const params: string[] = []; + console.time('generateQueryString'); + + + const processValue = (key: string, value: any) => { + if (Array.isArray(value)) { + value.forEach((item) => { + params.push(`${key}[]=${encodeURIComponent(item)}`); + }); + } else if (typeof value === 'object' && value !== null) { + const newTrail = trail ? `${trail}.${key}` : key; + params.push(generateQueryString(value, newTrail)); + } else if (typeof value === 'number' && value > 0) { + params.push(`${key}=${value}`); + } else if (typeof value === 'string') { + params.push(`${key}=${encodeURIComponent(value)}`); + } + }; + + for (const key in obj) { + if (obj.hasOwnProperty(key)) { + const value = obj[key]; + if (value !== undefined) { + processValue(key, value); + } + } + } + + console.timeEnd('generateQueryString'); + + return params.join('&'); +}; + + +export const request = (url: string, { method, headers, data, params = {} }: RequestParams = {}): Promise => new Promise((resolve, reject) => { + // check required args + if (url == null) + throw new Error('URL not specified'); + + if (method == null) + throw new Error('Method not specified'); + + + // V1 add credentials + if (url.includes('https://osu.ppy.sh/api/') && !url.includes('https://osu.ppy.sh/api/v2')) + params.k = params.v1 || auth.cache_v1; + + // V2 add credentials + if (url.includes('https://osu.ppy.sh/api/v2')) + headers = { + // @ts-ignore + Authorization: `Bearer ${params.v2 || auth.cache_v2}`, + Accept: `application/json`, + 'Content-Type': `application/json`, + }; + + + const generate_query = generateQueryString(params); + const build_url = url + (generate_query ? `?${generate_query}` : ''); + + console.log({ url: build_url, method, headers, data }); + const req = https.request(build_url, { method, headers }, (response) => { + const chunks: any[] = []; + + // handle response events + response.on('data', (chunk: any) => chunks.push(chunk)); + response.on('end', async () => { + const data = Buffer.concat(chunks).toString(); + + if (/^application\/json/.test(response.headers['content-type'])) { + try { + const parse = JSON.parse(data); + if (parse.authentication === 'basic' && auth.cache_v2 && total_retries < 3) { + await auth.update_cache_token(); + total_retries++; + + + const retry_request = await request(url, { method, headers, data, params }); + return resolve(retry_request); + }; + + + total_retries = 0; + return resolve(parse); + } catch (error) { + reject(error); + }; + }; + + + resolve(data); + }); + }); + + + // throw error + req.on('error', reject); + + // timeout + req.setTimeout(TIMEOUT_MS, () => { + req.destroy(); + reject(new Error(`Request to ${build_url} time out after ${TIMEOUT_MS}ms`)); + }); + + + // write body to request, if specified + if (data) req.write(data); + req.end(); +}); \ No newline at end of file From 6125cabb044ce4fbc0d8fe4337a1181b4b6c48e5 Mon Sep 17 00:00:00 2001 From: ck Date: Sun, 24 Sep 2023 09:11:23 +0300 Subject: [PATCH 008/259] types 1/? --- api/v2/scores/details.ts | 2 +- api/v2/scores/user/list.ts | 2 +- api/v2/site/ranking/details.ts | 2 +- api/v2/user/details.ts | 2 +- types/index.ts | 6 ++++++ 5 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 types/index.ts diff --git a/api/v2/scores/details.ts b/api/v2/scores/details.ts index 848a3dfb..646d5c04 100644 --- a/api/v2/scores/details.ts +++ b/api/v2/scores/details.ts @@ -1,5 +1,5 @@ import { request } from "../../../utility/request"; -import { gamemode_names } from "../../../utility/types"; +import { gamemode_names } from "../../../types"; diff --git a/api/v2/scores/user/list.ts b/api/v2/scores/user/list.ts index 31138500..2c7dac15 100644 --- a/api/v2/scores/user/list.ts +++ b/api/v2/scores/user/list.ts @@ -1,5 +1,5 @@ import { request } from "../../../../utility/request"; -import { gamemode_names } from "../../../../utility/types"; +import { gamemode_names } from "../../../../types"; import mods from '../../../../tools/mods'; diff --git a/api/v2/site/ranking/details.ts b/api/v2/site/ranking/details.ts index a380a97a..a7722734 100644 --- a/api/v2/site/ranking/details.ts +++ b/api/v2/site/ranking/details.ts @@ -1,4 +1,4 @@ -import { gamemode_names, ranking_types, country_codes } from "../../../../utility/types"; +import { gamemode_names, ranking_types, country_codes } from "../../../../types"; import { request } from "../../../../utility/request"; diff --git a/api/v2/user/details.ts b/api/v2/user/details.ts index c594ae9e..058daf02 100644 --- a/api/v2/user/details.ts +++ b/api/v2/user/details.ts @@ -1,5 +1,5 @@ import { request } from "../../../utility/request"; -import { gamemode_names } from "../../../utility/types"; +import { gamemode_names } from "../../../types"; diff --git a/types/index.ts b/types/index.ts new file mode 100644 index 00000000..cec43d7f --- /dev/null +++ b/types/index.ts @@ -0,0 +1,6 @@ +export type gamemode_names = 'osu' | 'fruits' | 'mania' | 'taiko'; + +export type ranking_types = 'charts' | 'country' | 'performance' | 'score'; + +export type country_names = "United States" | "Russian Federation" | "Germany" | "Poland" | "France" | "Japan" | "Canada" | "Brazil" | "United Kingdom" | "Taiwan" | "South Korea" | "China" | "Australia" | "Indonesia" | "Ukraine" | "Philippines" | "Chile" | "Finland" | "Argentina" | "Netherlands" | "Sweden" | "Singapore" | "Mexico" | "Malaysia" | "Spain" | "Italy" | "Hong Kong" | "Thailand" | "Vietnam" | "Norway" | "Czech Republic" | "Turkey" | "Belarus" | "Austria" | "Belgium" | "Portugal" | "Romania" | "Hungary" | "Denmark" | "Lithuania" | "Kazakhstan" | "New Zealand" | "Peru" | "Switzerland" | "Colombia" | "Israel" | "Estonia" | "Bulgaria" | "Slovakia" | "Greece" | "Latvia" | "Venezuela" | "Serbia" | "Ireland" | "Croatia" | "Saudi Arabia" | "Uruguay" | "South Africa" | "United Arab Emirates" | "Slovenia" | "India" | "Ecuador" | "Morocco" | "Costa Rica" | "Moldova" | "Dominican Republic" | "Brunei" | "Egypt" | "Reunion" | "Macau" | "Tunisia" | "Panama" | "Algeria" | "Mongolia" | "Paraguay" | "Kuwait" | "Puerto Rico" | "Georgia" | "Bolivia" | "El Salvador" | "Qatar" | "Guatemala" | "Luxembourg" | "Uzbekistan" | "Kyrgyzstan" | "North Macedonia" | "Cambodia" | "Bosnia and Herzegovina" | "Iceland" | "Jordan" | "Pakistan" | "Trinidad and Tobago" | "Cyprus" | "Honduras" | "Nicaragua" | "Bahrain" | "Maldives" | "Bangladesh" | "French Polynesia" | "Lebanon" | "Nepal" | "Iraq" | "Guam" | "Azerbaijan" | "Albania" | "Malta" | "Myanmar" | "New Caledonia" | "Oman" | "Iran, Islamic Republic of" | "Armenia" | "Guadeloupe" | "Martinique" | "Jamaica" | "Lao People 's Democratic Republic" | "Sri Lanka" | "Palestinian Territory Occupied" | "Mauritius" | "Syrian Arab Republic" | "Montenegro" | "Faroe Islands" | "Jersey" | "French Guiana" | "Northern Mariana Islands" | "Isle of Man" | "Suriname" | "Belize" | "Barbados" | "Aruba" | "Libya" | "Aland Islands" | "Guernsey" | "Madagascar" | "Sudan" | "Liechtenstein" | "Bahamas" | "Kenya" | "Greenland" | "Bermuda" | "Europe" | "Cote D ' Ivoire" | "Guyana" | "Gibraltar" | "Virgin Islands, U.S." | "Andorra" | "Saint Lucia" | "Tajikistan" | "Antigua and Barbuda" | "Senegal" | "Saint Pierre and Miquelon" | "Cook Islands" | "Antarctica" | "Central African Republic" | "Liberia" | "Eritrea"; +export type country_codes = "US" | "RU" | "DE" | "PL" | "FR" | "JP" | "CA" | "BR" | "GB" | "TW" | "KR" | "CN" | "AU" | "ID" | "UA" | "PH" | "CL" | "FI" | "AR" | "NL" | "SE" | "SG" | "MX" | "MY" | "ES" | "IT" | "HK" | "TH" | "VN" | "NO" | "CZ" | "TR" | "BY" | "AT" | "BE" | "PT" | "RO" | "HU" | "DK" | "LT" | "KZ" | "NZ" | "PE" | "CH" | "CO" | "IL" | "EE" | "BG" | "SK" | "GR" | "LV" | "VE" | "RS" | "IE" | "HR" | "SA" | "UY" | "ZA" | "AE" | "SI" | "IN" | "EC" | "MA" | "CR" | "MD" | "DO" | "BN" | "EG" | "RE" | "MO" | "TN" | "PA" | "DZ" | "MN" | "PY" | "KW" | "PR" | "GE" | "BO" | "SV" | "QA" | "GT" | "LU" | "UZ" | "KG" | "MK" | "KH" | "BA" | "IS" | "JO" | "PK" | "TT" | "CY" | "HN" | "NI" | "BH" | "MV" | "BD" | "PF" | "LB" | "NP" | "IQ" | "GU" | "AZ" | "AL" | "MT" | "MM" | "NC" | "OM" | "IR" | "AM" | "GP" | "MQ" | "JM" | "LA" | "LK" | "PS" | "MU" | "SY" | "ME" | "FO" | "JE" | "GF" | "MP" | "IM" | "SR" | "BZ" | "BB" | "AW" | "LY" | "AX" | "GG" | "MG" | "SD" | "LI" | "BS" | "KE" | "GL" | "BM" | "EU" | "CI" | "GY" | "GI" | "VI" | "AD" | "LC" | "TJ" | "AG" | "SN" | "PM" | "CK" | "AQ" | "CF" | "LR" | "ER"; \ No newline at end of file From a6973cf896190c939327570d7937582dbc7d5678 Mon Sep 17 00:00:00 2001 From: ck Date: Sun, 24 Sep 2023 09:14:34 +0300 Subject: [PATCH 009/259] leftovers --- index.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/index.ts b/index.ts index d7149e96..aa492650 100644 --- a/index.ts +++ b/index.ts @@ -1,11 +1,7 @@ -// export * as v1 from "./api/v1/index"; -// export * as v2 from "./api/v2/index"; - export * as country from './tools/country'; export * as mods from './tools/mods'; export * as auth from './utility/auth'; -// export * as v1 from "./api/v1"; export * as v2 from "./api/v2/index"; \ No newline at end of file From 3f25abd5f1c4ad2ad623f6ddb2d625fb30136f0f Mon Sep 17 00:00:00 2001 From: ck Date: Sun, 24 Sep 2023 09:55:14 +0300 Subject: [PATCH 010/259] v2 event endpoint --- api/v2/index.ts | 2 ++ api/v2/users/events.ts | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 api/v2/users/events.ts diff --git a/api/v2/index.ts b/api/v2/index.ts index d3b84d51..3b9b5562 100644 --- a/api/v2/index.ts +++ b/api/v2/index.ts @@ -1,8 +1,10 @@ import users_details from "./users/details"; +import users_events from "./users/events"; export const users = { details: users_details, + events: users_events, }; diff --git a/api/v2/users/events.ts b/api/v2/users/events.ts new file mode 100644 index 00000000..ba134456 --- /dev/null +++ b/api/v2/users/events.ts @@ -0,0 +1,30 @@ +import { request } from "../../../utility/request"; +import { UsersEvents, Event } from '../../../types/users_events'; + + + +const name = async ({ sort, cursor_string, type }: { + cursor_string?: string; + sort?: 'id_desc' | 'id_asc', + type?: ('achievement' | 'beatmapPlaycount' | 'beatmapsetApprove' | 'beatmapsetDelete' | 'beatmapsetRevive' | 'beatmapsetUpdate' | 'beatmapsetUpload' | 'rank' | 'userSupportAgain' | 'userSupportFirst' | 'userSupportGift' | 'usernameChange')[] +} = {}): Promise => { + const data: UsersEvents = await request(`https://osu.ppy.sh/api/v2/events`, { + method: 'GET', + params: { sort: sort, cursor_string: cursor_string }, + }); + + + if (type != null) { + if (!Array.isArray(type)) + throw new Error('Event Type must be an Array of options'); + + const sorted = data.events.filter(r => type.includes(r.type)); + data.events = sorted; + }; + + + return data; +}; + + +export default name; \ No newline at end of file From 54bfc1f298079daf3934f61d2082e86027a9d7af Mon Sep 17 00:00:00 2001 From: ck Date: Sun, 24 Sep 2023 09:55:32 +0300 Subject: [PATCH 011/259] types 1/? --- api/v2/scores/details.ts | 3 +- api/v2/scores/user/list.ts | 60 +--------- api/v2/site/ranking/details.ts | 3 +- api/v2/user/details.ts | 3 +- api/v2/users/details.ts | 3 +- types/ranking_details.ts | 195 +++++++++++++++++++++++++++++++++ types/scores_details.ts | 132 ++++++++++++++++++++++ types/scores_user.ts | 146 ++++++++++++++++++++++++ types/user_details.ts | 175 +++++++++++++++++++++++++++++ types/users_details.ts | 84 ++++++++++++++ types/users_events.ts | 58 ++++++++++ 11 files changed, 801 insertions(+), 61 deletions(-) create mode 100644 types/ranking_details.ts create mode 100644 types/scores_details.ts create mode 100644 types/scores_user.ts create mode 100644 types/user_details.ts create mode 100644 types/users_details.ts create mode 100644 types/users_events.ts diff --git a/api/v2/scores/details.ts b/api/v2/scores/details.ts index 646d5c04..9ac5d33d 100644 --- a/api/v2/scores/details.ts +++ b/api/v2/scores/details.ts @@ -1,9 +1,10 @@ import { request } from "../../../utility/request"; import { gamemode_names } from "../../../types"; +import { ScoresDetails } from '../../../types/scores_details'; -const name = async (score_id: number, mode: gamemode_names) => { +const name = async (score_id: number, mode: gamemode_names): Promise => { if (mode == null) throw new Error('Gamemode name not specified'); diff --git a/api/v2/scores/user/list.ts b/api/v2/scores/user/list.ts index 2c7dac15..b010b290 100644 --- a/api/v2/scores/user/list.ts +++ b/api/v2/scores/user/list.ts @@ -1,71 +1,17 @@ import { request } from "../../../../utility/request"; import { gamemode_names } from "../../../../types"; import mods from '../../../../tools/mods'; +import { ScoresUser } from '../../../../types/scores_user'; -export const description = { - params: [ - { - type: 'number', - name: 'user', - optional: false, - description: 'id of the user', - }, - { - type: 'string', - name: 'type', - optional: false, - description: '\`\`\`recent\`\`\` or \`\`\`best\`\`\` or \`\`\`firsts\`\`\` or \`\`\`pinned\`\`\`', - }, - { - name: 'object', - params: [ - { - type: 'boolean', - name: 'include_fails', - options: false, - optional: true, - description: 'Only for \`\`\`recent\`\`\` scores, include scores of failed plays. Set to \`\`\`true\`\`\` to include them. Defaults to \`\`\`false\`\`\`', - }, - { - type: 'string', - name: 'mode', - optional: true, - description: '\`\`\`osu\`\`\` or \`\`\`fruits\`\`\` or \`\`\`mania\`\`\` or \`\`\`taiko\`\`\`', - }, - { - type: 'number', - name: 'mods', - options: false, - optional: true, - description: 'Use \`\`\`mods.enums\`\`\` instead of mods id or name', - }, - { - type: 'number', - name: 'limit', - optional: true, - description: 'Maximum number of results', - }, - { - type: 'string', - name: 'offset', - optional: true, - description: 'Result offset for pagination', - }, - ] - }, - ], -}; - - const name = async (user_id: number, type: 'recent' | 'best' | 'firsts' | 'pinned', object?: { include_fails?: boolean, mode?: gamemode_names, limit?: number, offset?: number, mods?: number -}) => { +}): Promise => { if (object.include_fails) // @ts-ignore object.include_fails = object.include_fails == true ? 1 : 0; @@ -77,7 +23,7 @@ const name = async (user_id: number, type: 'recent' | 'best' | 'firsts' | 'pinne // check if scores exists. Sometimes there can an error if (Array.isArray(data)) { - const transform = data.map((v, i) => ({ + const transform: ScoresUser[] = data.map((v, i) => ({ index: i + 1, mods_id: mods.id(v.mods.join('')) || 0, ...v diff --git a/api/v2/site/ranking/details.ts b/api/v2/site/ranking/details.ts index a7722734..5213d3f7 100644 --- a/api/v2/site/ranking/details.ts +++ b/api/v2/site/ranking/details.ts @@ -1,5 +1,6 @@ import { gamemode_names, ranking_types, country_codes } from "../../../../types"; import { request } from "../../../../utility/request"; +import { RankingDetails } from '../../../../types/ranking_details'; @@ -9,7 +10,7 @@ const name = async (mode: gamemode_names, type: ranking_types, object?: { filter?: 'all' | 'friends', spotlight_id?: number, variant?: '4k' | '7k', -}) => { +}): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/rankings/${mode}/${type}`, { method: 'GET', params: object, diff --git a/api/v2/user/details.ts b/api/v2/user/details.ts index 058daf02..35fb8865 100644 --- a/api/v2/user/details.ts +++ b/api/v2/user/details.ts @@ -1,9 +1,10 @@ import { request } from "../../../utility/request"; import { gamemode_names } from "../../../types"; +import { UserDetails } from '../../../types/user_details'; -const name = async (user: number, { mode, key }: { mode?: gamemode_names, key?: 'id' | 'username' } = {}) => { +const name = async (user: number, { mode, key }: { mode?: gamemode_names, key?: 'id' | 'username' } = {}): Promise => { let url = `https://osu.ppy.sh/api/v2/users/${user}`; if (mode != null) url += `/${mode}`; diff --git a/api/v2/users/details.ts b/api/v2/users/details.ts index 8c994e5e..d1ec808e 100644 --- a/api/v2/users/details.ts +++ b/api/v2/users/details.ts @@ -1,8 +1,9 @@ import { request } from "../../../utility/request"; +import { UsersDetails } from '../../../types/users_details'; -const name = async (ids: number[]) => { +const name = async (ids: number[]): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/users`, { method: 'GET', params: { diff --git a/types/ranking_details.ts b/types/ranking_details.ts new file mode 100644 index 00000000..2d080214 --- /dev/null +++ b/types/ranking_details.ts @@ -0,0 +1,195 @@ +export interface RankingDetails { + cursor?: Cursor; + ranking: Ranking[]; + total?: number; + beatmapsets?: Beatmapset[]; + spotlight?: Spotlight; +} + +export interface Beatmapset { + artist: string; + artist_unicode: string; + covers: Covers; + creator: string; + favourite_count: number; + hype: null; + id: number; + nsfw: boolean; + offset: number; + play_count: number; + preview_url: string; + source: string; + spotlight: boolean; + status: Status; + title: string; + title_unicode: string; + track_id: number | null; + user_id: number; + video: boolean; + bpm: number; + can_be_hyped: boolean; + deleted_at: null; + discussion_enabled: boolean; + discussion_locked: boolean; + is_scoreable: boolean; + last_updated: Date; + legacy_thread_url: string; + nominations_summary: NominationsSummary; + ranked: number; + ranked_date: Date; + storyboard: boolean; + submitted_date: Date; + tags: string; + availability: Availability; + beatmaps: Beatmap[]; +} + +export interface Availability { + download_disabled: boolean; + more_information: null; +} + +export interface Beatmap { + beatmapset_id: number; + difficulty_rating: number; + id: number; + mode: Mode; + status: Status; + total_length: number; + user_id: number; + version: string; + accuracy: number; + ar: number; + bpm: number; + convert: boolean; + count_circles: number; + count_sliders: number; + count_spinners: number; + cs: number; + deleted_at: null; + drain: number; + hit_length: number; + is_scoreable: boolean; + last_updated: Date; + mode_int: number; + passcount: number; + playcount: number; + ranked: number; + url: string; + checksum: string; +} + +export enum Mode { + Osu = "osu", +} + +export enum Status { + Ranked = "ranked", +} + +export interface Covers { + cover: string; + "cover@2x": string; + card: string; + "card@2x": string; + list: string; + "list@2x": string; + slimcover: string; + "slimcover@2x": string; +} + +export interface NominationsSummary { + current: number; + required: number; +} + +export interface Cursor { + page: number; +} + +export interface Ranking { + count_100?: number; + count_300?: number; + count_50?: number; + count_miss?: number; + level?: Level; + global_rank?: number | null; + global_rank_exp?: number | null; + pp?: number | null; + pp_exp?: number; + ranked_score: number; + hit_accuracy?: number; + play_count: number; + play_time?: number | null; + total_score?: number; + total_hits?: number; + maximum_combo?: number; + replays_watched_by_others?: number; + is_ranked?: boolean; + grade_counts?: GradeCounts; + user?: User; + code?: string; + active_users?: number; + performance?: number; + country?: Country; +} + +export interface Country { + code: string; + name: string; +} + +export interface GradeCounts { + ss: number; + ssh: number | null; + s: number; + sh: number | null; + a: number; +} + +export interface Level { + current: number; + progress: number; +} + +export interface User { + avatar_url: string; + country_code: string; + default_group: DefaultGroup; + id: number; + is_active: boolean; + is_bot: boolean; + is_deleted: boolean; + is_online: boolean; + is_supporter: boolean; + last_visit: Date | null; + pm_friends_only: boolean; + profile_colour: null | string; + username: string; + country: Country; + cover: Cover; +} + +export interface Cover { + custom_url: null | string; + url: string; + id: null | string; +} + +export enum DefaultGroup { + Alumni = "alumni", + Bng = "bng", + Default = "default", + Loved = "loved", + Nat = "nat", +} + +export interface Spotlight { + end_date: Date; + id: number; + mode_specific: boolean; + name: string; + start_date: Date; + type: string; + participant_count: number; +} diff --git a/types/scores_details.ts b/types/scores_details.ts new file mode 100644 index 00000000..fa67ea2f --- /dev/null +++ b/types/scores_details.ts @@ -0,0 +1,132 @@ +export interface ScoresDetails { + accuracy: number; + best_id: number; + created_at: Date; + id: number; + max_combo: number; + mode: string; + mode_int: number; + mods: string[]; + passed: boolean; + perfect: boolean; + pp: number; + rank: string; + replay: boolean; + score: number; + statistics: Statistics; + type: string; + user_id: number; + current_user_attributes: CurrentUserAttributes; + beatmap: Beatmap; + beatmapset: Beatmapset; + rank_global: number; + user: User; +} + +export interface Beatmap { + beatmapset_id: number; + difficulty_rating: number; + id: number; + mode: string; + status: string; + total_length: number; + user_id: number; + version: string; + accuracy: number; + ar: number; + bpm: number; + convert: boolean; + count_circles: number; + count_sliders: number; + count_spinners: number; + cs: number; + deleted_at: null; + drain: number; + hit_length: number; + is_scoreable: boolean; + last_updated: Date; + mode_int: number; + passcount: number; + playcount: number; + ranked: number; + url: string; + checksum: string; + max_combo: number; + user: User; +} + +export interface User { + avatar_url: string; + country_code: string; + default_group: string; + id: number; + is_active: boolean; + is_bot: boolean; + is_deleted: boolean; + is_online: boolean; + is_supporter: boolean; + last_visit: Date; + pm_friends_only: boolean; + profile_colour: null; + username: string; + country?: Country; + cover?: Cover; + groups?: any[]; +} + +export interface Country { + code: string; + name: string; +} + +export interface Cover { + custom_url: string; + url: string; + id: string; +} + +export interface Beatmapset { + artist: string; + artist_unicode: string; + covers: Covers; + creator: string; + favourite_count: number; + hype: null; + id: number; + nsfw: boolean; + offset: number; + play_count: number; + preview_url: string; + source: string; + spotlight: boolean; + status: string; + title: string; + title_unicode: string; + track_id: number; + user_id: number; + video: boolean; +} + +export interface Covers { + cover: string; + "cover@2x": string; + card: string; + "card@2x": string; + list: string; + "list@2x": string; + slimcover: string; + "slimcover@2x": string; +} + +export interface CurrentUserAttributes { + pin: null; +} + +export interface Statistics { + count_100: number; + count_300: number; + count_50: number; + count_geki: number; + count_katu: number; + count_miss: number; +} diff --git a/types/scores_user.ts b/types/scores_user.ts new file mode 100644 index 00000000..4aec85bc --- /dev/null +++ b/types/scores_user.ts @@ -0,0 +1,146 @@ +export interface ScoresUser { + index: number; + mods_id: number; + accuracy: number; + best_id: number | null; + created_at: Date; + id: number; + max_combo: number; + mode: Mode; + mode_int: number; + mods: string[]; + passed: boolean; + perfect: boolean; + pp: number | null; + rank: string; + replay: boolean; + score: number; + statistics: Statistics; + type: Type; + user_id: number; + current_user_attributes: CurrentUserAttributes; + beatmap: Beatmap; + beatmapset: Beatmapset; + user: User; + weight?: Weight; +} + +export interface Beatmap { + beatmapset_id: number; + difficulty_rating: number; + id: number; + mode: Mode; + status: Status; + total_length: number; + user_id: number; + version: string; + accuracy: number; + ar: number; + bpm: number; + convert: boolean; + count_circles: number; + count_sliders: number; + count_spinners: number; + cs: number; + deleted_at: null; + drain: number; + hit_length: number; + is_scoreable: boolean; + last_updated: Date; + mode_int: number; + passcount: number; + playcount: number; + ranked: number; + url: string; + checksum: string; +} + +export enum Mode { + Osu = "osu", +} + +export enum Status { + Approved = "approved", + Loved = "loved", + Ranked = "ranked", +} + +export interface Beatmapset { + artist: string; + artist_unicode: string; + covers: Covers; + creator: string; + favourite_count: number; + hype: null; + id: number; + nsfw: boolean; + offset: number; + play_count: number; + preview_url: string; + source: string; + spotlight: boolean; + status: Status; + title: string; + title_unicode: string; + track_id: number | null; + user_id: number; + video: boolean; +} + +export interface Covers { + cover: string; + "cover@2x": string; + card: string; + "card@2x": string; + list: string; + "list@2x": string; + slimcover: string; + "slimcover@2x": string; +} + +export interface CurrentUserAttributes { + pin: null; +} + +export interface Statistics { + count_100: number; + count_300: number; + count_50: number; + count_geki: number; + count_katu: number; + count_miss: number; +} + +export enum Type { + ScoreBestOsu = "score_best_osu", + ScoreOsu = "score_osu", +} + +export interface User { + avatar_url: string; + country_code: CountryCode; + default_group: DefaultGroup; + id: number; + is_active: boolean; + is_bot: boolean; + is_deleted: boolean; + is_online: boolean; + is_supporter: boolean; + last_visit: Date; + pm_friends_only: boolean; + profile_colour: null; + username: string; +} + +export enum CountryCode { + ID = "ID", +} + +export enum DefaultGroup { + Default = "default", +} + +export interface Weight { + percentage: number; + pp: number; +} diff --git a/types/user_details.ts b/types/user_details.ts new file mode 100644 index 00000000..164f0f71 --- /dev/null +++ b/types/user_details.ts @@ -0,0 +1,175 @@ +export interface UserDetails { + avatar_url: string; + country_code: string; + default_group: string; + id: number; + is_active: boolean; + is_bot: boolean; + is_deleted: boolean; + is_online: boolean; + is_supporter: boolean; + last_visit: Date | null; + pm_friends_only: boolean; + profile_colour: null | string; + username: string; + cover_url: string; + discord: null | string; + has_supported: boolean; + interests: null | string; + join_date: Date; + location: null | string; + max_blocks: number; + max_friends: number; + occupation: null | string; + playmode: string; + playstyle: string[] | null; + post_count: number; + profile_order: string[]; + title: null; + title_url: null; + twitter: null | string; + website: null | string; + country: Country; + cover: Cover; + kudosu: Kudosu; + account_history: any[]; + active_tournament_banner: ActiveTournamentBanner | null; + badges: Badge[]; + beatmap_playcounts_count: number; + comments_count: number; + favourite_beatmapset_count: number; + follower_count: number; + graveyard_beatmapset_count: number; + groups: Group[]; + guest_beatmapset_count: number; + loved_beatmapset_count: number; + mapping_follower_count: number; + monthly_playcounts: Count[]; + nominated_beatmapset_count: number; + page: Page; + pending_beatmapset_count: number; + previous_usernames: string[]; + rank_highest: RankHighest; + ranked_beatmapset_count: number; + replays_watched_counts: Count[]; + scores_best_count: number; + scores_first_count: number; + scores_pinned_count: number; + scores_recent_count: number; + statistics: Statistics; + support_level: number; + user_achievements: UserAchievement[]; + rank_history: RankHistory; + rankHistory: RankHistory; + ranked_and_approved_beatmapset_count: number; + unranked_beatmapset_count: number; +} + +export interface ActiveTournamentBanner { + id: number; + tournament_id: number; + image: string; + "image@2x": string; +} + +export interface Badge { + awarded_at: Date; + description: string; + "image@2x_url": string; + image_url: string; + url: string; +} + +export interface Country { + code: string; + name: string; +} + +export interface Cover { + custom_url: string; + url: string; + id: null | string; +} + +export interface Group { + colour: string; + has_listing: boolean; + has_playmodes: boolean; + id: number; + identifier: string; + is_probationary: boolean; + name: string; + short_name: string; + playmodes: null; +} + +export interface Kudosu { + available: number; + total: number; +} + +export interface Count { + start_date: Date; + count: number; +} + +export interface Page { + html: string; + raw: string; +} + +export interface RankHistory { + mode: string; + data: number[]; +} + +export interface RankHighest { + rank: number; + updated_at: Date; +} + +export interface Statistics { + count_100: number; + count_300: number; + count_50: number; + count_miss: number; + level: Level; + global_rank: number | null; + global_rank_exp: number; + pp: number; + pp_exp: number; + ranked_score: number; + hit_accuracy: number; + play_count: number; + play_time: number; + total_score: number; + total_hits: number; + maximum_combo: number; + replays_watched_by_others: number; + is_ranked: boolean; + grade_counts: GradeCounts; + country_rank: number | null; + rank: Rank; +} + +export interface GradeCounts { + ss: number; + ssh: number; + s: number; + sh: number; + a: number; +} + +export interface Level { + current: number; + progress: number; +} + +export interface Rank { + country: number | null; +} + +export interface UserAchievement { + achieved_at: Date; + achievement_id: number; +} diff --git a/types/users_details.ts b/types/users_details.ts new file mode 100644 index 00000000..658edae0 --- /dev/null +++ b/types/users_details.ts @@ -0,0 +1,84 @@ +export interface UsersDetails { + avatar_url: string; + country_code: string; + default_group: string; + id: number; + is_active: boolean; + is_bot: boolean; + is_deleted: boolean; + is_online: boolean; + is_supporter: boolean; + last_visit: Date | null; + pm_friends_only: boolean; + profile_colour: null | string; + username: string; + country: Country; + cover: Cover; + groups: Group[]; + statistics_rulesets: StatisticsRulesets; +} + +export interface Country { + code: string; + name: string; +} + +export interface Cover { + custom_url: string; + url: string; + id: null | string; +} + +export interface Group { + colour: string; + has_listing: boolean; + has_playmodes: boolean; + id: number; + identifier: string; + is_probationary: boolean; + name: string; + short_name: string; + playmodes: null; +} + +export interface StatisticsRulesets { + osu: Fruits; + taiko: Fruits; + fruits: Fruits; + mania: Fruits; +} + +export interface Fruits { + count_100: number; + count_300: number; + count_50: number; + count_miss: number; + level: Level; + global_rank: number | null; + global_rank_exp: number | null; + pp: number; + pp_exp: number; + ranked_score: number; + hit_accuracy: number; + play_count: number; + play_time: number; + total_score: number; + total_hits: number; + maximum_combo: number; + replays_watched_by_others: number; + is_ranked: boolean; + grade_counts: GradeCounts; +} + +export interface GradeCounts { + ss: number; + ssh: number; + s: number; + sh: number; + a: number; +} + +export interface Level { + current: number; + progress: number; +} diff --git a/types/users_events.ts b/types/users_events.ts new file mode 100644 index 00000000..eff8d7f8 --- /dev/null +++ b/types/users_events.ts @@ -0,0 +1,58 @@ +export interface UsersEvents { + events: Event[]; + cursor: Cursor; + cursor_string: string; +} + +export interface Cursor { + event_id: number; +} + +export interface Event { + created_at: Date; + createdAt: Date; + id: number; + type: Type; + scoreRank?: string; + rank?: number; + mode?: Mode; + beatmap?: Beatmap; + user: User; + achievement?: Achievement; + beatmapset?: Beatmap; +} + +export interface Achievement { + icon_url: string; + id: number; + name: string; + grouping: string; + ordering: number; + slug: string; + description: string; + mode: Mode | null; + instructions: null | string; +} + +export enum Mode { + Fruits = "fruits", + Mania = "mania", + Osu = "osu", + Taiko = "taiko", +} + +export interface Beatmap { + title: string; + url: string; +} + +export enum Type { + Achievement = "achievement", + BeatmapsetUpdate = "beatmapsetUpdate", + Rank = "rank", +} + +export interface User { + username: string; + url: string; +} From fa97361f1fe2d1e7d1d05ac379f0a667da81dd7f Mon Sep 17 00:00:00 2001 From: ck Date: Sun, 24 Sep 2023 09:56:55 +0300 Subject: [PATCH 012/259] beta v.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 14ab2bfe..ec33ec24 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "2.8.52", + "version": "3.0.0-beta.0", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "index.js", "types": "index.d.ts", From 8db0fd69d38a596549769c7cc7d643bb9a92c5f6 Mon Sep 17 00:00:00 2001 From: ck Date: Mon, 25 Sep 2023 10:23:13 +0300 Subject: [PATCH 013/259] oops --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index ec33ec24..122c630e 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.0", + "version": "3.0.0-beta.1", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", - "main": "index.js", - "types": "index.d.ts", + "main": "dist/index.js", + "types": "dist/index.d.ts", "files": [ "dist/*" ], From 46e00baf471fe7a9ca1ace6e9d87ab8031b25b27 Mon Sep 17 00:00:00 2001 From: ck Date: Tue, 26 Sep 2023 02:38:12 +0300 Subject: [PATCH 014/259] bring more tools --- index.ts | 11 +++++++++++ package.json | 2 +- tools/accuracy.ts | 33 +++++++++++++++++++++++++++++++++ tools/download_file.ts | 30 ++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 tools/accuracy.ts create mode 100644 tools/download_file.ts diff --git a/index.ts b/index.ts index aa492650..c9410aff 100644 --- a/index.ts +++ b/index.ts @@ -1,3 +1,14 @@ +import download_file from './tools/download_file'; +import accuracy from './tools/accuracy'; + + +export const tools = { + accuracy: accuracy, + download: { + difficulty: download_file + }, +}; + export * as country from './tools/country'; export * as mods from './tools/mods'; diff --git a/package.json b/package.json index 122c630e..a70803ad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.1", + "version": "3.0.0-beta.2", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/tools/accuracy.ts b/tools/accuracy.ts new file mode 100644 index 00000000..e3239826 --- /dev/null +++ b/tools/accuracy.ts @@ -0,0 +1,33 @@ +export interface types { + (hits: { + 300: string, + 100: string, + 50: string, + 0: string, + geki: string, + katu: string + }, mode: 'osu' | 'fruits' | 'taiko' | 'mania'): number; +}; + + +const name: types = (hits, mode = 'osu') => { + const h300 = parseInt(hits[300]); + const h100 = parseInt(hits[100]); + const h50 = parseInt(hits[50]); + const h0 = parseInt(hits[0]); + const geki = parseInt(hits.geki); + const katu = parseInt(hits.katu); + + let acc = 0.0; + + switch (mode) { + case 'osu': acc = (100.0 * (6 * h300 + 2 * h100 + h50)) / (6 * (h50 + h100 + h300 + h0)); break; + case 'taiko': acc = (100.0 * (2 * h300 + h100)) / (2 * (h300 + h100 + h0)); break; + case 'fruits': acc = (100.0 * (h300 + h100 + h50)) / (h300 + h100 + h50 + katu + h0); break; + case 'mania': acc = (100.0 * (6 * geki + 6 * h300 + 4 * katu + 2 * h100 + h50)) / (6 * (h50 + h100 + h300 + h0 + geki + katu)); break; + }; + + return parseFloat(acc.toFixed(2)); +}; + +export default name; \ No newline at end of file diff --git a/tools/download_file.ts b/tools/download_file.ts new file mode 100644 index 00000000..ecfb229e --- /dev/null +++ b/tools/download_file.ts @@ -0,0 +1,30 @@ +import { request } from "../utility/request"; +import FS from "fs/promises"; +import path from "path"; +import fs from "fs"; + + +export interface types { + (difficulty_id: number, file_path: string, overwrite?: boolean): Promise; +}; + + +const name: types = async (difficulty_id, file_path, overwrite) => { + const { dir } = path.parse(file_path); + if (!fs.existsSync(dir)) + FS.mkdir(file_path, { recursive: true }); + + + if (fs.existsSync(file_path) && overwrite != true) + return file_path; + + + const data = await request(`https://osu.ppy.sh/osu/${difficulty_id}`, { method: "GET" }); + if (!data.includes('osu file format v')) return null; + + + FS.writeFile(file_path, data, 'utf-8'); + return file_path; +}; + +export default name; \ No newline at end of file From 97c6a349235f7a619b2fd3b83204955edc99b628 Mon Sep 17 00:00:00 2001 From: ck Date: Tue, 26 Sep 2023 02:49:57 +0300 Subject: [PATCH 015/259] switch to native questring encode & close debug --- api/v2/users/details.ts | 2 +- utility/request.ts | 39 +++------------------------------------ 2 files changed, 4 insertions(+), 37 deletions(-) diff --git a/api/v2/users/details.ts b/api/v2/users/details.ts index d1ec808e..824c695f 100644 --- a/api/v2/users/details.ts +++ b/api/v2/users/details.ts @@ -7,7 +7,7 @@ const name = async (ids: number[]): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/users`, { method: 'GET', params: { - ids + 'ids[]': ids }, }); diff --git a/utility/request.ts b/utility/request.ts index 1a8a9a29..3342359e 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -1,5 +1,6 @@ // PACKAGES import https from 'https'; +import querystring from 'node:querystring'; // import fs from "fs"; @@ -30,40 +31,6 @@ const TIMEOUT_MS = 60000; let total_retries = 0; -const generateQueryString = (obj: any, trail: string = ''): string => { - const params: string[] = []; - console.time('generateQueryString'); - - - const processValue = (key: string, value: any) => { - if (Array.isArray(value)) { - value.forEach((item) => { - params.push(`${key}[]=${encodeURIComponent(item)}`); - }); - } else if (typeof value === 'object' && value !== null) { - const newTrail = trail ? `${trail}.${key}` : key; - params.push(generateQueryString(value, newTrail)); - } else if (typeof value === 'number' && value > 0) { - params.push(`${key}=${value}`); - } else if (typeof value === 'string') { - params.push(`${key}=${encodeURIComponent(value)}`); - } - }; - - for (const key in obj) { - if (obj.hasOwnProperty(key)) { - const value = obj[key]; - if (value !== undefined) { - processValue(key, value); - } - } - } - - console.timeEnd('generateQueryString'); - - return params.join('&'); -}; - export const request = (url: string, { method, headers, data, params = {} }: RequestParams = {}): Promise => new Promise((resolve, reject) => { // check required args @@ -88,10 +55,10 @@ export const request = (url: string, { method, headers, data, params = {} }: Req }; - const generate_query = generateQueryString(params); + const generate_query = querystring.encode(params); const build_url = url + (generate_query ? `?${generate_query}` : ''); - console.log({ url: build_url, method, headers, data }); + // console.log({ url: build_url, method, headers, data }); const req = https.request(build_url, { method, headers }, (response) => { const chunks: any[] = []; From d035960ba2e0a435f169d22e19e117617ddfbb5a Mon Sep 17 00:00:00 2001 From: ck Date: Tue, 26 Sep 2023 02:50:04 +0300 Subject: [PATCH 016/259] fixes --- api/v2/scores/details.ts | 2 +- package.json | 2 +- tsconfig.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api/v2/scores/details.ts b/api/v2/scores/details.ts index 9ac5d33d..339bff25 100644 --- a/api/v2/scores/details.ts +++ b/api/v2/scores/details.ts @@ -4,7 +4,7 @@ import { ScoresDetails } from '../../../types/scores_details'; -const name = async (score_id: number, mode: gamemode_names): Promise => { +const name = async (score_id: number, mode: gamemode_names): Promise => { if (mode == null) throw new Error('Gamemode name not specified'); diff --git a/package.json b/package.json index a70803ad..be0f408c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.2", + "version": "3.0.0-beta.3", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/tsconfig.json b/tsconfig.json index f94ddec7..5fd9360a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,7 +14,7 @@ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ "declaration": true, /* Generates corresponding '.d.ts' file. */ // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ - "sourceMap": true, /* Generates corresponding '.map' file. */ + "sourceMap": false, /* Generates corresponding '.map' file. */ // "outFile": "./", /* Concatenate and emit output to single file. */ "outDir": "dist", /* Redirect output structure to the directory. */ "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ From 944b6a4dbd841d132109d4aea7b24813ab72e401 Mon Sep 17 00:00:00 2001 From: ck Date: Wed, 27 Sep 2023 20:44:55 +0300 Subject: [PATCH 017/259] beta: hotfix auth relogin --- package.json | 2 +- utility/auth.ts | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index be0f408c..349bb9d2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.3", + "version": "3.0.0-beta.4", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/utility/auth.ts b/utility/auth.ts index 66ba705f..b1315def 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -31,7 +31,7 @@ const credentials: { clientId: number, clientSecret: string, redirect_uri: string, - scope: auth_scopes, + scopes: auth_scopes, } = { type: 0, username: '', @@ -39,7 +39,7 @@ const credentials: { clientId: 0, clientSecret: '', redirect_uri: '', - scope: ['public'], + scopes: ['public'], }; @@ -52,7 +52,9 @@ export const set_v2 = (v: string) => cache_v2 = v; const isInitial = () => cache_v2 != ''; -const store_credentials = (type: number, obj: any) => { +const store_credentials = (type: number, obj: { + username?: string, password?: string, clientId?: number, clientSecret?: string, scopes?: auth_scopes, redirect_uri?: string +}) => { if (type == 1) { credentials.type = 1; credentials.username = obj.username; @@ -63,7 +65,7 @@ const store_credentials = (type: number, obj: any) => { credentials.type = 2; credentials.clientId = obj.clientId; credentials.clientSecret = obj.clientSecret; - credentials.scope = obj.scope; + credentials.scopes = obj.scopes; }; if (type == 3) { @@ -71,14 +73,14 @@ const store_credentials = (type: number, obj: any) => { credentials.clientId = obj.clientId; credentials.clientSecret = obj.clientSecret; credentials.redirect_uri = obj.redirect_uri; - credentials.scope = obj.scope; + credentials.scopes = obj.scopes; }; }; export const update_cache_token = async () => { // if (credentials.type == 1) await lazer_user(credentials.username, credentials.password); - if (credentials.type == 2) await client_login(credentials.clientId, credentials.clientSecret, credentials.scope); + if (credentials.type == 2) await client_login(credentials.clientId, credentials.clientSecret, credentials.scopes); // if (credentials.type == 3) await cli(credentials.clientId, credentials.clientSecret, credentials.redirect_uri, credentials.scope); return true; From 134b26d45bb2d32ff4eb27f53e80645e3719f282 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 30 Oct 2023 00:32:26 +0300 Subject: [PATCH 018/259] more endpoints --- api/v2/index.ts | 9 +++++++-- api/v2/scores/beatmaps.ts | 17 +++++++++++++++++ api/v2/scores/user/beatmap.ts | 25 +++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 api/v2/scores/beatmaps.ts create mode 100644 api/v2/scores/user/beatmap.ts diff --git a/api/v2/index.ts b/api/v2/index.ts index 3b9b5562..b6a28a6d 100644 --- a/api/v2/index.ts +++ b/api/v2/index.ts @@ -19,7 +19,9 @@ export const user = { import scores_details from "./scores/details"; +import scores_beatmap from "./scores/beatmaps"; import scores_user_list from "./scores/user/list"; +import scores_user_beatmap from "./scores/user/beatmap"; export const scores = { details: scores_details, @@ -29,7 +31,9 @@ export const scores = { */ category: scores_user_list, list: scores_user_list, - } + beatmap: scores_user_beatmap, + }, + beatmap: scores_beatmap, }; @@ -40,4 +44,5 @@ export const site = { ranking: { details: site_ranking_details, }, -}; \ No newline at end of file +}; + diff --git a/api/v2/scores/beatmaps.ts b/api/v2/scores/beatmaps.ts new file mode 100644 index 00000000..364b44fb --- /dev/null +++ b/api/v2/scores/beatmaps.ts @@ -0,0 +1,17 @@ +import { request } from "../../../utility/request"; +import { gamemode_names } from '../../../types'; + + + +const name = async (beatmap_id: number, obj: { mode: gamemode_names, mods: string[], type: 'global' | 'country' | 'friend' }) => { + const data = await request(`https://osu.ppy.sh/api/v2/beatmaps/${beatmap_id}/scores`, { + method: 'GET', + params: obj, + }); + + if (!data.scores) return data; + return data.scores.map((v: any, i: number) => ({ position: i + 1, ...v })); +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/scores/user/beatmap.ts b/api/v2/scores/user/beatmap.ts new file mode 100644 index 00000000..32c2187a --- /dev/null +++ b/api/v2/scores/user/beatmap.ts @@ -0,0 +1,25 @@ +import { gamemode_names } from "../../../../types"; +import { request } from "../../../../utility/request"; + + + +const name = async (beatmap_id: number, user_id: number, obj: { mode?: gamemode_names, mods?: string[], best_only?: boolean } = {}) => { + let url = `https://osu.ppy.sh/api/v2/beatmaps/${beatmap_id}/scores/users/${user_id}`; + if (!obj.best_only) url += '/all'; + + const data = await request(url, { + method: 'GET', + params: obj, + }); + + if (obj.best_only == true) { + data.score.position = data.position; + return [data.score]; + }; + + if (data.scores) return data.scores + return data; +}; + + +export default name; \ No newline at end of file From 3f92acde6d5bfba4f7d7c838246506f09f1ee9e0 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 30 Oct 2023 00:40:04 +0300 Subject: [PATCH 019/259] add forum details temporary --- api/v2/forums/topic/details.ts | 15 +++++++++++ api/v2/index.ts | 9 +++++++ types/forums_topic_details.ts | 49 ++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 api/v2/forums/topic/details.ts create mode 100644 types/forums_topic_details.ts diff --git a/api/v2/forums/topic/details.ts b/api/v2/forums/topic/details.ts new file mode 100644 index 00000000..dc86db2e --- /dev/null +++ b/api/v2/forums/topic/details.ts @@ -0,0 +1,15 @@ +import { request } from "../../../../utility/request"; +import { ForumPostDetails } from '../../../../types/forums_topic_details'; + + +// FIXME: add query params +const name = async (topic_id: number): Promise => { + const data = await request(`https://osu.ppy.sh/api/v2/forums/topics/${topic_id}`, { + method: 'GET', + }); + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/index.ts b/api/v2/index.ts index b6a28a6d..0d9ead28 100644 --- a/api/v2/index.ts +++ b/api/v2/index.ts @@ -46,3 +46,12 @@ export const site = { }, }; + + +import forums_topic_details from './forums/topic/details'; + +export const forums = { + topic: { + details: forums_topic_details + } +} \ No newline at end of file diff --git a/types/forums_topic_details.ts b/types/forums_topic_details.ts new file mode 100644 index 00000000..d837356f --- /dev/null +++ b/types/forums_topic_details.ts @@ -0,0 +1,49 @@ +export interface ForumPostDetails { + posts: Post[] + search: Search + topic: Topic + cursor: Cursor + cursor_string: string +} + +export interface Post { + created_at: string + deleted_at: any + edited_at?: string + edited_by_id?: number + forum_id: number + id: number + topic_id: number + user_id: number + body: Body +} + +export interface Body { + html: string + raw: string +} + +export interface Search { + limit: number + sort: string +} + +export interface Topic { + created_at: string + deleted_at: any + first_post_id: number + forum_id: number + id: number + is_locked: boolean + last_post_id: number + post_count: number + title: string + type: string + updated_at: string + user_id: number + poll: any +} + +export interface Cursor { + id: number +} From 33bc6a141c395ce4cf90bb6b4acfbbad03295958 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 30 Oct 2023 00:40:15 +0300 Subject: [PATCH 020/259] bump ver --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 349bb9d2..7be05b9b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.4", + "version": "3.0.0-beta.5", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", From e360b35316fef5ed9ab5a07c83194cbacb6656fa Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Tue, 14 Nov 2023 14:14:35 +0300 Subject: [PATCH 021/259] forums topics --- api/v2/forums/topic/details.ts | 10 +++++++++- package.json | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/api/v2/forums/topic/details.ts b/api/v2/forums/topic/details.ts index dc86db2e..793ad04b 100644 --- a/api/v2/forums/topic/details.ts +++ b/api/v2/forums/topic/details.ts @@ -3,9 +3,17 @@ import { ForumPostDetails } from '../../../../types/forums_topic_details'; // FIXME: add query params -const name = async (topic_id: number): Promise => { +const name = async (topic_id: number, obj: { + sort: 'id_asc' | 'id_desc', + limit: number, + start: string, + end: string, + cursor_string: string, +}): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/forums/topics/${topic_id}`, { method: 'GET', + params: obj, + }); return data; diff --git a/package.json b/package.json index 7be05b9b..71d69f5d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.5", + "version": "3.0.0-beta.6", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", From f71812406d42d093006a9c25805a63cb77827242 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Tue, 14 Nov 2023 14:15:09 +0300 Subject: [PATCH 022/259] upgrade difficulty download --- package.json | 2 +- tools/download_file.ts | 36 +++++++++++++++++++++++------------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 71d69f5d..75c03dba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.6", + "version": "3.0.0-beta.7", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/tools/download_file.ts b/tools/download_file.ts index ecfb229e..e88fcead 100644 --- a/tools/download_file.ts +++ b/tools/download_file.ts @@ -1,30 +1,40 @@ import { request } from "../utility/request"; -import FS from "fs/promises"; import path from "path"; import fs from "fs"; export interface types { - (difficulty_id: number, file_path: string, overwrite?: boolean): Promise; + (difficulty_id: number, file_path: string, overwrite?: boolean): Promise<{ type: 'created' | 'exists' | 'rate-limit', path?: string }>; }; -const name: types = async (difficulty_id, file_path, overwrite) => { +const name: types = (difficulty_id, file_path, overwrite) => new Promise(async (resolve, reject) => { const { dir } = path.parse(file_path); - if (!fs.existsSync(dir)) - FS.mkdir(file_path, { recursive: true }); + if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); - if (fs.existsSync(file_path) && overwrite != true) - return file_path; + if (fs.existsSync(file_path) && overwrite != true) { + resolve({ + type: 'exists', + path: file_path, + }); + return; + }; const data = await request(`https://osu.ppy.sh/osu/${difficulty_id}`, { method: "GET" }); - if (!data.includes('osu file format v')) return null; - - - FS.writeFile(file_path, data, 'utf-8'); - return file_path; -}; + fs.writeFile(file_path, data, 'utf8', (err) => { + if (err) { + reject(err); + return; + }; + + + resolve({ + type: data.includes('429 Too Many Requests') ? 'rate-limit' : 'created', + path: file_path, + }); + }); +}); export default name; \ No newline at end of file From 90b7d08a3b70b9849ef8d5159a3fc3ba099bf67c Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 11 Dec 2023 07:49:44 +0300 Subject: [PATCH 023/259] reworked auth methods --- types/index.ts | 49 +++++++- utility/auth.ts | 273 ++++++++++++++++++++++++++++++--------------- utility/request.ts | 8 +- 3 files changed, 236 insertions(+), 94 deletions(-) diff --git a/types/index.ts b/types/index.ts index cec43d7f..023dca55 100644 --- a/types/index.ts +++ b/types/index.ts @@ -3,4 +3,51 @@ export type gamemode_names = 'osu' | 'fruits' | 'mania' | 'taiko'; export type ranking_types = 'charts' | 'country' | 'performance' | 'score'; export type country_names = "United States" | "Russian Federation" | "Germany" | "Poland" | "France" | "Japan" | "Canada" | "Brazil" | "United Kingdom" | "Taiwan" | "South Korea" | "China" | "Australia" | "Indonesia" | "Ukraine" | "Philippines" | "Chile" | "Finland" | "Argentina" | "Netherlands" | "Sweden" | "Singapore" | "Mexico" | "Malaysia" | "Spain" | "Italy" | "Hong Kong" | "Thailand" | "Vietnam" | "Norway" | "Czech Republic" | "Turkey" | "Belarus" | "Austria" | "Belgium" | "Portugal" | "Romania" | "Hungary" | "Denmark" | "Lithuania" | "Kazakhstan" | "New Zealand" | "Peru" | "Switzerland" | "Colombia" | "Israel" | "Estonia" | "Bulgaria" | "Slovakia" | "Greece" | "Latvia" | "Venezuela" | "Serbia" | "Ireland" | "Croatia" | "Saudi Arabia" | "Uruguay" | "South Africa" | "United Arab Emirates" | "Slovenia" | "India" | "Ecuador" | "Morocco" | "Costa Rica" | "Moldova" | "Dominican Republic" | "Brunei" | "Egypt" | "Reunion" | "Macau" | "Tunisia" | "Panama" | "Algeria" | "Mongolia" | "Paraguay" | "Kuwait" | "Puerto Rico" | "Georgia" | "Bolivia" | "El Salvador" | "Qatar" | "Guatemala" | "Luxembourg" | "Uzbekistan" | "Kyrgyzstan" | "North Macedonia" | "Cambodia" | "Bosnia and Herzegovina" | "Iceland" | "Jordan" | "Pakistan" | "Trinidad and Tobago" | "Cyprus" | "Honduras" | "Nicaragua" | "Bahrain" | "Maldives" | "Bangladesh" | "French Polynesia" | "Lebanon" | "Nepal" | "Iraq" | "Guam" | "Azerbaijan" | "Albania" | "Malta" | "Myanmar" | "New Caledonia" | "Oman" | "Iran, Islamic Republic of" | "Armenia" | "Guadeloupe" | "Martinique" | "Jamaica" | "Lao People 's Democratic Republic" | "Sri Lanka" | "Palestinian Territory Occupied" | "Mauritius" | "Syrian Arab Republic" | "Montenegro" | "Faroe Islands" | "Jersey" | "French Guiana" | "Northern Mariana Islands" | "Isle of Man" | "Suriname" | "Belize" | "Barbados" | "Aruba" | "Libya" | "Aland Islands" | "Guernsey" | "Madagascar" | "Sudan" | "Liechtenstein" | "Bahamas" | "Kenya" | "Greenland" | "Bermuda" | "Europe" | "Cote D ' Ivoire" | "Guyana" | "Gibraltar" | "Virgin Islands, U.S." | "Andorra" | "Saint Lucia" | "Tajikistan" | "Antigua and Barbuda" | "Senegal" | "Saint Pierre and Miquelon" | "Cook Islands" | "Antarctica" | "Central African Republic" | "Liberia" | "Eritrea"; -export type country_codes = "US" | "RU" | "DE" | "PL" | "FR" | "JP" | "CA" | "BR" | "GB" | "TW" | "KR" | "CN" | "AU" | "ID" | "UA" | "PH" | "CL" | "FI" | "AR" | "NL" | "SE" | "SG" | "MX" | "MY" | "ES" | "IT" | "HK" | "TH" | "VN" | "NO" | "CZ" | "TR" | "BY" | "AT" | "BE" | "PT" | "RO" | "HU" | "DK" | "LT" | "KZ" | "NZ" | "PE" | "CH" | "CO" | "IL" | "EE" | "BG" | "SK" | "GR" | "LV" | "VE" | "RS" | "IE" | "HR" | "SA" | "UY" | "ZA" | "AE" | "SI" | "IN" | "EC" | "MA" | "CR" | "MD" | "DO" | "BN" | "EG" | "RE" | "MO" | "TN" | "PA" | "DZ" | "MN" | "PY" | "KW" | "PR" | "GE" | "BO" | "SV" | "QA" | "GT" | "LU" | "UZ" | "KG" | "MK" | "KH" | "BA" | "IS" | "JO" | "PK" | "TT" | "CY" | "HN" | "NI" | "BH" | "MV" | "BD" | "PF" | "LB" | "NP" | "IQ" | "GU" | "AZ" | "AL" | "MT" | "MM" | "NC" | "OM" | "IR" | "AM" | "GP" | "MQ" | "JM" | "LA" | "LK" | "PS" | "MU" | "SY" | "ME" | "FO" | "JE" | "GF" | "MP" | "IM" | "SR" | "BZ" | "BB" | "AW" | "LY" | "AX" | "GG" | "MG" | "SD" | "LI" | "BS" | "KE" | "GL" | "BM" | "EU" | "CI" | "GY" | "GI" | "VI" | "AD" | "LC" | "TJ" | "AG" | "SN" | "PM" | "CK" | "AQ" | "CF" | "LR" | "ER"; \ No newline at end of file +export type country_codes = "US" | "RU" | "DE" | "PL" | "FR" | "JP" | "CA" | "BR" | "GB" | "TW" | "KR" | "CN" | "AU" | "ID" | "UA" | "PH" | "CL" | "FI" | "AR" | "NL" | "SE" | "SG" | "MX" | "MY" | "ES" | "IT" | "HK" | "TH" | "VN" | "NO" | "CZ" | "TR" | "BY" | "AT" | "BE" | "PT" | "RO" | "HU" | "DK" | "LT" | "KZ" | "NZ" | "PE" | "CH" | "CO" | "IL" | "EE" | "BG" | "SK" | "GR" | "LV" | "VE" | "RS" | "IE" | "HR" | "SA" | "UY" | "ZA" | "AE" | "SI" | "IN" | "EC" | "MA" | "CR" | "MD" | "DO" | "BN" | "EG" | "RE" | "MO" | "TN" | "PA" | "DZ" | "MN" | "PY" | "KW" | "PR" | "GE" | "BO" | "SV" | "QA" | "GT" | "LU" | "UZ" | "KG" | "MK" | "KH" | "BA" | "IS" | "JO" | "PK" | "TT" | "CY" | "HN" | "NI" | "BH" | "MV" | "BD" | "PF" | "LB" | "NP" | "IQ" | "GU" | "AZ" | "AL" | "MT" | "MM" | "NC" | "OM" | "IR" | "AM" | "GP" | "MQ" | "JM" | "LA" | "LK" | "PS" | "MU" | "SY" | "ME" | "FO" | "JE" | "GF" | "MP" | "IM" | "SR" | "BZ" | "BB" | "AW" | "LY" | "AX" | "GG" | "MG" | "SD" | "LI" | "BS" | "KE" | "GL" | "BM" | "EU" | "CI" | "GY" | "GI" | "VI" | "AD" | "LC" | "TJ" | "AG" | "SN" | "PM" | "CK" | "AQ" | "CF" | "LR" | "ER"; + + +export type auth_scopes = ( + 'chat.read' | + 'chat.write' | + 'chat.write_manage' | + 'delegate' | + 'forum.write' | + 'friends.read' | + 'identify' | + 'public' +)[]; + + +export type auth_params = ({ + method: 'stable v2'; + + client_id: number | string; + client_secret: string; + + scopes: auth_scopes; +} | { + method: 'stable v1'; + + api_key: string; +} | { + method: 'lazer' + + login: string; + password: string; +} | { + method: 'cli'; + + client_id: number | string; + client_secret: string; + + redirect_url: string; + state: string; + + scopes: auth_scopes; +}); + + +export type auth_response = { + access_token: string; + expires_in: number; +}; \ No newline at end of file diff --git a/utility/auth.ts b/utility/auth.ts index b1315def..413943e3 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -1,120 +1,109 @@ -// PACKAGES -// import { execSync } from 'child_process'; -// import readln from "readline"; - - -// IMPORTS +import { execSync } from 'child_process'; import { request } from "./request"; -// import { gamemode_names } from './types'; +import readln from "readline"; -export type auth_scopes = [ - 'chat.read' | - 'chat.write' | - 'chat.write_manage' | - 'delegate' | - 'forum.write' | - 'friends.read' | - 'identify' | - 'public' -]; +import { auth_params, auth_response, auth_scopes, gamemode_names } from '../types/index'; +import { UserDetails } from '../types/user_details'; -export type auth_login = { - access_token: string, - expires_in: number -} const credentials: { - type: number, - username: string, - password: string, - clientId: number, - clientSecret: string, - redirect_uri: string, - scopes: auth_scopes, + method: any; + + api_key: string; + + client_id: number | string; + client_secret: string; + + login: string; + password: string; + + redirect_url: string; + state: string; + + scopes: auth_scopes; } = { - type: 0, - username: '', + method: '' as any, + + api_key: '', + + client_id: '', + client_secret: '', + + login: '', password: '', - clientId: 0, - clientSecret: '', - redirect_uri: '', + + redirect_url: '', + state: '', + scopes: ['public'], }; +export const cache_tokens = { + v1: '', + v2: '', +}; + -export let cache_v1: string = ''; -export let cache_v2: string = ''; +export const login = async (params: auth_params) => { + credentials.method = params.method; -export const set_v1 = (v: string) => cache_v1 = v; -export const set_v2 = (v: string) => cache_v2 = v; -const isInitial = () => cache_v2 != ''; + if (params.method == 'stable v1') { + credentials.api_key = params.api_key; -const store_credentials = (type: number, obj: { - username?: string, password?: string, clientId?: number, clientSecret?: string, scopes?: auth_scopes, redirect_uri?: string -}) => { - if (type == 1) { - credentials.type = 1; - credentials.username = obj.username; - credentials.password = obj.password; + cache_tokens.v1 = params.api_key; + return cache_tokens.v1; }; - if (type == 2) { - credentials.type = 2; - credentials.clientId = obj.clientId; - credentials.clientSecret = obj.clientSecret; - credentials.scopes = obj.scopes; + + if (params.method == 'stable v2') { + credentials.client_id = params.client_id; + credentials.client_secret = params.client_secret; + if (params.scopes) credentials.scopes = params.scopes; + + const authorize = await client_login(params.client_id, params.client_secret, params.scopes || ['public']); + return authorize; }; - if (type == 3) { - credentials.type = 3; - credentials.clientId = obj.clientId; - credentials.clientSecret = obj.clientSecret; - credentials.redirect_uri = obj.redirect_uri; - credentials.scopes = obj.scopes; + + if (params.method == 'lazer') { + credentials.login = params.login; + credentials.password = params.password; + + const authorize = await lazer_login(params.login, params.password); + return authorize; }; -}; -export const update_cache_token = async () => { - // if (credentials.type == 1) await lazer_user(credentials.username, credentials.password); - if (credentials.type == 2) await client_login(credentials.clientId, credentials.clientSecret, credentials.scopes); - // if (credentials.type == 3) await cli(credentials.clientId, credentials.clientSecret, credentials.redirect_uri, credentials.scope); + if (params.method == 'cli') { + credentials.client_id = params.client_id; + credentials.client_secret = params.client_secret; + if (params.scopes) credentials.scopes = params.scopes; - return true; -}; + credentials.redirect_url = params.redirect_url; + credentials.state = params.state; + + const authorize = await authorize_cli(params.client_id, params.client_secret, params.redirect_url, params.scopes || ['public'], params.state); + return authorize; + }; -/** - * # Authorization via osu client - * - clientId - osu Client ID - * - clientSecret - osu Client Secret - * - _**(optional)**_ scopes - list of scopes - * - chat.read - Allows read chat messages on a user's behalf. - * - chat.write - Allows sending chat messages on a user's behalf. - * - chat.write_manage - Allows joining and leaving chat channels on a user's behalf. - * - delegate - Allows acting as the owner of a client; only available for Client Credentials Grant. - * - forum.write - Allows creating and editing forum posts on a user's behalf. - * - friends.read - Allows reading of the user's friend list. - * - identify - Allows reading of the public profile of the user (/me). - * - public - Allows reading of publicly available data on behalf of the user. - */ -export const client_login = async (clientId: number, clientSecret: string, scopes?: auth_scopes): Promise => { - if (scopes == null) - throw new Error('Specify scopes'); - if (scopes != null && !Array.isArray(scopes)) - throw new Error('Scopes must be an Array'); + throw new Error('Unknown login method'); +}; + +export const set_v2 = (token: string) => cache_tokens.v2 = token; - // add public scopes - if (scopes == null) - scopes = ['public']; +export const refresh_token = async () => { + const refresh = await login(credentials); + return refresh; +}; - if (!isInitial()) store_credentials(2, { clientId, clientSecret, scopes }); +const client_login = async (client_id: number | string, client_secret: string, scopes: auth_scopes): Promise => { const { access_token, expires_in } = await request('https://osu.ppy.sh/oauth/token', { method: 'POST', headers: { @@ -123,14 +112,120 @@ export const client_login = async (clientId: number, clientSecret: string, scope }, data: JSON.stringify({ grant_type: 'client_credentials', - client_id: clientId, - client_secret: clientSecret, + client_id: client_id, + client_secret: client_secret, scope: scopes.join(' '), code: 'code', }) }); - cache_v2 = access_token; + cache_tokens.v2 = access_token; + return { access_token, expires_in }; +}; + + +const lazer_login = async (login: string, password: string) => { + const { access_token, expires_in } = await request('https://osu.ppy.sh/oauth/token', { + method: 'POST', + headers: { + "Accept": "application/json", + "Content-Type": "application/json", + }, + data: JSON.stringify({ + username: login, + password: password, + grant_type: "password", + client_id: 5, + client_secret: 'FGc9GAtyHzeQDshWP5Ah7dega8hJACAJpQtw6OXk', + scope: "*" + }) + }); + + + cache_tokens.v2 = access_token; return { access_token, expires_in }; +}; + + +const authorize_cli = async (client_id: number | string, client_secret: string, redirect_uri: string, scopes: auth_scopes, state?: string): Promise => { + const cl = readln.createInterface(process.stdin, process.stdout); + const question = (q: string) => new Promise((res, rej) => cl.question(q + ': ', (answer: string) => res(answer))); + + + const url = build_url({ client_id, redirect_uri, scopes, state }); + const start = (process.platform == 'darwin' ? 'open' : process.platform == 'win32' ? 'start' : 'xdg-open'); + execSync(start + ' ' + url.replace(/&/g, '^&')); + + + const code = await question('Paste code here'); + const { access_token, expires_in } = await request('https://osu.ppy.sh/oauth/token', { + method: 'POST', + headers: { + "Accept": "application/json", + "Content-Type": "application/json", + }, + data: JSON.stringify({ + grant_type: 'authorization_code', + client_id: client_id, + client_secret: client_secret, + redirect_uri: redirect_uri, + code, + }) + }); + + + cache_tokens.v2 = access_token; + return { access_token, expires_in }; +}; + + +export const build_url = ({ client_id, redirect_uri, scopes, state }: { + client_id: number | string, + redirect_uri: string, + scopes: auth_scopes, + state?: string +}): string => { + const url = new URL('https://osu.ppy.sh/oauth/authorize'); + const params: any = { + client_id: client_id, + redirect_uri: redirect_uri, + response_type: 'code', + scope: scopes.join(' '), + state: state, + }; + + + Object.keys(params).forEach(key => url.searchParams.append(key, params[key])); + return url.href; +}; + + +export const authorize = async ({ code, mode, client_id, client_secret, redirect_url }: { + code: string; + mode: gamemode_names; + + client_id: number | string; + client_secret: string; + + redirect_url: string; +}): Promise => { + const { access_token } = await request('https://osu.ppy.sh/oauth/token', { + method: 'POST', + headers: { + "Accept": "application/json", + "Content-Type": "application/json", + }, + data: JSON.stringify({ + grant_type: 'authorization_code', + client_id: client_id, + client_secret: client_secret, + redirect_uri: redirect_url, + code, + }) + }); + + + const user = await request(`https://osu.ppy.sh/api/v2/me/${mode}`, { params: { v2: access_token } }); + return user; }; \ No newline at end of file diff --git a/utility/request.ts b/utility/request.ts index 3342359e..6ee0c267 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -43,13 +43,13 @@ export const request = (url: string, { method, headers, data, params = {} }: Req // V1 add credentials if (url.includes('https://osu.ppy.sh/api/') && !url.includes('https://osu.ppy.sh/api/v2')) - params.k = params.v1 || auth.cache_v1; + params.k = params.v1 || auth.cache_tokens.v1; // V2 add credentials if (url.includes('https://osu.ppy.sh/api/v2')) headers = { // @ts-ignore - Authorization: `Bearer ${params.v2 || auth.cache_v2}`, + Authorization: `Bearer ${params.v2 || auth.cache_tokens.v2}`, Accept: `application/json`, 'Content-Type': `application/json`, }; @@ -70,8 +70,8 @@ export const request = (url: string, { method, headers, data, params = {} }: Req if (/^application\/json/.test(response.headers['content-type'])) { try { const parse = JSON.parse(data); - if (parse.authentication === 'basic' && auth.cache_v2 && total_retries < 3) { - await auth.update_cache_token(); + if (parse.authentication === 'basic' && auth.cache_tokens.v1 && total_retries < 3) { + await auth.refresh_token(); total_retries++; From 2e4ce4f61982672dbcf88b50ba656231027d65e4 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 11 Dec 2023 07:50:15 +0300 Subject: [PATCH 024/259] site search endpoint --- api/v2/index.ts | 8 +++++++- api/v2/search/index.ts | 40 ++++++++++++++++++++++++++++++++++++ types/v2/search_all.ts | 46 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 api/v2/search/index.ts create mode 100644 types/v2/search_all.ts diff --git a/api/v2/index.ts b/api/v2/index.ts index 0d9ead28..3b96352d 100644 --- a/api/v2/index.ts +++ b/api/v2/index.ts @@ -54,4 +54,10 @@ export const forums = { topic: { details: forums_topic_details } -} \ No newline at end of file +}; + + + +import search_all from './search/index'; + +export const search = search_all; \ No newline at end of file diff --git a/api/v2/search/index.ts b/api/v2/search/index.ts new file mode 100644 index 00000000..88f85b72 --- /dev/null +++ b/api/v2/search/index.ts @@ -0,0 +1,40 @@ +import { request } from "../../../utility/request"; +import { SearchAll } from '../../../types/v2/search_all'; + + +type Test = ({ + type: 'site'; + mode?: 'all' | 'user' | 'wiki_page'; + query?: string; + page?: number; +} | { + type: 'beatmaps'; +}) + +const name = async (obj: Test): Promise => { + const params: any = {}; + let url = 'https://osu.ppy.sh/api/v2'; + + + switch (obj.type) { + case 'site': + url += '/search'; + + + params.mode = obj.mode; + params.query = obj.query; + params.page = obj.page; + break; + }; + + + const data = await request(url, { + method: 'GET', + params: params, + }); + + return { type: obj.type, result: data }; +}; + + +export default name; \ No newline at end of file diff --git a/types/v2/search_all.ts b/types/v2/search_all.ts new file mode 100644 index 00000000..dcebb72c --- /dev/null +++ b/types/v2/search_all.ts @@ -0,0 +1,46 @@ +export interface SearchAll { + type: string + result: Result +} + +export interface Result { + user: User + wiki_page: WikiPage +} + +export interface User { + data: UserData[] + total: number +} + +export interface UserData { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour: any + username: string +} + +export interface WikiPage { + data: WikiData[] + total: number +} + +export interface WikiData { + available_locales: string[] + layout: string + locale: string + markdown: string + path: string + subtitle?: string + tags: string[] + title: string +} From 0bd58131ff0a2c65bf6089db3e83c6fdb0133718 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 11 Dec 2023 07:50:36 +0300 Subject: [PATCH 025/259] combine user.me and user.details endpoints --- api/v2/user/details.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/api/v2/user/details.ts b/api/v2/user/details.ts index 35fb8865..bb927af2 100644 --- a/api/v2/user/details.ts +++ b/api/v2/user/details.ts @@ -4,10 +4,20 @@ import { UserDetails } from '../../../types/user_details'; -const name = async (user: number, { mode, key }: { mode?: gamemode_names, key?: 'id' | 'username' } = {}): Promise => { - let url = `https://osu.ppy.sh/api/v2/users/${user}`; - if (mode != null) - url += `/${mode}`; +const name = async ({ myself, user, mode, key }: { + myself?: boolean; + user?: number; + mode?: gamemode_names; + key?: 'id' | 'username'; +}): Promise => { + let url = 'https://osu.ppy.sh/api/v2'; + + + if (myself == true) url += '/me'; + else if (user != null) url += `/users/${user}`; + + if (mode != null) url += `/${mode}`; + const data = await request(url, { method: 'GET', From af9dd9fcacbeeb44a5513c3dba82146070cb62bc Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 11 Dec 2023 07:50:49 +0300 Subject: [PATCH 026/259] ver bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 75c03dba..b16f5e16 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.7", + "version": "3.0.0-beta.8", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", From 5a38cce0dbff263d7f3260e19d32de5b87b3acd0 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 11 Dec 2023 08:07:49 +0300 Subject: [PATCH 027/259] add tokens to authorize --- package.json | 2 +- types/user_details.ts | 6 ++++++ utility/auth.ts | 10 +++++++--- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index b16f5e16..f6abc557 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.8", + "version": "3.0.0-beta.9", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/types/user_details.ts b/types/user_details.ts index 164f0f71..2500d424 100644 --- a/types/user_details.ts +++ b/types/user_details.ts @@ -65,6 +65,12 @@ export interface UserDetails { unranked_beatmapset_count: number; } +export interface UserAuth extends UserDetails { + access_token: string; + refresh_token: string; + expires_in: number; +} + export interface ActiveTournamentBanner { id: number; tournament_id: number; diff --git a/utility/auth.ts b/utility/auth.ts index 413943e3..e712a87f 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -4,7 +4,7 @@ import readln from "readline"; import { auth_params, auth_response, auth_scopes, gamemode_names } from '../types/index'; -import { UserDetails } from '../types/user_details'; +import { UserAuth } from '../types/user_details'; const credentials: { @@ -209,8 +209,8 @@ export const authorize = async ({ code, mode, client_id, client_secret, redirect client_secret: string; redirect_url: string; -}): Promise => { - const { access_token } = await request('https://osu.ppy.sh/oauth/token', { +}): Promise => { + const { access_token, refresh_token, expires_in } = await request('https://osu.ppy.sh/oauth/token', { method: 'POST', headers: { "Accept": "application/json", @@ -227,5 +227,9 @@ export const authorize = async ({ code, mode, client_id, client_secret, redirect const user = await request(`https://osu.ppy.sh/api/v2/me/${mode}`, { params: { v2: access_token } }); + user.access_token; + user.refresh_token; + user.expires_in; + return user; }; \ No newline at end of file From 176357c30f28d84bb9c3db06e217093367f12586 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 11 Dec 2023 09:50:39 +0300 Subject: [PATCH 028/259] oopps --- package.json | 2 +- utility/auth.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index f6abc557..18a7a418 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.9", + "version": "3.0.0-beta.10", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/utility/auth.ts b/utility/auth.ts index e712a87f..aaaf8333 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -226,7 +226,7 @@ export const authorize = async ({ code, mode, client_id, client_secret, redirect }); - const user = await request(`https://osu.ppy.sh/api/v2/me/${mode}`, { params: { v2: access_token } }); + const user = await request(`https://osu.ppy.sh/api/v2/me/${mode}`, { method: 'GET', params: { v2: access_token } }); user.access_token; user.refresh_token; user.expires_in; From f648874bdd3d7c03a4c7862674d8a63b6df66711 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 11 Dec 2023 09:53:24 +0300 Subject: [PATCH 029/259] dude --- package.json | 2 +- utility/auth.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 18a7a418..f0037152 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.10", + "version": "3.0.0-beta.11", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/utility/auth.ts b/utility/auth.ts index aaaf8333..f0bf939b 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -192,8 +192,8 @@ export const build_url = ({ client_id, redirect_uri, scopes, state }: { redirect_uri: redirect_uri, response_type: 'code', scope: scopes.join(' '), - state: state, }; + if (state) params.state = state; Object.keys(params).forEach(key => url.searchParams.append(key, params[key])); @@ -227,9 +227,9 @@ export const authorize = async ({ code, mode, client_id, client_secret, redirect const user = await request(`https://osu.ppy.sh/api/v2/me/${mode}`, { method: 'GET', params: { v2: access_token } }); - user.access_token; - user.refresh_token; - user.expires_in; + user.access_token = access_token; + user.refresh_token = refresh_token; + user.expires_in = expires_in; return user; }; \ No newline at end of file From 0a555475198693cbabd47f457f75d5a2333e6990 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 16 Dec 2023 09:48:10 +0300 Subject: [PATCH 030/259] change type name + enums --- api/v2/scores/beatmaps.ts | 4 ++-- api/v2/scores/details.ts | 4 ++-- api/v2/scores/user/beatmap.ts | 4 ++-- api/v2/scores/user/list.ts | 4 ++-- api/v2/site/ranking/details.ts | 4 ++-- api/v2/user/details.ts | 4 ++-- index.ts | 1 + types/enums.ts | 40 ++++++++++++++++++++++++++++++++++ types/index.ts | 5 ++++- utility/auth.ts | 4 ++-- 10 files changed, 59 insertions(+), 15 deletions(-) create mode 100644 types/enums.ts diff --git a/api/v2/scores/beatmaps.ts b/api/v2/scores/beatmaps.ts index 364b44fb..5a0576fc 100644 --- a/api/v2/scores/beatmaps.ts +++ b/api/v2/scores/beatmaps.ts @@ -1,9 +1,9 @@ import { request } from "../../../utility/request"; -import { gamemode_names } from '../../../types'; +import { Modes_names } from '../../../types'; -const name = async (beatmap_id: number, obj: { mode: gamemode_names, mods: string[], type: 'global' | 'country' | 'friend' }) => { +const name = async (beatmap_id: number, obj: { mode: Modes_names, mods: string[], type: 'global' | 'country' | 'friend' }) => { const data = await request(`https://osu.ppy.sh/api/v2/beatmaps/${beatmap_id}/scores`, { method: 'GET', params: obj, diff --git a/api/v2/scores/details.ts b/api/v2/scores/details.ts index 339bff25..f18530ad 100644 --- a/api/v2/scores/details.ts +++ b/api/v2/scores/details.ts @@ -1,10 +1,10 @@ import { request } from "../../../utility/request"; -import { gamemode_names } from "../../../types"; +import { Modes_names } from "../../../types"; import { ScoresDetails } from '../../../types/scores_details'; -const name = async (score_id: number, mode: gamemode_names): Promise => { +const name = async (score_id: number, mode: Modes_names): Promise => { if (mode == null) throw new Error('Gamemode name not specified'); diff --git a/api/v2/scores/user/beatmap.ts b/api/v2/scores/user/beatmap.ts index 32c2187a..37438fd8 100644 --- a/api/v2/scores/user/beatmap.ts +++ b/api/v2/scores/user/beatmap.ts @@ -1,9 +1,9 @@ -import { gamemode_names } from "../../../../types"; +import { Modes_names } from "../../../../types"; import { request } from "../../../../utility/request"; -const name = async (beatmap_id: number, user_id: number, obj: { mode?: gamemode_names, mods?: string[], best_only?: boolean } = {}) => { +const name = async (beatmap_id: number, user_id: number, obj: { mode?: Modes_names, mods?: string[], best_only?: boolean } = {}) => { let url = `https://osu.ppy.sh/api/v2/beatmaps/${beatmap_id}/scores/users/${user_id}`; if (!obj.best_only) url += '/all'; diff --git a/api/v2/scores/user/list.ts b/api/v2/scores/user/list.ts index b010b290..efdbc4e3 100644 --- a/api/v2/scores/user/list.ts +++ b/api/v2/scores/user/list.ts @@ -1,5 +1,5 @@ import { request } from "../../../../utility/request"; -import { gamemode_names } from "../../../../types"; +import { Modes_names } from "../../../../types"; import mods from '../../../../tools/mods'; import { ScoresUser } from '../../../../types/scores_user'; @@ -7,7 +7,7 @@ import { ScoresUser } from '../../../../types/scores_user'; const name = async (user_id: number, type: 'recent' | 'best' | 'firsts' | 'pinned', object?: { include_fails?: boolean, - mode?: gamemode_names, + mode?: Modes_names, limit?: number, offset?: number, mods?: number diff --git a/api/v2/site/ranking/details.ts b/api/v2/site/ranking/details.ts index 5213d3f7..269abd04 100644 --- a/api/v2/site/ranking/details.ts +++ b/api/v2/site/ranking/details.ts @@ -1,10 +1,10 @@ -import { gamemode_names, ranking_types, country_codes } from "../../../../types"; +import { Modes_names, ranking_types, country_codes } from "../../../../types"; import { request } from "../../../../utility/request"; import { RankingDetails } from '../../../../types/ranking_details'; -const name = async (mode: gamemode_names, type: ranking_types, object?: { +const name = async (mode: Modes_names, type: ranking_types, object?: { country?: country_codes, "cursor[page]"?: number, filter?: 'all' | 'friends', diff --git a/api/v2/user/details.ts b/api/v2/user/details.ts index bb927af2..1db3a9db 100644 --- a/api/v2/user/details.ts +++ b/api/v2/user/details.ts @@ -1,5 +1,5 @@ import { request } from "../../../utility/request"; -import { gamemode_names } from "../../../types"; +import { Modes_names } from "../../../types"; import { UserDetails } from '../../../types/user_details'; @@ -7,7 +7,7 @@ import { UserDetails } from '../../../types/user_details'; const name = async ({ myself, user, mode, key }: { myself?: boolean; user?: number; - mode?: gamemode_names; + mode?: Modes_names; key?: 'id' | 'username'; }): Promise => { let url = 'https://osu.ppy.sh/api/v2'; diff --git a/index.ts b/index.ts index c9410aff..54bd5bfe 100644 --- a/index.ts +++ b/index.ts @@ -13,6 +13,7 @@ export * as country from './tools/country'; export * as mods from './tools/mods'; export * as auth from './utility/auth'; +export * as Enums from './types/enums'; export * as v2 from "./api/v2/index"; \ No newline at end of file diff --git a/types/enums.ts b/types/enums.ts new file mode 100644 index 00000000..a0735817 --- /dev/null +++ b/types/enums.ts @@ -0,0 +1,40 @@ +export enum Modes_enums { + osu = 0, + taiko = 1, + fruits = 2, + mania = 3, +}; + +export enum Genres_enum { + 'Unspecified', + 'Video Game', + 'Anime', + 'Rock', + 'Pop', + 'Other', + 'Novelty', + 'Hip Hop', + 'Electronic', + 'Metal', + 'Classical', + 'Folk', + 'Jazz' +} + +export enum Languages_enum { + Any, + English, + Chinese, + French, + German, + Italian, + Japanese, + Korean, + Spanish, + Swedish, + Russian, + Polish, + Instrumental, + Unspecified, + Other, +} \ No newline at end of file diff --git a/types/index.ts b/types/index.ts index 023dca55..ae08c5a8 100644 --- a/types/index.ts +++ b/types/index.ts @@ -1,4 +1,6 @@ -export type gamemode_names = 'osu' | 'fruits' | 'mania' | 'taiko'; +export type Modes_names = 'osu' | 'fruits' | 'mania' | 'taiko'; + + export type ranking_types = 'charts' | 'country' | 'performance' | 'score'; @@ -6,6 +8,7 @@ export type country_names = "United States" | "Russian Federation" | "Germany" | export type country_codes = "US" | "RU" | "DE" | "PL" | "FR" | "JP" | "CA" | "BR" | "GB" | "TW" | "KR" | "CN" | "AU" | "ID" | "UA" | "PH" | "CL" | "FI" | "AR" | "NL" | "SE" | "SG" | "MX" | "MY" | "ES" | "IT" | "HK" | "TH" | "VN" | "NO" | "CZ" | "TR" | "BY" | "AT" | "BE" | "PT" | "RO" | "HU" | "DK" | "LT" | "KZ" | "NZ" | "PE" | "CH" | "CO" | "IL" | "EE" | "BG" | "SK" | "GR" | "LV" | "VE" | "RS" | "IE" | "HR" | "SA" | "UY" | "ZA" | "AE" | "SI" | "IN" | "EC" | "MA" | "CR" | "MD" | "DO" | "BN" | "EG" | "RE" | "MO" | "TN" | "PA" | "DZ" | "MN" | "PY" | "KW" | "PR" | "GE" | "BO" | "SV" | "QA" | "GT" | "LU" | "UZ" | "KG" | "MK" | "KH" | "BA" | "IS" | "JO" | "PK" | "TT" | "CY" | "HN" | "NI" | "BH" | "MV" | "BD" | "PF" | "LB" | "NP" | "IQ" | "GU" | "AZ" | "AL" | "MT" | "MM" | "NC" | "OM" | "IR" | "AM" | "GP" | "MQ" | "JM" | "LA" | "LK" | "PS" | "MU" | "SY" | "ME" | "FO" | "JE" | "GF" | "MP" | "IM" | "SR" | "BZ" | "BB" | "AW" | "LY" | "AX" | "GG" | "MG" | "SD" | "LI" | "BS" | "KE" | "GL" | "BM" | "EU" | "CI" | "GY" | "GI" | "VI" | "AD" | "LC" | "TJ" | "AG" | "SN" | "PM" | "CK" | "AQ" | "CF" | "LR" | "ER"; + export type auth_scopes = ( 'chat.read' | 'chat.write' | diff --git a/utility/auth.ts b/utility/auth.ts index f0bf939b..4b316505 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -3,7 +3,7 @@ import { request } from "./request"; import readln from "readline"; -import { auth_params, auth_response, auth_scopes, gamemode_names } from '../types/index'; +import { auth_params, auth_response, auth_scopes, Modes_names } from '../types/index'; import { UserAuth } from '../types/user_details'; @@ -203,7 +203,7 @@ export const build_url = ({ client_id, redirect_uri, scopes, state }: { export const authorize = async ({ code, mode, client_id, client_secret, redirect_url }: { code: string; - mode: gamemode_names; + mode: Modes_names; client_id: number | string; client_secret: string; From 7b648303195780de89632c67f23eeeba1a549233 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 16 Dec 2023 09:48:55 +0300 Subject: [PATCH 031/259] [endpoint] Beatmaps Search --- api/v2/search/index.ts | 61 +++++++++++++++++++-- types/index.ts | 7 +++ types/v2/search_all.ts | 118 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 175 insertions(+), 11 deletions(-) diff --git a/api/v2/search/index.ts b/api/v2/search/index.ts index 88f85b72..25e50f78 100644 --- a/api/v2/search/index.ts +++ b/api/v2/search/index.ts @@ -1,17 +1,46 @@ +import { beatmap_category, beatmap_sorting, beatmap_statuses, Modes_names, beatmap_genres, beatmap_languages, beatmap_ranks, beatmap_extra } from "../../../types"; +import { Genres_enum, Languages_enum, Modes_enums } from "../../../types/enums"; +import { SearchBeatmaps, SearchWiki } from '../../../types/v2/search_all'; import { request } from "../../../utility/request"; -import { SearchAll } from '../../../types/v2/search_all'; -type Test = ({ +type params = ({ type: 'site'; mode?: 'all' | 'user' | 'wiki_page'; query?: string; page?: number; } | { + _played?: boolean; + _nsfw?: boolean; + type: 'beatmaps'; -}) + query?: string; + mode?: Modes_names | number; + status?: beatmap_statuses; + category?: (beatmap_category)[]; + + genre?: beatmap_genres | number; + language?: beatmap_languages | number; + + achieved_rank?: (beatmap_ranks)[]; + + extra?: (beatmap_extra)[]; + sort?: beatmap_sorting; + + cursor_string?: string; +}); + +type Response = + T extends 'site' ? { + type: 'site', + result: SearchWiki + } : T extends 'beatmaps' ? { + type: 'beatmaps', + result: SearchBeatmaps + } : never; + -const name = async (obj: Test): Promise => { +const name = async (obj: T): Promise> => { const params: any = {}; let url = 'https://osu.ppy.sh/api/v2'; @@ -25,6 +54,28 @@ const name = async (obj: Test): Promise => { params.query = obj.query; params.page = obj.page; break; + + case 'beatmaps': + url += '/beatmapsets/search'; + + if (obj._played) params.played = obj._played ? 'played' : 'unplayed'; + if (obj._nsfw) params.nsfw = obj._nsfw; + + if (obj.query) params.q = obj.query; + if (obj.mode) params.m = typeof obj.mode == 'number' ? obj.mode : Modes_enums[obj.mode]; + if (obj.status) params.s = obj.status; + if (obj.category) params.c = obj.category.join('.'); + + if (obj.genre) params.g = typeof obj.genre == 'number' ? obj.genre : Genres_enum[obj.genre]; + if (obj.language) params.l = typeof obj.language == 'number' ? obj.language : Languages_enum[obj.language]; + + if (obj.achieved_rank) params.r = obj.achieved_rank.join('.'); + + if (obj.extra) params.e = obj.extra.join('.'); + + if (obj.sort) params.sort = obj.sort; + if (obj.cursor_string) params.cursor_string = obj.cursor_string; + break; }; @@ -33,7 +84,7 @@ const name = async (obj: Test): Promise => { params: params, }); - return { type: obj.type, result: data }; + return { type: obj.type, result: data } as Response; }; diff --git a/types/index.ts b/types/index.ts index ae08c5a8..78d4e9d1 100644 --- a/types/index.ts +++ b/types/index.ts @@ -7,6 +7,13 @@ export type ranking_types = 'charts' | 'country' | 'performance' | 'score'; export type country_names = "United States" | "Russian Federation" | "Germany" | "Poland" | "France" | "Japan" | "Canada" | "Brazil" | "United Kingdom" | "Taiwan" | "South Korea" | "China" | "Australia" | "Indonesia" | "Ukraine" | "Philippines" | "Chile" | "Finland" | "Argentina" | "Netherlands" | "Sweden" | "Singapore" | "Mexico" | "Malaysia" | "Spain" | "Italy" | "Hong Kong" | "Thailand" | "Vietnam" | "Norway" | "Czech Republic" | "Turkey" | "Belarus" | "Austria" | "Belgium" | "Portugal" | "Romania" | "Hungary" | "Denmark" | "Lithuania" | "Kazakhstan" | "New Zealand" | "Peru" | "Switzerland" | "Colombia" | "Israel" | "Estonia" | "Bulgaria" | "Slovakia" | "Greece" | "Latvia" | "Venezuela" | "Serbia" | "Ireland" | "Croatia" | "Saudi Arabia" | "Uruguay" | "South Africa" | "United Arab Emirates" | "Slovenia" | "India" | "Ecuador" | "Morocco" | "Costa Rica" | "Moldova" | "Dominican Republic" | "Brunei" | "Egypt" | "Reunion" | "Macau" | "Tunisia" | "Panama" | "Algeria" | "Mongolia" | "Paraguay" | "Kuwait" | "Puerto Rico" | "Georgia" | "Bolivia" | "El Salvador" | "Qatar" | "Guatemala" | "Luxembourg" | "Uzbekistan" | "Kyrgyzstan" | "North Macedonia" | "Cambodia" | "Bosnia and Herzegovina" | "Iceland" | "Jordan" | "Pakistan" | "Trinidad and Tobago" | "Cyprus" | "Honduras" | "Nicaragua" | "Bahrain" | "Maldives" | "Bangladesh" | "French Polynesia" | "Lebanon" | "Nepal" | "Iraq" | "Guam" | "Azerbaijan" | "Albania" | "Malta" | "Myanmar" | "New Caledonia" | "Oman" | "Iran, Islamic Republic of" | "Armenia" | "Guadeloupe" | "Martinique" | "Jamaica" | "Lao People 's Democratic Republic" | "Sri Lanka" | "Palestinian Territory Occupied" | "Mauritius" | "Syrian Arab Republic" | "Montenegro" | "Faroe Islands" | "Jersey" | "French Guiana" | "Northern Mariana Islands" | "Isle of Man" | "Suriname" | "Belize" | "Barbados" | "Aruba" | "Libya" | "Aland Islands" | "Guernsey" | "Madagascar" | "Sudan" | "Liechtenstein" | "Bahamas" | "Kenya" | "Greenland" | "Bermuda" | "Europe" | "Cote D ' Ivoire" | "Guyana" | "Gibraltar" | "Virgin Islands, U.S." | "Andorra" | "Saint Lucia" | "Tajikistan" | "Antigua and Barbuda" | "Senegal" | "Saint Pierre and Miquelon" | "Cook Islands" | "Antarctica" | "Central African Republic" | "Liberia" | "Eritrea"; export type country_codes = "US" | "RU" | "DE" | "PL" | "FR" | "JP" | "CA" | "BR" | "GB" | "TW" | "KR" | "CN" | "AU" | "ID" | "UA" | "PH" | "CL" | "FI" | "AR" | "NL" | "SE" | "SG" | "MX" | "MY" | "ES" | "IT" | "HK" | "TH" | "VN" | "NO" | "CZ" | "TR" | "BY" | "AT" | "BE" | "PT" | "RO" | "HU" | "DK" | "LT" | "KZ" | "NZ" | "PE" | "CH" | "CO" | "IL" | "EE" | "BG" | "SK" | "GR" | "LV" | "VE" | "RS" | "IE" | "HR" | "SA" | "UY" | "ZA" | "AE" | "SI" | "IN" | "EC" | "MA" | "CR" | "MD" | "DO" | "BN" | "EG" | "RE" | "MO" | "TN" | "PA" | "DZ" | "MN" | "PY" | "KW" | "PR" | "GE" | "BO" | "SV" | "QA" | "GT" | "LU" | "UZ" | "KG" | "MK" | "KH" | "BA" | "IS" | "JO" | "PK" | "TT" | "CY" | "HN" | "NI" | "BH" | "MV" | "BD" | "PF" | "LB" | "NP" | "IQ" | "GU" | "AZ" | "AL" | "MT" | "MM" | "NC" | "OM" | "IR" | "AM" | "GP" | "MQ" | "JM" | "LA" | "LK" | "PS" | "MU" | "SY" | "ME" | "FO" | "JE" | "GF" | "MP" | "IM" | "SR" | "BZ" | "BB" | "AW" | "LY" | "AX" | "GG" | "MG" | "SD" | "LI" | "BS" | "KE" | "GL" | "BM" | "EU" | "CI" | "GY" | "GI" | "VI" | "AD" | "LC" | "TJ" | "AG" | "SN" | "PM" | "CK" | "AQ" | "CF" | "LR" | "ER"; +export type beatmap_statuses = 'any' | 'ranked' | 'qualified' | 'loved' | 'favourites' | 'pending' | 'wip' | 'graveyard' | 'mine'; +export type beatmap_category = 'converts' | 'follows' | 'recommended' | 'featured_artists' | 'spotlights'; +export type beatmap_sorting = 'title_desc' | 'title_asc' | 'artist_desc' | 'artist_asc' | 'difficulty_desc' | 'difficulty_asc' | 'updated_desc' | 'updated_asc' | 'ranked_desc' | 'ranked_asc' | 'rating_desc' | 'rating_asc' | 'plays_desc' | 'plays_asc' | 'favourites_desc' | 'favourites_asc'; +export type beatmap_genres = 'Unspecified' | 'Video Game' | 'Anime' | 'Rock' | 'Pop' | 'Other' | 'Novelty' | 'Hip Hop' | 'Electronic' | 'Metal' | 'Classical' | 'Folk' | 'Jazz'; +export type beatmap_languages = 'Any' | 'English' | 'Chinese' | 'French' | 'German' | 'Italian' | 'Japanese' | 'Korean' | 'Spanish' | 'Swedish' | 'Russian' | 'Polish' | 'Instrumental' | 'Unspecified' | 'Other'; +export type beatmap_ranks = 'XH' | 'X' | 'SH' | 'S' | 'A' | 'B' | 'C' | 'D'; +export type beatmap_extra = 'storyboard' | 'video'; export type auth_scopes = ( diff --git a/types/v2/search_all.ts b/types/v2/search_all.ts index dcebb72c..6a5aad3a 100644 --- a/types/v2/search_all.ts +++ b/types/v2/search_all.ts @@ -1,9 +1,4 @@ -export interface SearchAll { - type: string - result: Result -} - -export interface Result { +export interface SearchWiki { user: User wiki_page: WikiPage } @@ -44,3 +39,114 @@ export interface WikiData { tags: string[] title: string } + + +export interface SearchBeatmaps { + beatmapsets: Beatmapset[] + search: Search + recommended_difficulty: any + error: any + total: number + cursor: Cursor + cursor_string: string +} + +export interface Beatmapset { + artist: string + artist_unicode: string + covers: Covers + creator: string + favourite_count: number + hype: any + id: number + nsfw: boolean + offset: number + play_count: number + preview_url: string + source: string + spotlight: boolean + status: string + title: string + title_unicode: string + track_id?: number + user_id: number + video: boolean + bpm: number + can_be_hyped: boolean + deleted_at: any + discussion_enabled: boolean + discussion_locked: boolean + is_scoreable: boolean + last_updated: string + legacy_thread_url: string + nominations_summary: NominationsSummary + ranked: number + ranked_date: string + storyboard: boolean + submitted_date: string + tags: string + availability: Availability + beatmaps: Beatmap[] + pack_tags: string[] +} + +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} + +export interface NominationsSummary { + current: number + required: number +} + +export interface Availability { + download_disabled: boolean + more_information: any +} + +export interface Beatmap { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + accuracy: number + ar: number + bpm: number + convert: boolean + count_circles: number + count_sliders: number + count_spinners: number + cs: number + deleted_at: any + drain: number + hit_length: number + is_scoreable: boolean + last_updated: string + mode_int: number + passcount: number + playcount: number + ranked: number + url: string + checksum: string + max_combo: number +} + +export interface Search { + sort: string +} + +export interface Cursor { + approved_date: number + id: number +} From f96f0d542a8112d4dcf1d381865381d573d9635e Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 16 Dec 2023 12:27:56 +0300 Subject: [PATCH 032/259] added download file function --- utility/request.ts | 138 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 126 insertions(+), 12 deletions(-) diff --git a/utility/request.ts b/utility/request.ts index 6ee0c267..7ad6df64 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -1,7 +1,7 @@ // PACKAGES -import https from 'https'; import querystring from 'node:querystring'; -// import fs from "fs"; +import https from 'https'; +import fs from "fs"; // CREDENTIALS @@ -9,19 +9,12 @@ import * as auth from "./auth"; // TYPES -interface RequestParams { - method?: string; - params?: { [key: string]: any }; - headers?: { [key: string]: string }; - data?: string; -}; - export interface RequestType { (url: string, params: { method: string, data?: string, headers?: { [key: string]: string }, - params?: object | [object, ...object[]]; + params?: { [key: string]: any }; }): Promise; }; @@ -32,7 +25,7 @@ let total_retries = 0; -export const request = (url: string, { method, headers, data, params = {} }: RequestParams = {}): Promise => new Promise((resolve, reject) => { +export const request: RequestType = (url, { method, headers, data, params = {} }): Promise => new Promise((resolve, reject) => { // check required args if (url == null) throw new Error('URL not specified'); @@ -106,4 +99,125 @@ export const request = (url: string, { method, headers, data, params = {} }: Req // write body to request, if specified if (data) req.write(data); req.end(); -}); \ No newline at end of file +}); + + +/** + * Executes an HTTP request + * @param {string} url The url + * @param {string} dest The file destination + * @returns {Promise} The response + */ +export const download = (url: string, dest: string, { _callback, headers = {}, data, params, callback }: { + _callback: boolean; + headers?: { [key: string]: string }, + data?: string; + params?: any; + callback?: Function; +}): Promise => { + return new Promise((resolve, reject) => { + + const file = fs.createWriteStream(dest, { encoding: 'utf8' }); + + file.on('error', err => { + fs.unlinkSync(dest); + reject(err); + }); + + file.on('finish', () => { + file.close(); + resolve(dest); + }); + + + if (url.includes('https://osu.ppy.sh/api/v2')) headers['Authorization'] = `Bearer ${params?.v2 || auth.cache_tokens.v2}`; + + if (!headers['accept']) headers['accept'] = `application/octet-stream`; + // if (!headers['content-type']) headers['content-type'] = `application/octet-stream`; + + + const generate_query = querystring.encode(params); + const build_url = url + (generate_query ? `?${generate_query}` : ''); + + // console.log({ url: build_url, method, headers, data }); + const req = https.request(build_url, { method: 'GET', headers }, response => { + const { location } = response.headers; + + if (location) { + download(location, dest, { _callback, headers, data, params, callback }) + .then(resolve) + .catch(reject); + return; + } + + if (response.statusCode === 404) { + resolve({ error: 'file unavailable' }); + return; + } + + if (_callback == true && callback !== undefined) { + const totalLength = parseInt(response.headers['content-length']); + + let progress = 0; + let progressBar = 0; + + response.on('data', (chunk) => { + progress += chunk.length; + progressBar = 100 * (progress / totalLength); + callback(progressBar); + }); + } + + response.pipe(file); + }); + + req.setTimeout(TIMEOUT_MS, () => { + req.destroy(); + reject(new Error(`Request to ${url} time out after ${TIMEOUT_MS}ms`)); + }); + + if (data) { + req.write(data); + } + req.end(); + }); +}; + + +// export const download = (url: string, destination: string, { headers, data, params }: { +// headers?: { [key: string]: string }, +// data?: string; +// params?: any +// }) => { +// if (url.includes('https://osu.ppy.sh/api/v2')) headers['Authorization'] = `Bearer ${params?.v2 || auth.cache_tokens.v2}`; + +// if (!headers['accept']) headers['accept'] = `application/octet-stream`; +// if (!headers['content-Type']) headers['content-Type'] = `application/octet-stream`; + + +// return request(url, { method: 'GET', data, headers, params }) +// .then((response: Buffer) => { +// if (!(response instanceof Buffer)) { +// throw new Error('Invalid response format. Expected binary data.'); +// } +// fs.writeFileSync(destination, response); +// }) +// .catch((error: Error) => { +// // Handle errors, such as network issues or failed requests +// console.error('Error downloading file:', error.message); +// throw error; +// }); +// }; + +// export const download = (url: string, destination: string, { headers, data, params }: { +// headers?: { [key: string]: string }, +// data?: string; +// params: any +// }) => new Promise((resolve, reject) => { +// const file = fs.createWriteStream(dest, { encoding: 'utf8' }); + + + +// request(url, { method: 'GET', data, headers, params }) +// .t +// }); \ No newline at end of file From 32a9375cca097b278d10360583a26746ac6277ec Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 16 Dec 2023 12:29:19 +0300 Subject: [PATCH 033/259] [endpoints] Beatmap id/set lookup + beatmap attribute lookup --- api/v2/beatmaps/lookup.ts | 86 +++++++++++ types/v2/beatmaps_lookup_attributes.ts | 16 ++ types/v2/beatmaps_lookup_difficulty.ts | 99 ++++++++++++ types/v2/beatmaps_lookup_set.ts | 204 +++++++++++++++++++++++++ 4 files changed, 405 insertions(+) create mode 100644 api/v2/beatmaps/lookup.ts create mode 100644 types/v2/beatmaps_lookup_attributes.ts create mode 100644 types/v2/beatmaps_lookup_difficulty.ts create mode 100644 types/v2/beatmaps_lookup_set.ts diff --git a/api/v2/beatmaps/lookup.ts b/api/v2/beatmaps/lookup.ts new file mode 100644 index 00000000..5a92a3b6 --- /dev/null +++ b/api/v2/beatmaps/lookup.ts @@ -0,0 +1,86 @@ +import { BeatmapsLookupAttributes } from "../../../types/v2/beatmaps_lookup_attributes"; +import { BeatmapsLookupDifficulty } from "../../../types/v2/beatmaps_lookup_difficulty"; +import { BeatmapsLookupSet } from "../../../types/v2/beatmaps_lookup_set"; +import { Modes_enums } from "../../../types/enums"; +import { request } from "../../../utility/request"; +import { Modes_names } from "../../../types"; + + +type params = ({ + type: 'difficulty'; + id: number; + checksum: string; + filename: string; +} | { + type: 'set'; + id: number; +} | { + type: 'attributes'; + id: number; + mods: number; + mode: Modes_names +}); + + +type Response = + T extends 'difficulty' ? { + type: 'difficulty'; + result: BeatmapsLookupDifficulty + } : T extends 'set' ? { + type: 'set'; + result: BeatmapsLookupSet + } : T extends 'attributes' ? { + type: 'attributes'; + result: BeatmapsLookupAttributes + } : never; + + +const name = async (obj: T): Promise> => { + const params: any = {}; + let url = 'https://osu.ppy.sh/api/v2'; + let method = 'GET'; + + + switch (obj.type) { + case 'difficulty': + url += '/beatmaps/lookup'; + + if (obj.id) params.id = obj.id; + if (obj.checksum) params.checksum = obj.checksum; + if (obj.filename) params.filename = obj.filename; + + break; + + case 'set': + url += '/beatmapsets/lookup'; + + if (obj.id) params.beatmap_id = obj.id; + + break; + + case 'attributes': + url += `/beatmaps/${obj.id}/attributes`; + method = 'POST'; + + if (obj.mods) params.mods = obj.mods; + + if (typeof obj.mode == 'string') params.ruleset = obj.mode; + else if (typeof obj.mode == 'number') params.ruleset_id = Modes_enums[obj.mode]; + + break; + }; + + + const data = await request(url, { + method: method, + params: params, + }); + + if (obj.type == 'attributes') + return { type: obj.type, result: data.attributes } as Response; + + return { type: obj.type, result: data } as Response; +}; + + +export default name; \ No newline at end of file diff --git a/types/v2/beatmaps_lookup_attributes.ts b/types/v2/beatmaps_lookup_attributes.ts new file mode 100644 index 00000000..656ce27b --- /dev/null +++ b/types/v2/beatmaps_lookup_attributes.ts @@ -0,0 +1,16 @@ +export interface BeatmapsLookupAttributes { + star_rating: number + max_combo: number + aim_difficulty?: number + speed_difficulty?: number + speed_note_count?: number + flashlight_difficulty?: number + slider_factor?: number + approach_rate?: number + overall_difficulty?: number + stamina_difficulty?: number + rhythm_difficulty?: number + colour_difficulty?: number + peak_difficulty?: number + great_hit_window?: number +} diff --git a/types/v2/beatmaps_lookup_difficulty.ts b/types/v2/beatmaps_lookup_difficulty.ts new file mode 100644 index 00000000..4917f5a1 --- /dev/null +++ b/types/v2/beatmaps_lookup_difficulty.ts @@ -0,0 +1,99 @@ +export interface BeatmapsLookupDifficulty { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + accuracy: number + ar: number + bpm: number + convert: boolean + count_circles: number + count_sliders: number + count_spinners: number + cs: number + deleted_at: any + drain: number + hit_length: number + is_scoreable: boolean + last_updated: string + mode_int: number + passcount: number + playcount: number + ranked: number + url: string + checksum: string + beatmapset: Beatmapset + failtimes: Failtimes + max_combo: number +} + +export interface Beatmapset { + artist: string + artist_unicode: string + covers: Covers + creator: string + favourite_count: number + hype: any + id: number + nsfw: boolean + offset: number + play_count: number + preview_url: string + source: string + spotlight: boolean + status: string + title: string + title_unicode: string + track_id?: number + user_id: number + video: boolean + bpm: number + can_be_hyped: boolean + deleted_at: any + discussion_enabled: boolean + discussion_locked: boolean + is_scoreable: boolean + last_updated: string + legacy_thread_url: string + nominations_summary: NominationsSummary + ranked: number + ranked_date?: string + storyboard: boolean + submitted_date: string + tags: string + availability: Availability + ratings: number[] +} + +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} + +export interface NominationsSummary { + current: number + required: number +} + +export interface Availability { + download_disabled: boolean + more_information?: string +} + +export interface Failtimes { + fail: number[] + exit: number[] +} + + + diff --git a/types/v2/beatmaps_lookup_set.ts b/types/v2/beatmaps_lookup_set.ts new file mode 100644 index 00000000..86b5ad43 --- /dev/null +++ b/types/v2/beatmaps_lookup_set.ts @@ -0,0 +1,204 @@ +export interface BeatmapsLookupSet { + error: any + artist?: string + artist_unicode?: string + covers?: Covers + creator?: string + favourite_count?: number + hype: any + id?: number + nsfw?: boolean + offset?: number + play_count?: number + preview_url?: string + source?: string + spotlight?: boolean + status?: string + title?: string + title_unicode?: string + track_id: any + user_id?: number + video?: boolean + bpm?: number + can_be_hyped?: boolean + deleted_at: any + discussion_enabled?: boolean + discussion_locked?: boolean + is_scoreable?: boolean + last_updated?: string + legacy_thread_url?: string + nominations_summary?: NominationsSummary + ranked?: number + ranked_date: any + storyboard?: boolean + submitted_date?: string + tags?: string + availability?: Availability + beatmaps?: Beatmap[] + converts?: Convert[] + current_nominations?: any[] + description?: Description + genre?: Genre + language?: Language + pack_tags?: any[] + ratings?: number[] + recent_favourites?: RecentFavourite[] + related_users?: RelatedUser[] + user?: User +} + +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} + +export interface NominationsSummary { + current: number + required: number +} + +export interface Availability { + download_disabled: boolean + more_information: any +} + +export interface Beatmap { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + accuracy: number + ar: number + bpm: number + convert: boolean + count_circles: number + count_sliders: number + count_spinners: number + cs: number + deleted_at: any + drain: number + hit_length: number + is_scoreable: boolean + last_updated: string + mode_int: number + passcount: number + playcount: number + ranked: number + url: string + checksum: string + failtimes: Failtimes + max_combo: number +} + +export interface Failtimes { + exit: number[] + fail: number[] +} + +export interface Convert { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + accuracy: number + ar: number + bpm: number + convert: boolean + count_circles: number + count_sliders: number + count_spinners: number + cs: number + deleted_at: any + drain: number + hit_length: number + is_scoreable: boolean + last_updated: string + mode_int: number + passcount: number + playcount: number + ranked: number + url: string + checksum: string + failtimes: Failtimes2 +} + +export interface Failtimes2 { + exit: number[] + fail: number[] +} + +export interface Description { + description: string +} + +export interface Genre { + id: number + name: string +} + +export interface Language { + id: number + name: string +} + +export interface RecentFavourite { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour: any + username: string +} + +export interface RelatedUser { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour: any + username: string +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour: any + username: string +} From dbb1d39aaa8eab5c9a611a84fbb5809ef8eb1ca9 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 16 Dec 2023 12:29:53 +0300 Subject: [PATCH 034/259] [endpoint] Beatmap id/set details --- api/v2/beatmaps/details.ts | 51 ++++++ types/v2/beamaps_details_difficulty.ts | 96 +++++++++++ types/v2/beamaps_details_set.ts | 210 +++++++++++++++++++++++++ 3 files changed, 357 insertions(+) create mode 100644 api/v2/beatmaps/details.ts create mode 100644 types/v2/beamaps_details_difficulty.ts create mode 100644 types/v2/beamaps_details_set.ts diff --git a/api/v2/beatmaps/details.ts b/api/v2/beatmaps/details.ts new file mode 100644 index 00000000..f1780949 --- /dev/null +++ b/api/v2/beatmaps/details.ts @@ -0,0 +1,51 @@ +import { BeamapsDetailsDifficulty } from "../../../types/v2/beamaps_details_difficulty"; +import { BeamapsDetailsSet } from "../../../types/v2/beamaps_details_set"; +import { request } from "../../../utility/request"; + + +type params = ({ + type: 'difficulty'; + id: number; +} | { + type: 'set'; + id: number; +}); + + +type Response = + T extends 'difficulty' ? { + type: 'difficulty'; + result: BeamapsDetailsDifficulty + } : T extends 'set' ? { + type: 'set'; + result: BeamapsDetailsSet + } : never; + + +const name = async (obj: T): Promise> => { + const params: any = {}; + let url = 'https://osu.ppy.sh/api/v2'; + let method = 'GET'; + + + switch (obj.type) { + case 'difficulty': + url += `/beatmaps/${obj.id}`; + break; + + case 'set': + url += `/beatmapsets/${obj.id}`; + break; + }; + + + const data = await request(url, { + method: method, + params: params, + }); + + return { type: obj.type, result: data } as Response; +}; + + +export default name; \ No newline at end of file diff --git a/types/v2/beamaps_details_difficulty.ts b/types/v2/beamaps_details_difficulty.ts new file mode 100644 index 00000000..803ab06d --- /dev/null +++ b/types/v2/beamaps_details_difficulty.ts @@ -0,0 +1,96 @@ +export interface BeamapsDetailsDifficulty { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + accuracy: number + ar: number + bpm: number + convert: boolean + count_circles: number + count_sliders: number + count_spinners: number + cs: number + deleted_at: any + drain: number + hit_length: number + is_scoreable: boolean + last_updated: string + mode_int: number + passcount: number + playcount: number + ranked: number + url: string + checksum: string + beatmapset: Beatmapset + failtimes: Failtimes + max_combo: number +} + +export interface Beatmapset { + artist: string + artist_unicode: string + covers: Covers + creator: string + favourite_count: number + hype: any + id: number + nsfw: boolean + offset: number + play_count: number + preview_url: string + source: string + spotlight: boolean + status: string + title: string + title_unicode: string + track_id: any + user_id: number + video: boolean + bpm: number + can_be_hyped: boolean + deleted_at: any + discussion_enabled: boolean + discussion_locked: boolean + is_scoreable: boolean + last_updated: string + legacy_thread_url: string + nominations_summary: NominationsSummary + ranked: number + ranked_date: string + storyboard: boolean + submitted_date: string + tags: string + availability: Availability + ratings: number[] +} + +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} + +export interface NominationsSummary { + current: number + required: number +} + +export interface Availability { + download_disabled: boolean + more_information: any +} + +export interface Failtimes { + fail: number[] + exit: number[] +} diff --git a/types/v2/beamaps_details_set.ts b/types/v2/beamaps_details_set.ts new file mode 100644 index 00000000..312d7446 --- /dev/null +++ b/types/v2/beamaps_details_set.ts @@ -0,0 +1,210 @@ +export interface BeamapsDetailsSet { + artist: string + artist_unicode: string + covers: Covers + creator: string + favourite_count: number + hype: any + id: number + nsfw: boolean + offset: number + play_count: number + preview_url: string + source: string + spotlight: boolean + status: string + title: string + title_unicode: string + track_id?: number + user_id: number + video: boolean + bpm: number + can_be_hyped: boolean + deleted_at: any + discussion_enabled: boolean + discussion_locked: boolean + is_scoreable: boolean + last_updated: string + legacy_thread_url: string + nominations_summary: NominationsSummary + ranked: number + ranked_date?: string + storyboard: boolean + submitted_date: string + tags: string + availability: Availability + beatmaps: Beatmap[] + converts: Convert[] + current_nominations: CurrentNomination[] + description: Description + genre: Genre + language: Language + pack_tags: string[] + ratings: number[] + recent_favourites: RecentFavourite[] + related_users: RelatedUser[] + user: User +} + +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} + +export interface NominationsSummary { + current: number + required: number +} + +export interface Availability { + download_disabled: boolean + more_information?: string +} + +export interface Beatmap { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + accuracy: number + ar: number + bpm: number + convert: boolean + count_circles: number + count_sliders: number + count_spinners: number + cs: number + deleted_at: any + drain: number + hit_length: number + is_scoreable: boolean + last_updated: string + mode_int: number + passcount: number + playcount: number + ranked: number + url: string + checksum: string + failtimes: Failtimes + max_combo: number +} + +export interface Failtimes { + fail: number[] + exit: number[] +} + +export interface Convert { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + accuracy: number + ar: number + bpm: number + convert: boolean + count_circles: number + count_sliders: number + count_spinners: number + cs: number + deleted_at: any + drain: number + hit_length: number + is_scoreable: boolean + last_updated: string + mode_int: number + passcount: number + playcount: number + ranked: number + url: string + checksum: string + failtimes: Failtimes2 +} + +export interface Failtimes2 { + fail: number[] + exit: number[] +} + +export interface CurrentNomination { + beatmapset_id: number + rulesets: string[] + reset: boolean + user_id: number +} + +export interface Description { + description: string +} + +export interface Genre { + id: number + name: string +} + +export interface Language { + id: number + name: string +} + +export interface RecentFavourite { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour: any + username: string +} + +export interface RelatedUser { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour?: string + username: string +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour: any + username: string +} From 7b1c7eb3cd6ed1268b4f92bfc15c1dbd6c6198b0 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 16 Dec 2023 12:30:40 +0300 Subject: [PATCH 035/259] [endpoint] Beatmaps Events --- api/v2/beatmaps/events.ts | 25 ++++++ types/v2/beatmaps_events.ts | 155 ++++++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 api/v2/beatmaps/events.ts create mode 100644 types/v2/beatmaps_events.ts diff --git a/api/v2/beatmaps/events.ts b/api/v2/beatmaps/events.ts new file mode 100644 index 00000000..58752c90 --- /dev/null +++ b/api/v2/beatmaps/events.ts @@ -0,0 +1,25 @@ +import { BeatmapsEvents } from "../../../types/v2/beatmaps_events"; +import { beatmap_events_types } from "../../../types"; +import { request } from "../../../utility/request"; + + + +const name = async (obj: { + user: string | number, + types: (beatmap_events_types)[]; + min_date: string; + max_date: string; +}): Promise => { + let url = 'https://osu.ppy.sh/api/v2/beatmapsets/events'; + + + const data = await request(url, { + method: 'GET', + params: obj, + }); + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/types/v2/beatmaps_events.ts b/types/v2/beatmaps_events.ts new file mode 100644 index 00000000..57e57c5f --- /dev/null +++ b/types/v2/beatmaps_events.ts @@ -0,0 +1,155 @@ +export interface BeatmapsEvents { + events: Event[] + reviewsConfig: ReviewsConfig + users: User2[] +} + +export interface Event { + id: number + type: string + comment?: Comment + created_at: string + user_id?: number + beatmapset: Beatmapset + discussion?: Discussion +} + +export interface Comment { + beatmap_discussion_id?: number + beatmap_discussion_post_id?: number + new_vote?: NewVote + votes?: Vote[] + old?: string + new?: string +} + +export interface NewVote { + user_id: number + score: number +} + +export interface Vote { + user_id: number + score: number +} + +export interface Beatmapset { + artist: string + artist_unicode: string + covers: Covers + creator: string + favourite_count: number + hype?: Hype + id: number + nsfw: boolean + offset: number + play_count: number + preview_url: string + source: string + spotlight: boolean + status: string + title: string + title_unicode: string + track_id: any + user_id: number + video: boolean + user: User +} + +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} + +export interface Hype { + current: number + required: number +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour: any + username: string +} + +export interface Discussion { + id: number + beatmapset_id: number + beatmap_id: number + user_id: number + deleted_by_id: any + message_type: string + parent_id?: number + timestamp?: number + resolved: boolean + can_be_resolved: boolean + can_grant_kudosu: boolean + created_at: string + updated_at: string + deleted_at: any + last_post_at: string + kudosu_denied: boolean + starting_post: StartingPost +} + +export interface StartingPost { + beatmapset_discussion_id: number + created_at: string + deleted_at: any + deleted_by_id: any + id: number + last_editor_id?: number + message: string + system: boolean + updated_at: string + user_id: number +} + +export interface ReviewsConfig { + max_blocks: number +} + +export interface User2 { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour?: string + username: string + groups: Group[] +} + +export interface Group { + colour: string + has_listing: boolean + has_playmodes: boolean + id: number + identifier: string + is_probationary: boolean + name: string + short_name: string + playmodes: string[] +} From 93cd2fe152959b3685f4d0ddad3e9af0176881ab Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 16 Dec 2023 12:31:02 +0300 Subject: [PATCH 036/259] [endpoint] Download beatmaps (10 hosts) --- api/v2/beatmaps/download.ts | 82 +++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 api/v2/beatmaps/download.ts diff --git a/api/v2/beatmaps/download.ts b/api/v2/beatmaps/download.ts new file mode 100644 index 00000000..624b6c0a --- /dev/null +++ b/api/v2/beatmaps/download.ts @@ -0,0 +1,82 @@ +import { download } from "../../../utility/request"; + + +const name = async (obj: { + from: 'osu' | 'beatconnect' | 'chimu' | 'nerinyan' | 'osu_direct_mirror' | 'sayobot' | 'gatari' | 'ripple' | 'akatsuki' | 'catboy', + beatmapset_id: number; + file_path: string; + no_video?: boolean; + progress_track_fn: (from: string, progress: number) => void; +}): Promise => { + let url = ''; + let headers: any = { + accept: 'application/octet-stream', + }; + + const progress_track = (progress: number) => { + obj.progress_track_fn(obj.from, progress); + }; + + switch (obj.from) { + case 'chimu': + url = `https://api.chimu.moe/v1/download/${obj.beatmapset_id}`; + break; + + case 'beatconnect': + url = `https://beatconnect.io/b/${obj.beatmapset_id}/`; + break; + + case 'sayobot': + url = `https://dl.sayobot.cn/beatmaps/download/${obj.no_video ? 'novideo' : 'full'}/${obj.beatmapset_id}`; + break; + + // DOESNT WORK FOR SOME REASON + // case 'nerinyan': + // url = `https://api.nerinyan.moe/d/${obj.beatmapset_id}${obj.no_video ? '?nv=1' : ''}`; + // headers = { + // accept: 'application/x-osu-beatmap-archive' + // }; + // break; + + case 'osu_direct_mirror': + url = `https://api.osu.direct/d/${obj.beatmapset_id}` + break; + + case 'gatari': + url = `https://osu.gatari.pw/d/${obj.beatmapset_id}`; + headers['Referer'] = 'https://osu.gatari.pw/'; + break; + + case 'ripple': + url = `https://storage.ripple.moe/d/${obj.beatmapset_id}`; + headers['Referer'] = 'https://ripple.moe/'; + break; + + case 'akatsuki': + url = `https://akatsuki.gg/d/${obj.beatmapset_id}`; + headers['Referer'] = 'https://akatsuki.gg/'; + break; + + case 'catboy': + url = `https://catboy.best/d/${obj.beatmapset_id}`; + headers['Referer'] = 'https://catboy.best/'; + break; + + case 'osu': + default: + url = `https://osu.ppy.sh/api/v2/beatmapsets/${obj.beatmapset_id}/download${obj.no_video ? '?noVideo=1' : ''}`; + headers['Referer'] = 'https://osu.ppy.sh/'; + break; + }; + + + const data = await download(url, obj.file_path, { + _callback: obj.progress_track_fn != null, + headers, + callback: progress_track, + }); + return data; +}; + + +export default name; \ No newline at end of file From 154a80d246200263c8dfa1bf6f4cf7315ececbb6 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 16 Dec 2023 12:31:17 +0300 Subject: [PATCH 037/259] added endpoints --- api/v2/index.ts | 18 +++++++++++++++++- types/index.ts | 4 ++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/api/v2/index.ts b/api/v2/index.ts index 3b96352d..ef76978a 100644 --- a/api/v2/index.ts +++ b/api/v2/index.ts @@ -60,4 +60,20 @@ export const forums = { import search_all from './search/index'; -export const search = search_all; \ No newline at end of file +export const search = search_all; + + + +import beatmaps_events from "./beatmaps/events"; +import beatmaps_lookup from "./beatmaps/lookup"; +import beatmaps_details from "./beatmaps/details"; +import beatmaps_download from "./beatmaps/download"; + + +export const beatmaps = { + events: beatmaps_events, + lookup: beatmaps_lookup, + details: beatmaps_details, + download: beatmaps_download, +}; + diff --git a/types/index.ts b/types/index.ts index 78d4e9d1..36c56583 100644 --- a/types/index.ts +++ b/types/index.ts @@ -1,7 +1,5 @@ export type Modes_names = 'osu' | 'fruits' | 'mania' | 'taiko'; - - export type ranking_types = 'charts' | 'country' | 'performance' | 'score'; export type country_names = "United States" | "Russian Federation" | "Germany" | "Poland" | "France" | "Japan" | "Canada" | "Brazil" | "United Kingdom" | "Taiwan" | "South Korea" | "China" | "Australia" | "Indonesia" | "Ukraine" | "Philippines" | "Chile" | "Finland" | "Argentina" | "Netherlands" | "Sweden" | "Singapore" | "Mexico" | "Malaysia" | "Spain" | "Italy" | "Hong Kong" | "Thailand" | "Vietnam" | "Norway" | "Czech Republic" | "Turkey" | "Belarus" | "Austria" | "Belgium" | "Portugal" | "Romania" | "Hungary" | "Denmark" | "Lithuania" | "Kazakhstan" | "New Zealand" | "Peru" | "Switzerland" | "Colombia" | "Israel" | "Estonia" | "Bulgaria" | "Slovakia" | "Greece" | "Latvia" | "Venezuela" | "Serbia" | "Ireland" | "Croatia" | "Saudi Arabia" | "Uruguay" | "South Africa" | "United Arab Emirates" | "Slovenia" | "India" | "Ecuador" | "Morocco" | "Costa Rica" | "Moldova" | "Dominican Republic" | "Brunei" | "Egypt" | "Reunion" | "Macau" | "Tunisia" | "Panama" | "Algeria" | "Mongolia" | "Paraguay" | "Kuwait" | "Puerto Rico" | "Georgia" | "Bolivia" | "El Salvador" | "Qatar" | "Guatemala" | "Luxembourg" | "Uzbekistan" | "Kyrgyzstan" | "North Macedonia" | "Cambodia" | "Bosnia and Herzegovina" | "Iceland" | "Jordan" | "Pakistan" | "Trinidad and Tobago" | "Cyprus" | "Honduras" | "Nicaragua" | "Bahrain" | "Maldives" | "Bangladesh" | "French Polynesia" | "Lebanon" | "Nepal" | "Iraq" | "Guam" | "Azerbaijan" | "Albania" | "Malta" | "Myanmar" | "New Caledonia" | "Oman" | "Iran, Islamic Republic of" | "Armenia" | "Guadeloupe" | "Martinique" | "Jamaica" | "Lao People 's Democratic Republic" | "Sri Lanka" | "Palestinian Territory Occupied" | "Mauritius" | "Syrian Arab Republic" | "Montenegro" | "Faroe Islands" | "Jersey" | "French Guiana" | "Northern Mariana Islands" | "Isle of Man" | "Suriname" | "Belize" | "Barbados" | "Aruba" | "Libya" | "Aland Islands" | "Guernsey" | "Madagascar" | "Sudan" | "Liechtenstein" | "Bahamas" | "Kenya" | "Greenland" | "Bermuda" | "Europe" | "Cote D ' Ivoire" | "Guyana" | "Gibraltar" | "Virgin Islands, U.S." | "Andorra" | "Saint Lucia" | "Tajikistan" | "Antigua and Barbuda" | "Senegal" | "Saint Pierre and Miquelon" | "Cook Islands" | "Antarctica" | "Central African Republic" | "Liberia" | "Eritrea"; @@ -15,6 +13,8 @@ export type beatmap_languages = 'Any' | 'English' | 'Chinese' | 'French' | 'Germ export type beatmap_ranks = 'XH' | 'X' | 'SH' | 'S' | 'A' | 'B' | 'C' | 'D'; export type beatmap_extra = 'storyboard' | 'video'; +export type beatmap_events_types = 'nominate' | 'qualify' | 'rank' | 'love' | 'nomination_reset' | 'nomination_reset_received' | 'disqualify' | 'remove_from_loved' | 'kudosu_gain' | 'kudosu_lost' | 'genre_edit' | 'language_edit' | 'nsfw_toggle' | 'offset_edit' | 'issue_resolve' | 'issue_reopen' | 'beatmap_owner_change' | 'kudosu_allow' | 'kudosu_deny' | 'approve' | 'kudosu_recalculate' | 'discussion_delete' | 'discussion_restore' | 'discussion_post_delete' | 'discussion_post_restor' ; + export type auth_scopes = ( 'chat.read' | From e4090f9a1469fc320e174b3140eee3bd9419868f Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 16 Dec 2023 12:31:32 +0300 Subject: [PATCH 038/259] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f0037152..b15177b4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.11", + "version": "3.0.0-beta.12", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", From 43088df5f61c2a035fab18c60d315028ceb5e230 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 17 Dec 2023 11:47:41 +0300 Subject: [PATCH 039/259] fix types --- api/v2/forums/topic/details.ts | 12 ++++++------ package.json | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/api/v2/forums/topic/details.ts b/api/v2/forums/topic/details.ts index 793ad04b..f44ffbab 100644 --- a/api/v2/forums/topic/details.ts +++ b/api/v2/forums/topic/details.ts @@ -3,12 +3,12 @@ import { ForumPostDetails } from '../../../../types/forums_topic_details'; // FIXME: add query params -const name = async (topic_id: number, obj: { - sort: 'id_asc' | 'id_desc', - limit: number, - start: string, - end: string, - cursor_string: string, +const name = async (topic_id: number, obj?: { + sort?: 'id_asc' | 'id_desc', + limit?: number, + start?: string, + end?: string, + cursor_string?: string, }): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/forums/topics/${topic_id}`, { method: 'GET', diff --git a/package.json b/package.json index b15177b4..bec204a5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.12", + "version": "3.0.0-beta.13", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", From 0182c6f4da8e369d5fe1e1d2a38d05f8d29d8680 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 17 Dec 2023 12:05:06 +0300 Subject: [PATCH 040/259] im dumb --- api/v2/search/index.ts | 14 ++++++-------- package.json | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/api/v2/search/index.ts b/api/v2/search/index.ts index 25e50f78..b3a4306f 100644 --- a/api/v2/search/index.ts +++ b/api/v2/search/index.ts @@ -31,13 +31,11 @@ type params = ({ }); type Response = - T extends 'site' ? { - type: 'site', - result: SearchWiki - } : T extends 'beatmaps' ? { - type: 'beatmaps', - result: SearchBeatmaps - } : never; + T extends 'site' + ? SearchWiki + : T extends 'beatmaps' + ? SearchBeatmaps + : never; const name = async (obj: T): Promise> => { @@ -84,7 +82,7 @@ const name = async (obj: T): Promise> => { params: params, }); - return { type: obj.type, result: data } as Response; + return data as Response; }; diff --git a/package.json b/package.json index bec204a5..3671ff43 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.13", + "version": "3.0.0-beta.14", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", From de72428c2aea0b4990b32c03efbaa30738cd3359 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 17 Dec 2023 18:08:05 +0300 Subject: [PATCH 041/259] man --- api/v2/beatmaps/details.ts | 13 +++++-------- api/v2/beatmaps/lookup.ts | 21 +++++++++------------ package.json | 2 +- 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/api/v2/beatmaps/details.ts b/api/v2/beatmaps/details.ts index f1780949..930ba1df 100644 --- a/api/v2/beatmaps/details.ts +++ b/api/v2/beatmaps/details.ts @@ -13,13 +13,10 @@ type params = ({ type Response = - T extends 'difficulty' ? { - type: 'difficulty'; - result: BeamapsDetailsDifficulty - } : T extends 'set' ? { - type: 'set'; - result: BeamapsDetailsSet - } : never; + T extends 'difficulty' + ? BeamapsDetailsDifficulty + : T extends 'set' + ? BeamapsDetailsSet : never; const name = async (obj: T): Promise> => { @@ -44,7 +41,7 @@ const name = async (obj: T): Promise> => { params: params, }); - return { type: obj.type, result: data } as Response; + return data as Response; }; diff --git a/api/v2/beatmaps/lookup.ts b/api/v2/beatmaps/lookup.ts index 5a92a3b6..9839da42 100644 --- a/api/v2/beatmaps/lookup.ts +++ b/api/v2/beatmaps/lookup.ts @@ -23,16 +23,13 @@ type params = ({ type Response = - T extends 'difficulty' ? { - type: 'difficulty'; - result: BeatmapsLookupDifficulty - } : T extends 'set' ? { - type: 'set'; - result: BeatmapsLookupSet - } : T extends 'attributes' ? { - type: 'attributes'; - result: BeatmapsLookupAttributes - } : never; + T extends 'difficulty' + ? BeatmapsLookupDifficulty + : T extends 'set' + ? BeatmapsLookupSet + : T extends 'attributes' + ? BeatmapsLookupAttributes + : never; const name = async (obj: T): Promise> => { @@ -77,9 +74,9 @@ const name = async (obj: T): Promise> => { }); if (obj.type == 'attributes') - return { type: obj.type, result: data.attributes } as Response; + return data.attributes as Response; - return { type: obj.type, result: data } as Response; + return data as Response; }; diff --git a/package.json b/package.json index 3671ff43..f3fd842a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.14", + "version": "3.0.0-beta.15", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", From dcb17f593011fcebda41e5daabece45c2403011f Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 23 Dec 2023 13:26:15 +0300 Subject: [PATCH 042/259] [endpoint] user activity --- api/v2/index.ts | 2 ++ api/v2/user/activity.ts | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 api/v2/user/activity.ts diff --git a/api/v2/index.ts b/api/v2/index.ts index ef76978a..e230b37a 100644 --- a/api/v2/index.ts +++ b/api/v2/index.ts @@ -10,10 +10,12 @@ export const users = { import user_details from "./user/details"; +import user_activity from "./user/activity"; export const user = { details: user_details, + activity: user_activity }; diff --git a/api/v2/user/activity.ts b/api/v2/user/activity.ts new file mode 100644 index 00000000..001c382b --- /dev/null +++ b/api/v2/user/activity.ts @@ -0,0 +1,24 @@ +import { request } from "../../../utility/request"; +import { Modes_names } from "../../../types"; +import { UserDetails } from '../../../types/user_details'; + + + +const name = async ({ user, limit, offset }: { + user: number; + limit: number; + offset: string; +}): Promise => { + let url = `https://osu.ppy.sh/api/v2/users/${user}/recent_activity`; + + + const data = await request(url, { + method: 'GET', + params: { limit, offset }, + }); + + return data; +}; + + +export default name; \ No newline at end of file From 6f3c8aa97ad59819f81b33f940b70d764d37daff Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 23 Dec 2023 13:26:35 +0300 Subject: [PATCH 043/259] fix: Incorrect refresh token --- utility/request.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utility/request.ts b/utility/request.ts index 7ad6df64..ff2c8fec 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -63,7 +63,7 @@ export const request: RequestType = (url, { method, headers, data, params = {} } if (/^application\/json/.test(response.headers['content-type'])) { try { const parse = JSON.parse(data); - if (parse.authentication === 'basic' && auth.cache_tokens.v1 && total_retries < 3) { + if (parse.authentication === 'basic' && total_retries < 3) { await auth.refresh_token(); total_retries++; From 491cdec3cdfafa159f9ee16b36b8e75bdf3b8c42 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 23 Dec 2023 13:26:51 +0300 Subject: [PATCH 044/259] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f3fd842a..45cce095 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.15", + "version": "3.0.0-beta.16", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", From e2d9f69a53e5b4b2ae6c021767b5230d8629e41e Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 25 Dec 2023 11:59:06 +0300 Subject: [PATCH 045/259] grant_type --- package.json | 2 +- utility/auth.ts | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 45cce095..13bc8e73 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.16", + "version": "3.0.0-beta.17", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/utility/auth.ts b/utility/auth.ts index 4b316505..923ac64f 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -201,7 +201,7 @@ export const build_url = ({ client_id, redirect_uri, scopes, state }: { }; -export const authorize = async ({ code, mode, client_id, client_secret, redirect_url }: { +export const authorize = async ({ code, mode, client_id, client_secret, redirect_url, grant_type }: { code: string; mode: Modes_names; @@ -209,6 +209,7 @@ export const authorize = async ({ code, mode, client_id, client_secret, redirect client_secret: string; redirect_url: string; + grant_type?: string; }): Promise => { const { access_token, refresh_token, expires_in } = await request('https://osu.ppy.sh/oauth/token', { method: 'POST', @@ -217,7 +218,7 @@ export const authorize = async ({ code, mode, client_id, client_secret, redirect "Content-Type": "application/json", }, data: JSON.stringify({ - grant_type: 'authorization_code', + grant_type: grant_type || 'authorization_code', client_id: client_id, client_secret: client_secret, redirect_uri: redirect_url, From 91b00347da5b212c366168eceb35b0c8da263b33 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 25 Dec 2023 12:15:58 +0300 Subject: [PATCH 046/259] refresh session --- package.json | 2 +- utility/auth.ts | 41 +++++++++++++++++++++++++++++++++++++---- utility/request.ts | 4 ++-- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 13bc8e73..b016c702 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.17", + "version": "3.0.0-beta.19", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/utility/auth.ts b/utility/auth.ts index 923ac64f..4d4ad0a5 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -201,7 +201,7 @@ export const build_url = ({ client_id, redirect_uri, scopes, state }: { }; -export const authorize = async ({ code, mode, client_id, client_secret, redirect_url, grant_type }: { +export const authorize = async ({ code, mode, client_id, client_secret, redirect_url }: { code: string; mode: Modes_names; @@ -209,7 +209,6 @@ export const authorize = async ({ code, mode, client_id, client_secret, redirect client_secret: string; redirect_url: string; - grant_type?: string; }): Promise => { const { access_token, refresh_token, expires_in } = await request('https://osu.ppy.sh/oauth/token', { method: 'POST', @@ -218,7 +217,7 @@ export const authorize = async ({ code, mode, client_id, client_secret, redirect "Content-Type": "application/json", }, data: JSON.stringify({ - grant_type: grant_type || 'authorization_code', + grant_type: 'authorization_code', client_id: client_id, client_secret: client_secret, redirect_uri: redirect_url, @@ -227,10 +226,44 @@ export const authorize = async ({ code, mode, client_id, client_secret, redirect }); - const user = await request(`https://osu.ppy.sh/api/v2/me/${mode}`, { method: 'GET', params: { v2: access_token } }); + const user = await request(`https://osu.ppy.sh/api/v2/me/${mode}`, { method: 'GET', params: { v2: access_token, nor: true } }); user.access_token = access_token; user.refresh_token = refresh_token; user.expires_in = expires_in; + return user; +}; + + +export const refresh_session = async ({ refresh_token, mode, client_id, client_secret, redirect_url }: { + refresh_token: string; + mode: Modes_names; + + client_id: number | string; + client_secret: string; + + redirect_url: string; +}): Promise => { + const { access_token, refresh_token: refresh_token_new, expires_in } = await request('https://osu.ppy.sh/oauth/token', { + method: 'POST', + headers: { + "Accept": "application/json", + "Content-Type": "application/json", + }, + data: JSON.stringify({ + grant_type: 'refresh_token', + client_id: client_id, + client_secret: client_secret, + redirect_uri: redirect_url, + refresh_token, + }) + }); + + + const user = await request(`https://osu.ppy.sh/api/v2/me/${mode}`, { method: 'GET', params: { v2: access_token, nor: true } }); + user.access_token = access_token; + user.refresh_token = refresh_token_new; + user.expires_in = expires_in; + return user; }; \ No newline at end of file diff --git a/utility/request.ts b/utility/request.ts index ff2c8fec..ece3c722 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -63,7 +63,7 @@ export const request: RequestType = (url, { method, headers, data, params = {} } if (/^application\/json/.test(response.headers['content-type'])) { try { const parse = JSON.parse(data); - if (parse.authentication === 'basic' && total_retries < 3) { + if (parse.authentication === 'basic' && total_retries < 3 && params.nor != true) { await auth.refresh_token(); total_retries++; @@ -116,7 +116,7 @@ export const download = (url: string, dest: string, { _callback, headers = {}, d callback?: Function; }): Promise => { return new Promise((resolve, reject) => { - + const file = fs.createWriteStream(dest, { encoding: 'utf8' }); file.on('error', err => { From e53f29bbd35cb7ffe810a33c290fa8b82f25d6bd Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Thu, 28 Dec 2023 14:17:17 +0300 Subject: [PATCH 047/259] fix auth problem for token only auths --- package.json | 2 +- utility/auth.ts | 2 +- utility/request.ts | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index b016c702..6f56d252 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.19", + "version": "3.0.0-beta.20", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/utility/auth.ts b/utility/auth.ts index 4d4ad0a5..314dd57e 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -90,7 +90,7 @@ export const login = async (params: auth_params) => { }; - throw new Error('Unknown login method'); + return null; }; diff --git a/utility/request.ts b/utility/request.ts index ece3c722..2c4ff193 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -64,7 +64,8 @@ export const request: RequestType = (url, { method, headers, data, params = {} } try { const parse = JSON.parse(data); if (parse.authentication === 'basic' && total_retries < 3 && params.nor != true) { - await auth.refresh_token(); + const refresh = await auth.refresh_token(); + if (refresh == null) return resolve({ authentication: 'basic' }); total_retries++; From b3ecc800fecb63c687a0892fb0c6723851488ac5 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Tue, 30 Jan 2024 13:11:37 +0300 Subject: [PATCH 048/259] 1 --- src/api/v2/routes/beatmap/id/attributes.ts | 61 ---------------------- src/api/v2/routes/beatmap/id/details.ts | 36 ------------- src/api/v2/routes/beatmap/id/lookup.ts | 57 -------------------- src/api/v2/routes/beatmap/set/details.ts | 36 ------------- src/api/v2/routes/beatmap/set/lookup.ts | 38 -------------- 5 files changed, 228 deletions(-) delete mode 100644 src/api/v2/routes/beatmap/id/attributes.ts delete mode 100644 src/api/v2/routes/beatmap/id/details.ts delete mode 100644 src/api/v2/routes/beatmap/id/lookup.ts delete mode 100644 src/api/v2/routes/beatmap/set/details.ts delete mode 100644 src/api/v2/routes/beatmap/set/lookup.ts diff --git a/src/api/v2/routes/beatmap/id/attributes.ts b/src/api/v2/routes/beatmap/id/attributes.ts deleted file mode 100644 index f7074250..00000000 --- a/src/api/v2/routes/beatmap/id/attributes.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { types } from '../../../../../types/v2_beatmap_id_attributes'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); -import { name as mods_name } from '../../../../../utility/mods'; - -export const description: Description = { - auth: 1, - title: __filename, - method: 'POST', - description: 'Return attributes (stars, combo, stats) of beatmap', - params: [ - { - type: 'number', - name: 'beatmap_id', - optional: false, - description: 'Beatmap id', - }, - { - name: 'body', - params: [ - { - type: 'string[] | number', - name: 'mods', - optional: true, - description: 'Array of matching mods [\'HD\', \'DT\']', - }, - { - type: 'string', - name: 'ruleset', - optional: true, - description: `\`\`\`osu\`\`\` or \`\`\`fruits\`\`\` or \`\`\`mania\`\`\` or \`\`\`taiko\`\`\``, - }, - { - type: 'number', - name: 'ruleset_id', - optional: true, - description: `\`\`\`0\`\`\` or \`\`\`1\`\`\` or \`\`\`2\`\`\` or \`\`\`3\`\`\``, - }, - ] - }, - ], -}; - - - -const name: types = async (beatmap_id, body = {}) => { - if (body.mods) body.mods = Array.isArray(body.mods) ? body.mods : mods_name(body.mods).match(/.{1,2}/g); - - const data = await request(`beatmaps/${beatmap_id}/attributes`, { - method: 'POST', - data: JSON.stringify(body), - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/beatmap/id/details.ts b/src/api/v2/routes/beatmap/id/details.ts deleted file mode 100644 index adb9f8da..00000000 --- a/src/api/v2/routes/beatmap/id/details.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { types } from '../../../../../types/v2_beatmap_id_details'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return beatmap data of specified beatmap id', - params: [ - { - type: 'number', - name: 'beatmap', - optional: false, - description: 'id of the beatmap', - }, - ], - return: 'response', -}; - - - -const name: types = async (beatmap) => { - const data = await request(`beatmaps/${beatmap}`, { - method: 'GET', - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/beatmap/id/lookup.ts b/src/api/v2/routes/beatmap/id/lookup.ts deleted file mode 100644 index 2cbbb74d..00000000 --- a/src/api/v2/routes/beatmap/id/lookup.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { types } from '../../../../../types/v2_beatmap_id_lookup'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return data of the specified beatmap id', - params: [ - { - name: 'object', - params: [ - { - type: 'number', - name: 'id', - optional: true, - description: 'id of the beatmap', - }, - { - type: 'string', - name: 'checksum', - optional: true, - description: 'md5 of the beatmap file', - }, - { - type: 'string', - name: 'filename', - optional: true, - description: 'file name of the beatmap', - }, - ], - }, - ], -}; - - - -const name: types = async (object) => { - const data = await request(`beatmaps/lookup`, { - method: 'GET', - params: { - checksum: object.checksum, - filename: object.filename, - id: object.id, - }, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/beatmap/set/details.ts b/src/api/v2/routes/beatmap/set/details.ts deleted file mode 100644 index 3d7465a6..00000000 --- a/src/api/v2/routes/beatmap/set/details.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { types } from '../../../../../types/v2_beatmap_set_details'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return beatmap data of specified beatmap set id', - params: [ - { - type: 'string', - name: 'beatmapset', - optional: false, - description: 'Beatmap set id', - }, - ], - return: 'response', -}; - - - -const name: types = async (beatmapset) => { - const data = await request(`beatmapsets/${beatmapset}`, { - method: 'GET', - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/beatmap/set/lookup.ts b/src/api/v2/routes/beatmap/set/lookup.ts deleted file mode 100644 index f47a4abb..00000000 --- a/src/api/v2/routes/beatmap/set/lookup.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { types } from '../../../../../types/v2_beatmap_set_lookup'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return details about beatmapset for specified beatmap id', - params: [ - { - type: 'number', - name: 'beatmap_id', - optional: false, - description: 'id of the beatmap', - }, - ], -}; - - - -const name: types = async (beatmap_id) => { - const data = await request(`beatmapsets/lookup`, { - method: 'GET', - params: { - beatmap_id: beatmap_id, - }, - }); - - return data; -}; - - -export default name; \ No newline at end of file From 9878062732c832dc267dbccdeb8e4f9053d947fe Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Tue, 30 Jan 2024 13:16:11 +0300 Subject: [PATCH 049/259] fix type --- package.json | 2 +- types/scores_user.ts | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 6f56d252..5a153ccd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.20", + "version": "3.0.0-beta.21", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/types/scores_user.ts b/types/scores_user.ts index 4aec85bc..9a311ba9 100644 --- a/types/scores_user.ts +++ b/types/scores_user.ts @@ -103,12 +103,12 @@ export interface CurrentUserAttributes { } export interface Statistics { - count_100: number; - count_300: number; - count_50: number; - count_geki: number; - count_katu: number; - count_miss: number; + count_100: number | null; + count_300: number | null; + count_50: number | null; + count_geki: number | null; + count_katu: number | null; + count_miss: number | null; } export enum Type { From 9af957f9517d674fc1cb208d71a06ddd78e5e829 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Tue, 30 Jan 2024 19:28:16 +0300 Subject: [PATCH 050/259] lazer changes --- api/v2/scores/details.ts | 8 +- api/v2/scores/user/beatmap.ts | 5 +- api/v2/scores/user/list.ts | 14 +- package.json | 2 +- types/index.ts | 8 +- types/scores_details.ts | 121 +++++++++++------ types/scores_user.ts | 239 +++++++++++++++------------------ types/v2/scores_user_beamap.ts | 169 +++++++++++++++++++++++ utility/auth.ts | 6 +- utility/request.ts | 15 ++- 10 files changed, 390 insertions(+), 197 deletions(-) create mode 100644 types/v2/scores_user_beamap.ts diff --git a/api/v2/scores/details.ts b/api/v2/scores/details.ts index f18530ad..83066512 100644 --- a/api/v2/scores/details.ts +++ b/api/v2/scores/details.ts @@ -4,12 +4,8 @@ import { ScoresDetails } from '../../../types/scores_details'; -const name = async (score_id: number, mode: Modes_names): Promise => { - if (mode == null) - throw new Error('Gamemode name not specified'); - - - const data = await request(`https://osu.ppy.sh/api/v2/scores/${mode}/${score_id}`, { +const name = async (score_id: number): Promise => { + const data = await request(`https://osu.ppy.sh/api/v2/scores/${score_id}`, { method: 'GET', }); diff --git a/api/v2/scores/user/beatmap.ts b/api/v2/scores/user/beatmap.ts index 37438fd8..7bc3a4c3 100644 --- a/api/v2/scores/user/beatmap.ts +++ b/api/v2/scores/user/beatmap.ts @@ -1,9 +1,10 @@ -import { Modes_names } from "../../../../types"; +import { ScoresUserBeatmap } from "../../../../types/v2/scores_user_beamap"; import { request } from "../../../../utility/request"; +import { Modes_names } from "../../../../types"; -const name = async (beatmap_id: number, user_id: number, obj: { mode?: Modes_names, mods?: string[], best_only?: boolean } = {}) => { +const name = async (beatmap_id: number, user_id: number, obj: { mode?: Modes_names, mods?: string[], best_only?: boolean } = {}): Promise => { let url = `https://osu.ppy.sh/api/v2/beatmaps/${beatmap_id}/scores/users/${user_id}`; if (!obj.best_only) url += '/all'; diff --git a/api/v2/scores/user/list.ts b/api/v2/scores/user/list.ts index efdbc4e3..ea37b0d1 100644 --- a/api/v2/scores/user/list.ts +++ b/api/v2/scores/user/list.ts @@ -23,11 +23,15 @@ const name = async (user_id: number, type: 'recent' | 'best' | 'firsts' | 'pinne // check if scores exists. Sometimes there can an error if (Array.isArray(data)) { - const transform: ScoresUser[] = data.map((v, i) => ({ - index: i + 1, - mods_id: mods.id(v.mods.join('')) || 0, - ...v - })); + const transform: ScoresUser[] = data.map((v: ScoresUser, i) => { + const id = v.mods.map(r => r.acronym).filter(r => r != 'CL').join(''); + + return { + index: i + 1, + mods_id: mods.id(id) || 0, + ...v + }; + }); if (object?.mods) return transform.filter(r => (r.mods_id & object.mods) > 0); return transform; diff --git a/package.json b/package.json index 5a153ccd..2c01c4b3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.21", + "version": "3.0.0-beta.22", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/types/index.ts b/types/index.ts index 36c56583..05b98302 100644 --- a/types/index.ts +++ b/types/index.ts @@ -13,7 +13,7 @@ export type beatmap_languages = 'Any' | 'English' | 'Chinese' | 'French' | 'Germ export type beatmap_ranks = 'XH' | 'X' | 'SH' | 'S' | 'A' | 'B' | 'C' | 'D'; export type beatmap_extra = 'storyboard' | 'video'; -export type beatmap_events_types = 'nominate' | 'qualify' | 'rank' | 'love' | 'nomination_reset' | 'nomination_reset_received' | 'disqualify' | 'remove_from_loved' | 'kudosu_gain' | 'kudosu_lost' | 'genre_edit' | 'language_edit' | 'nsfw_toggle' | 'offset_edit' | 'issue_resolve' | 'issue_reopen' | 'beatmap_owner_change' | 'kudosu_allow' | 'kudosu_deny' | 'approve' | 'kudosu_recalculate' | 'discussion_delete' | 'discussion_restore' | 'discussion_post_delete' | 'discussion_post_restor' ; +export type beatmap_events_types = 'nominate' | 'qualify' | 'rank' | 'love' | 'nomination_reset' | 'nomination_reset_received' | 'disqualify' | 'remove_from_loved' | 'kudosu_gain' | 'kudosu_lost' | 'genre_edit' | 'language_edit' | 'nsfw_toggle' | 'offset_edit' | 'issue_resolve' | 'issue_reopen' | 'beatmap_owner_change' | 'kudosu_allow' | 'kudosu_deny' | 'approve' | 'kudosu_recalculate' | 'discussion_delete' | 'discussion_restore' | 'discussion_post_delete' | 'discussion_post_restor'; export type auth_scopes = ( @@ -29,18 +29,18 @@ export type auth_scopes = ( export type auth_params = ({ - method: 'stable v2'; + method: 'v2'; client_id: number | string; client_secret: string; scopes: auth_scopes; } | { - method: 'stable v1'; + method: 'v1'; api_key: string; } | { - method: 'lazer' + method: 'lazer'; login: string; password: string; diff --git a/types/scores_details.ts b/types/scores_details.ts index fa67ea2f..cb43e5e2 100644 --- a/types/scores_details.ts +++ b/types/scores_details.ts @@ -1,26 +1,60 @@ export interface ScoresDetails { - accuracy: number; - best_id: number; - created_at: Date; + ranked: boolean; + maximum_statistics: MaximumStatistics; + mods: Mod[]; + statistics: Statistics; + beatmap_id: number; + best_id: any; id: number; + rank: string; + type: string; + user_id: number; + accuracy: number; + build_id?: number; + ended_at: string; + has_replay: boolean; + legacy_perfect: any; + legacy_score_id?: number; + legacy_total_score: number; max_combo: number; - mode: string; - mode_int: number; - mods: string[]; passed: boolean; - perfect: boolean; pp: number; - rank: string; + ruleset_id: number; + started_at?: string; + total_score: number; replay: boolean; - score: number; - statistics: Statistics; - type: string; - user_id: number; current_user_attributes: CurrentUserAttributes; beatmap: Beatmap; beatmapset: Beatmapset; rank_global: number; - user: User; + user: User2; +} + +export interface MaximumStatistics { + great: number; + legacy_combo_increase?: number; + ignore_hit?: number; + large_tick_hit?: number; + slider_tail_hit?: number; +} + +export interface Mod { + acronym: string; +} + +export interface Statistics { + ok: number; + meh: number; + miss: number; + great: number; + ignore_hit?: number; + ignore_miss?: number; + large_tick_hit?: number; + slider_tail_hit?: number; +} + +export interface CurrentUserAttributes { + pin: any; } export interface Beatmap { @@ -40,11 +74,11 @@ export interface Beatmap { count_sliders: number; count_spinners: number; cs: number; - deleted_at: null; + deleted_at: any; drain: number; hit_length: number; is_scoreable: boolean; - last_updated: Date; + last_updated: string; mode_int: number; passcount: number; playcount: number; @@ -65,24 +99,10 @@ export interface User { is_deleted: boolean; is_online: boolean; is_supporter: boolean; - last_visit: Date; + last_visit?: string; pm_friends_only: boolean; - profile_colour: null; + profile_colour?: string; username: string; - country?: Country; - cover?: Cover; - groups?: any[]; -} - -export interface Country { - code: string; - name: string; -} - -export interface Cover { - custom_url: string; - url: string; - id: string; } export interface Beatmapset { @@ -91,7 +111,7 @@ export interface Beatmapset { covers: Covers; creator: string; favourite_count: number; - hype: null; + hype: any; id: number; nsfw: boolean; offset: number; @@ -102,7 +122,7 @@ export interface Beatmapset { status: string; title: string; title_unicode: string; - track_id: number; + track_id: any; user_id: number; video: boolean; } @@ -118,15 +138,32 @@ export interface Covers { "slimcover@2x": string; } -export interface CurrentUserAttributes { - pin: null; +export interface User2 { + avatar_url: string; + country_code: string; + default_group: string; + id: number; + is_active: boolean; + is_bot: boolean; + is_deleted: boolean; + is_online: boolean; + is_supporter: boolean; + last_visit?: string; + pm_friends_only: boolean; + profile_colour: any; + username: string; + country: Country; + cover: Cover; + groups: any[]; } -export interface Statistics { - count_100: number; - count_300: number; - count_50: number; - count_geki: number; - count_katu: number; - count_miss: number; +export interface Country { + code: string; + name: string; +} + +export interface Cover { + custom_url: string; + url: string; + id: any; } diff --git a/types/scores_user.ts b/types/scores_user.ts index 9a311ba9..dc5f0afd 100644 --- a/types/scores_user.ts +++ b/types/scores_user.ts @@ -1,146 +1,131 @@ export interface ScoresUser { - index: number; - mods_id: number; - accuracy: number; - best_id: number | null; - created_at: Date; - id: number; - max_combo: number; - mode: Mode; - mode_int: number; - mods: string[]; - passed: boolean; - perfect: boolean; - pp: number | null; - rank: string; - replay: boolean; - score: number; - statistics: Statistics; - type: Type; - user_id: number; - current_user_attributes: CurrentUserAttributes; - beatmap: Beatmap; - beatmapset: Beatmapset; - user: User; - weight?: Weight; + index: number + mods_id: number + ranked: boolean + maximum_statistics: MaximumStatistics + mods: Mod[] + statistics: Statistics + beatmap_id: number + best_id: any + id: number + rank: string + type: string + user_id: number + accuracy: number + build_id: any + ended_at: string + has_replay: boolean + legacy_perfect: any + legacy_score_id: number + legacy_total_score: number + max_combo: number + passed: boolean + pp?: number + ruleset_id: number + started_at: any + total_score: number + replay: boolean + current_user_attributes: CurrentUserAttributes + beatmap: Beatmap + beatmapset: Beatmapset + user: User } -export interface Beatmap { - beatmapset_id: number; - difficulty_rating: number; - id: number; - mode: Mode; - status: Status; - total_length: number; - user_id: number; - version: string; - accuracy: number; - ar: number; - bpm: number; - convert: boolean; - count_circles: number; - count_sliders: number; - count_spinners: number; - cs: number; - deleted_at: null; - drain: number; - hit_length: number; - is_scoreable: boolean; - last_updated: Date; - mode_int: number; - passcount: number; - playcount: number; - ranked: number; - url: string; - checksum: string; -} - -export enum Mode { - Osu = "osu", -} - -export enum Status { - Approved = "approved", - Loved = "loved", - Ranked = "ranked", -} - -export interface Beatmapset { - artist: string; - artist_unicode: string; - covers: Covers; - creator: string; - favourite_count: number; - hype: null; - id: number; - nsfw: boolean; - offset: number; - play_count: number; - preview_url: string; - source: string; - spotlight: boolean; - status: Status; - title: string; - title_unicode: string; - track_id: number | null; - user_id: number; - video: boolean; -} - -export interface Covers { - cover: string; - "cover@2x": string; - card: string; - "card@2x": string; - list: string; - "list@2x": string; - slimcover: string; - "slimcover@2x": string; +export interface MaximumStatistics { + great: number + legacy_combo_increase: number } -export interface CurrentUserAttributes { - pin: null; +export interface Mod { + acronym: string } export interface Statistics { - count_100: number | null; - count_300: number | null; - count_50: number | null; - count_geki: number | null; - count_katu: number | null; - count_miss: number | null; + ok?: number + miss?: number + great: number + meh?: number } -export enum Type { - ScoreBestOsu = "score_best_osu", - ScoreOsu = "score_osu", +export interface CurrentUserAttributes { + pin: any } -export interface User { - avatar_url: string; - country_code: CountryCode; - default_group: DefaultGroup; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: Date; - pm_friends_only: boolean; - profile_colour: null; - username: string; +export interface Beatmap { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + accuracy: number + ar: number + bpm: number + convert: boolean + count_circles: number + count_sliders: number + count_spinners: number + cs: number + deleted_at: any + drain: number + hit_length: number + is_scoreable: boolean + last_updated: string + mode_int: number + passcount: number + playcount: number + ranked: number + url: string + checksum: string } -export enum CountryCode { - ID = "ID", +export interface Beatmapset { + artist: string + artist_unicode: string + covers: Covers + creator: string + favourite_count: number + hype: any + id: number + nsfw: boolean + offset: number + play_count: number + preview_url: string + source: string + spotlight: boolean + status: string + title: string + title_unicode: string + track_id?: number + user_id: number + video: boolean } -export enum DefaultGroup { - Default = "default", +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string } -export interface Weight { - percentage: number; - pp: number; +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour: any + username: string } diff --git a/types/v2/scores_user_beamap.ts b/types/v2/scores_user_beamap.ts new file mode 100644 index 00000000..87ca06a6 --- /dev/null +++ b/types/v2/scores_user_beamap.ts @@ -0,0 +1,169 @@ +export interface ScoresUserBeatmap { + ranked: boolean + maximum_statistics: MaximumStatistics + mods: Mod[] + statistics: Statistics + beatmap_id: number + best_id: any + id: number + rank: string + type: string + user_id: number + accuracy: number + build_id?: number + ended_at: string + has_replay: boolean + legacy_perfect: any + legacy_score_id?: number + legacy_total_score: number + max_combo: number + passed: boolean + pp: number + ruleset_id: number + started_at?: string + total_score: number + replay: boolean + current_user_attributes: CurrentUserAttributes + beatmap: Beatmap + beatmapset: Beatmapset + rank_global: number + user: User2 +} + +export interface MaximumStatistics { + great: number + legacy_combo_increase?: number + ignore_hit?: number + large_tick_hit?: number + slider_tail_hit?: number +} + +export interface Mod { + acronym: string +} + +export interface Statistics { + ok: number + meh: number + miss: number + great: number + ignore_hit?: number + ignore_miss?: number + large_tick_hit?: number + slider_tail_hit?: number +} + +export interface CurrentUserAttributes { + pin: any +} + +export interface Beatmap { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + accuracy: number + ar: number + bpm: number + convert: boolean + count_circles: number + count_sliders: number + count_spinners: number + cs: number + deleted_at: any + drain: number + hit_length: number + is_scoreable: boolean + last_updated: string + mode_int: number + passcount: number + playcount: number + ranked: number + url: string + checksum: string + max_combo: number + user: User +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour?: string + username: string +} + +export interface Beatmapset { + artist: string + artist_unicode: string + covers: Covers + creator: string + favourite_count: number + hype: any + id: number + nsfw: boolean + offset: number + play_count: number + preview_url: string + source: string + spotlight: boolean + status: string + title: string + title_unicode: string + track_id: any + user_id: number + video: boolean +} + +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} + +export interface User2 { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour: any + username: string + country: Country + cover: Cover + groups: any[] +} + +export interface Country { + code: string + name: string +} + +export interface Cover { + custom_url: string + url: string + id: any +} diff --git a/utility/auth.ts b/utility/auth.ts index 314dd57e..6a69eb5e 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -7,7 +7,7 @@ import { auth_params, auth_response, auth_scopes, Modes_names } from '../types/i import { UserAuth } from '../types/user_details'; -const credentials: { +export const credentials: { method: any; api_key: string; @@ -50,7 +50,7 @@ export const login = async (params: auth_params) => { credentials.method = params.method; - if (params.method == 'stable v1') { + if (params.method == 'v1') { credentials.api_key = params.api_key; cache_tokens.v1 = params.api_key; @@ -58,7 +58,7 @@ export const login = async (params: auth_params) => { }; - if (params.method == 'stable v2') { + if (params.method == 'v2') { credentials.client_id = params.client_id; credentials.client_secret = params.client_secret; if (params.scopes) credentials.scopes = params.scopes; diff --git a/utility/request.ts b/utility/request.ts index 2c4ff193..ac94ea60 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -39,13 +39,14 @@ export const request: RequestType = (url, { method, headers, data, params = {} } params.k = params.v1 || auth.cache_tokens.v1; // V2 add credentials - if (url.includes('https://osu.ppy.sh/api/v2')) - headers = { - // @ts-ignore - Authorization: `Bearer ${params.v2 || auth.cache_tokens.v2}`, - Accept: `application/json`, - 'Content-Type': `application/json`, - }; + if (url.includes('https://osu.ppy.sh/api/v2')) { + if (!headers) headers = {}; + + headers.Authorization = `Bearer ${params.v2 || auth.cache_tokens.v2}`; + headers.Accept = `application/json`; + headers['Content-Type'] = `application/json`; + headers['x-api-version'] = '20220705'; + }; const generate_query = querystring.encode(params); From 37260591542e2de626d4f3199417aebaab614a10 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Tue, 30 Jan 2024 19:35:18 +0300 Subject: [PATCH 051/259] fix ttypes --- package.json | 2 +- types/scores_details.ts | 45 +++--- types/scores_user.ts | 252 +++++++++++++++++++-------------- types/v2/scores_user_beamap.ts | 206 +++++++-------------------- 4 files changed, 226 insertions(+), 279 deletions(-) diff --git a/package.json b/package.json index 2c01c4b3..8a0166d5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.22", + "version": "3.0.0-beta.23", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/types/scores_details.ts b/types/scores_details.ts index cb43e5e2..1d0749e6 100644 --- a/types/scores_details.ts +++ b/types/scores_details.ts @@ -10,17 +10,17 @@ export interface ScoresDetails { type: string; user_id: number; accuracy: number; - build_id?: number; + build_id: number; ended_at: string; has_replay: boolean; legacy_perfect: any; - legacy_score_id?: number; + legacy_score_id: any; legacy_total_score: number; max_combo: number; passed: boolean; - pp: number; + pp: any; ruleset_id: number; - started_at?: string; + started_at: string; total_score: number; replay: boolean; current_user_attributes: CurrentUserAttributes; @@ -32,25 +32,34 @@ export interface ScoresDetails { export interface MaximumStatistics { great: number; - legacy_combo_increase?: number; - ignore_hit?: number; - large_tick_hit?: number; - slider_tail_hit?: number; + ignore_hit: number; + large_bonus: number; + small_bonus: number; + large_tick_hit: number; } export interface Mod { acronym: string; + settings?: Settings; +} + +export interface Settings { + seed?: number; + angle_sharpness?: number; + drain_rate?: number; + circle_size?: number; + approach_rate?: number; + overall_difficulty?: number; } export interface Statistics { - ok: number; meh: number; miss: number; great: number; - ignore_hit?: number; - ignore_miss?: number; - large_tick_hit?: number; - slider_tail_hit?: number; + ignore_hit: number; + ignore_miss: number; + small_bonus: number; + large_tick_miss: number; } export interface CurrentUserAttributes { @@ -99,9 +108,9 @@ export interface User { is_deleted: boolean; is_online: boolean; is_supporter: boolean; - last_visit?: string; + last_visit: string; pm_friends_only: boolean; - profile_colour?: string; + profile_colour: string; username: string; } @@ -148,7 +157,7 @@ export interface User2 { is_deleted: boolean; is_online: boolean; is_supporter: boolean; - last_visit?: string; + last_visit: string; pm_friends_only: boolean; profile_colour: any; username: string; @@ -163,7 +172,7 @@ export interface Country { } export interface Cover { - custom_url: string; + custom_url: any; url: string; - id: any; + id: string; } diff --git a/types/scores_user.ts b/types/scores_user.ts index dc5f0afd..2537e845 100644 --- a/types/scores_user.ts +++ b/types/scores_user.ts @@ -1,131 +1,173 @@ export interface ScoresUser { - index: number - mods_id: number - ranked: boolean - maximum_statistics: MaximumStatistics - mods: Mod[] - statistics: Statistics - beatmap_id: number - best_id: any - id: number - rank: string - type: string - user_id: number - accuracy: number - build_id: any - ended_at: string - has_replay: boolean - legacy_perfect: any - legacy_score_id: number - legacy_total_score: number - max_combo: number - passed: boolean - pp?: number - ruleset_id: number - started_at: any - total_score: number - replay: boolean - current_user_attributes: CurrentUserAttributes - beatmap: Beatmap - beatmapset: Beatmapset - user: User + index: number; + mods_id: number; + ranked: boolean; + maximum_statistics: MaximumStatistics; + mods: Mod[]; + statistics: Statistics; + beatmap_id: number; + best_id: any; + id: number; + rank: string; + type: string; + user_id: number; + accuracy: number; + build_id?: number; + ended_at: string; + has_replay: boolean; + legacy_perfect: any; + legacy_score_id?: number; + legacy_total_score: number; + max_combo: number; + passed: boolean; + pp?: number; + ruleset_id: number; + started_at?: string; + total_score: number; + replay: boolean; + current_user_attributes: CurrentUserAttributes; + beatmap: Beatmap; + beatmapset: Beatmapset; + user: User; } export interface MaximumStatistics { - great: number - legacy_combo_increase: number + great: number; + legacy_combo_increase?: number; + ignore_hit?: number; + large_bonus?: number; + small_bonus?: number; + large_tick_hit?: number; + small_tick_hit?: number; + slider_tail_hit?: number; } export interface Mod { - acronym: string + acronym: string; + settings?: Settings; +} + +export interface Settings { + speed_change?: number; + retries?: number; + seed?: number; + start_scale?: number; + angle_sharpness?: number; + drain_rate?: number; + circle_size?: number; + approach_rate?: number; + overall_difficulty?: number; + max_depth?: number; + scale?: number; + style?: string; + reflection?: string; + extended_limits?: boolean; + repulsion_strength?: number; + hidden_combo_count?: number; + spin_speed?: number; + final_rate?: number; + initial_rate?: number; + mute_combo_count?: number; + strength?: number; + attraction_strength?: number; + only_fade_approach_circles?: boolean; } export interface Statistics { - ok?: number - miss?: number - great: number - meh?: number + ok?: number; + great?: number; + meh?: number; + miss?: number; + ignore_hit?: number; + ignore_miss?: number; + small_bonus?: number; + large_tick_hit?: number; + large_bonus?: number; + large_tick_miss?: number; + small_tick_hit?: number; + small_tick_miss?: number; + slider_tail_hit?: number; } export interface CurrentUserAttributes { - pin: any + pin: any; } export interface Beatmap { - beatmapset_id: number - difficulty_rating: number - id: number - mode: string - status: string - total_length: number - user_id: number - version: string - accuracy: number - ar: number - bpm: number - convert: boolean - count_circles: number - count_sliders: number - count_spinners: number - cs: number - deleted_at: any - drain: number - hit_length: number - is_scoreable: boolean - last_updated: string - mode_int: number - passcount: number - playcount: number - ranked: number - url: string - checksum: string + beatmapset_id: number; + difficulty_rating: number; + id: number; + mode: string; + status: string; + total_length: number; + user_id: number; + version: string; + accuracy: number; + ar: number; + bpm: number; + convert: boolean; + count_circles: number; + count_sliders: number; + count_spinners: number; + cs: number; + deleted_at: any; + drain: number; + hit_length: number; + is_scoreable: boolean; + last_updated: string; + mode_int: number; + passcount: number; + playcount: number; + ranked: number; + url: string; + checksum: string; } export interface Beatmapset { - artist: string - artist_unicode: string - covers: Covers - creator: string - favourite_count: number - hype: any - id: number - nsfw: boolean - offset: number - play_count: number - preview_url: string - source: string - spotlight: boolean - status: string - title: string - title_unicode: string - track_id?: number - user_id: number - video: boolean + artist: string; + artist_unicode: string; + covers: Covers; + creator: string; + favourite_count: number; + hype: any; + id: number; + nsfw: boolean; + offset: number; + play_count: number; + preview_url: string; + source: string; + spotlight: boolean; + status: string; + title: string; + title_unicode: string; + track_id?: number; + user_id: number; + video: boolean; } export interface Covers { - cover: string - "cover@2x": string - card: string - "card@2x": string - list: string - "list@2x": string - slimcover: string - "slimcover@2x": string + cover: string; + "cover@2x": string; + card: string; + "card@2x": string; + list: string; + "list@2x": string; + slimcover: string; + "slimcover@2x": string; } export interface User { - avatar_url: string - country_code: string - default_group: string - id: number - is_active: boolean - is_bot: boolean - is_deleted: boolean - is_online: boolean - is_supporter: boolean - last_visit: string - pm_friends_only: boolean - profile_colour: any - username: string + avatar_url: string; + country_code: string; + default_group: string; + id: number; + is_active: boolean; + is_bot: boolean; + is_deleted: boolean; + is_online: boolean; + is_supporter: boolean; + last_visit: string; + pm_friends_only: boolean; + profile_colour: any; + username: string; } diff --git a/types/v2/scores_user_beamap.ts b/types/v2/scores_user_beamap.ts index 87ca06a6..1c44ece7 100644 --- a/types/v2/scores_user_beamap.ts +++ b/types/v2/scores_user_beamap.ts @@ -1,169 +1,65 @@ export interface ScoresUserBeatmap { - ranked: boolean - maximum_statistics: MaximumStatistics - mods: Mod[] - statistics: Statistics - beatmap_id: number - best_id: any - id: number - rank: string - type: string - user_id: number - accuracy: number - build_id?: number - ended_at: string - has_replay: boolean - legacy_perfect: any - legacy_score_id?: number - legacy_total_score: number - max_combo: number - passed: boolean - pp: number - ruleset_id: number - started_at?: string - total_score: number - replay: boolean - current_user_attributes: CurrentUserAttributes - beatmap: Beatmap - beatmapset: Beatmapset - rank_global: number - user: User2 + ranked: boolean; + maximum_statistics: MaximumStatistics; + mods: Mod[]; + statistics: Statistics; + beatmap_id: number; + best_id: any; + id: number; + rank: string; + type: string; + user_id: number; + accuracy: number; + build_id?: number; + ended_at: string; + has_replay: boolean; + legacy_perfect: any; + legacy_score_id?: number; + legacy_total_score: number; + max_combo: number; + passed: boolean; + pp?: number; + ruleset_id: number; + started_at?: string; + total_score: number; + replay: boolean; + current_user_attributes: CurrentUserAttributes; } export interface MaximumStatistics { - great: number - legacy_combo_increase?: number - ignore_hit?: number - large_tick_hit?: number - slider_tail_hit?: number + great: number; + legacy_combo_increase?: number; + ignore_hit?: number; + large_bonus?: number; + small_bonus?: number; + large_tick_hit?: number; } export interface Mod { - acronym: string + acronym: string; + settings?: Settings; } -export interface Statistics { - ok: number - meh: number - miss: number - great: number - ignore_hit?: number - ignore_miss?: number - large_tick_hit?: number - slider_tail_hit?: number -} - -export interface CurrentUserAttributes { - pin: any -} - -export interface Beatmap { - beatmapset_id: number - difficulty_rating: number - id: number - mode: string - status: string - total_length: number - user_id: number - version: string - accuracy: number - ar: number - bpm: number - convert: boolean - count_circles: number - count_sliders: number - count_spinners: number - cs: number - deleted_at: any - drain: number - hit_length: number - is_scoreable: boolean - last_updated: string - mode_int: number - passcount: number - playcount: number - ranked: number - url: string - checksum: string - max_combo: number - user: User -} - -export interface User { - avatar_url: string - country_code: string - default_group: string - id: number - is_active: boolean - is_bot: boolean - is_deleted: boolean - is_online: boolean - is_supporter: boolean - last_visit?: string - pm_friends_only: boolean - profile_colour?: string - username: string +export interface Settings { + seed?: number; + angle_sharpness?: number; + drain_rate?: number; + circle_size?: number; + approach_rate?: number; + overall_difficulty?: number; } -export interface Beatmapset { - artist: string - artist_unicode: string - covers: Covers - creator: string - favourite_count: number - hype: any - id: number - nsfw: boolean - offset: number - play_count: number - preview_url: string - source: string - spotlight: boolean - status: string - title: string - title_unicode: string - track_id: any - user_id: number - video: boolean -} - -export interface Covers { - cover: string - "cover@2x": string - card: string - "card@2x": string - list: string - "list@2x": string - slimcover: string - "slimcover@2x": string -} - -export interface User2 { - avatar_url: string - country_code: string - default_group: string - id: number - is_active: boolean - is_bot: boolean - is_deleted: boolean - is_online: boolean - is_supporter: boolean - last_visit?: string - pm_friends_only: boolean - profile_colour: any - username: string - country: Country - cover: Cover - groups: any[] -} - -export interface Country { - code: string - name: string +export interface Statistics { + ok?: number; + great: number; + meh?: number; + miss?: number; + ignore_hit?: number; + ignore_miss?: number; + small_bonus?: number; + large_tick_miss?: number; } -export interface Cover { - custom_url: string - url: string - id: any +export interface CurrentUserAttributes { + pin: any; } From 1de0733093edfd906dde8f8ac747f597856ba8c9 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Tue, 30 Jan 2024 21:18:39 +0300 Subject: [PATCH 052/259] fix types --- api/v2/scores/beatmaps.ts | 6 +++- api/v2/scores/user/beatmap.ts | 9 ++++- api/v2/scores/user/list.ts | 2 +- package.json | 2 +- types/users_events.ts | 66 ++++++++++++++++++++--------------- 5 files changed, 52 insertions(+), 33 deletions(-) diff --git a/api/v2/scores/beatmaps.ts b/api/v2/scores/beatmaps.ts index 5a0576fc..7bea1e67 100644 --- a/api/v2/scores/beatmaps.ts +++ b/api/v2/scores/beatmaps.ts @@ -3,7 +3,11 @@ import { Modes_names } from '../../../types'; -const name = async (beatmap_id: number, obj: { mode: Modes_names, mods: string[], type: 'global' | 'country' | 'friend' }) => { +const name = async (beatmap_id: number, obj?: { + mode?: Modes_names, + mods?: string[], + type?: 'global' | 'country' | 'friend', +}) => { const data = await request(`https://osu.ppy.sh/api/v2/beatmaps/${beatmap_id}/scores`, { method: 'GET', params: obj, diff --git a/api/v2/scores/user/beatmap.ts b/api/v2/scores/user/beatmap.ts index 7bc3a4c3..0325f370 100644 --- a/api/v2/scores/user/beatmap.ts +++ b/api/v2/scores/user/beatmap.ts @@ -4,20 +4,27 @@ import { Modes_names } from "../../../../types"; -const name = async (beatmap_id: number, user_id: number, obj: { mode?: Modes_names, mods?: string[], best_only?: boolean } = {}): Promise => { +const name = async (beatmap_id: number, user_id: number, obj: { + mode?: Modes_names, + mods?: string[], + best_only?: boolean, +} = {}): Promise => { let url = `https://osu.ppy.sh/api/v2/beatmaps/${beatmap_id}/scores/users/${user_id}`; if (!obj.best_only) url += '/all'; + const data = await request(url, { method: 'GET', params: obj, }); + if (obj.best_only == true) { data.score.position = data.position; return [data.score]; }; + if (data.scores) return data.scores return data; }; diff --git a/api/v2/scores/user/list.ts b/api/v2/scores/user/list.ts index ea37b0d1..0eb6c727 100644 --- a/api/v2/scores/user/list.ts +++ b/api/v2/scores/user/list.ts @@ -12,7 +12,7 @@ const name = async (user_id: number, type: 'recent' | 'best' | 'firsts' | 'pinne offset?: number, mods?: number }): Promise => { - if (object.include_fails) + if (object.include_fails != null) // @ts-ignore object.include_fails = object.include_fails == true ? 1 : 0; diff --git a/package.json b/package.json index 8a0166d5..f282211f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.23", + "version": "3.0.0-beta.24", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/types/users_events.ts b/types/users_events.ts index eff8d7f8..4f821d3f 100644 --- a/types/users_events.ts +++ b/types/users_events.ts @@ -1,3 +1,17 @@ +import { Modes_names } from "."; + +export enum ActionType { + Rank = 'rank', + Achievement = 'achievement', + BeatmapsetUpload = 'beatmapsetUpload', + BeatmapsetUpdate = 'beatmapsetUpdate', + UsernameChange = 'usernameChange', + UserSupportFirst = 'userSupportFirst', + UserSupportAgain = 'userSupportAgain', + BeatmapsetRevive = 'beatmapsetRevive', + BeatmapsetApprove = 'beatmapsetApprove', +} + export interface UsersEvents { events: Event[]; cursor: Cursor; @@ -9,17 +23,29 @@ export interface Cursor { } export interface Event { - created_at: Date; - createdAt: Date; + created_at: string; + createdAt: string; id: number; - type: Type; + type: ActionType; scoreRank?: string; rank?: number; - mode?: Mode; + mode?: Modes_names; beatmap?: Beatmap; - user: User; + user?: User; achievement?: Achievement; - beatmapset?: Beatmap; + beatmapset?: Beatmapset; + approval?: string; +} + +export interface Beatmap { + title: string; + url: string; +} + +export interface User { + username: string; + url: string; + previousUsername?: string; } export interface Achievement { @@ -30,29 +56,11 @@ export interface Achievement { ordering: number; slug: string; description: string; - mode: Mode | null; - instructions: null | string; + mode: Modes_names; + instructions: any; } -export enum Mode { - Fruits = "fruits", - Mania = "mania", - Osu = "osu", - Taiko = "taiko", -} - -export interface Beatmap { - title: string; - url: string; -} - -export enum Type { - Achievement = "achievement", - BeatmapsetUpdate = "beatmapsetUpdate", - Rank = "rank", -} - -export interface User { - username: string; - url: string; +export interface Beatmapset { + title: string + url: string } From d04fea7582a44ce9466bbac98330e514d7335bd0 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Tue, 30 Jan 2024 21:28:58 +0300 Subject: [PATCH 053/259] types ... --- package.json | 2 +- types/scores_user.ts | 15 ++++++++++----- utility/request.ts | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index f282211f..62d40818 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.24", + "version": "3.0.0-beta.25", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/types/scores_user.ts b/types/scores_user.ts index 2537e845..5b22184c 100644 --- a/types/scores_user.ts +++ b/types/scores_user.ts @@ -29,17 +29,17 @@ export interface ScoresUser { beatmap: Beatmap; beatmapset: Beatmapset; user: User; + weight?: Weight; } export interface MaximumStatistics { great: number; - legacy_combo_increase?: number; ignore_hit?: number; large_bonus?: number; small_bonus?: number; large_tick_hit?: number; - small_tick_hit?: number; slider_tail_hit?: number; + legacy_combo_increase?: number; } export interface Mod { @@ -75,18 +75,18 @@ export interface Settings { export interface Statistics { ok?: number; - great?: number; meh?: number; miss?: number; + great: number; ignore_hit?: number; ignore_miss?: number; + large_bonus?: number; small_bonus?: number; large_tick_hit?: number; - large_bonus?: number; + slider_tail_hit?: number; large_tick_miss?: number; small_tick_hit?: number; small_tick_miss?: number; - slider_tail_hit?: number; } export interface CurrentUserAttributes { @@ -171,3 +171,8 @@ export interface User { profile_colour: any; username: string; } + +export interface Weight { + percentage: number; + pp: number; +} diff --git a/utility/request.ts b/utility/request.ts index ac94ea60..92e76de0 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -45,7 +45,7 @@ export const request: RequestType = (url, { method, headers, data, params = {} } headers.Authorization = `Bearer ${params.v2 || auth.cache_tokens.v2}`; headers.Accept = `application/json`; headers['Content-Type'] = `application/json`; - headers['x-api-version'] = '20220705'; + headers['x-api-version'] = '20240130'; }; From d3116a978dffdce0ee0ae280a45e39200b432bfe Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 12 Feb 2024 03:20:07 +0300 Subject: [PATCH 054/259] types & mods --- package.json | 2 +- tools/mods.ts | 2 ++ types/scores_user.ts | 52 +++++++++++++++++--------------------------- 3 files changed, 23 insertions(+), 33 deletions(-) diff --git a/package.json b/package.json index 62d40818..0b02d649 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.25", + "version": "3.0.0-beta.26", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/tools/mods.ts b/tools/mods.ts index 20438ca9..ce6bf6a4 100644 --- a/tools/mods.ts +++ b/tools/mods.ts @@ -129,6 +129,8 @@ const id = (mods: string | number): number | undefined => { const values: string[] = Object.keys(num_codes).map((a) => a); for (let i = 0; i < name.length; i++) { const find = values.find((v) => num_codes[v].toLowerCase() === name[i].toLowerCase()); + if (!find) continue; + _mods += parseInt(find); }; diff --git a/types/scores_user.ts b/types/scores_user.ts index 5b22184c..6dffeefb 100644 --- a/types/scores_user.ts +++ b/types/scores_user.ts @@ -33,13 +33,15 @@ export interface ScoresUser { } export interface MaximumStatistics { - great: number; + great?: number; + legacy_combo_increase?: number; + small_tick_hit?: number; + large_tick_hit?: number; + perfect?: number; ignore_hit?: number; large_bonus?: number; small_bonus?: number; - large_tick_hit?: number; slider_tail_hit?: number; - legacy_combo_increase?: number; } export interface Mod { @@ -48,45 +50,26 @@ export interface Mod { } export interface Settings { - speed_change?: number; - retries?: number; - seed?: number; - start_scale?: number; - angle_sharpness?: number; - drain_rate?: number; - circle_size?: number; approach_rate?: number; - overall_difficulty?: number; - max_depth?: number; - scale?: number; - style?: string; - reflection?: string; - extended_limits?: boolean; - repulsion_strength?: number; - hidden_combo_count?: number; - spin_speed?: number; - final_rate?: number; - initial_rate?: number; - mute_combo_count?: number; - strength?: number; - attraction_strength?: number; - only_fade_approach_circles?: boolean; + speed_change?: number; } export interface Statistics { ok?: number; - meh?: number; miss?: number; great: number; + large_bonus?: number; + small_tick_hit?: number; + large_tick_hit?: number; + small_tick_miss?: number; + meh?: number; + good?: number; + perfect?: number; ignore_hit?: number; ignore_miss?: number; - large_bonus?: number; small_bonus?: number; - large_tick_hit?: number; slider_tail_hit?: number; large_tick_miss?: number; - small_tick_hit?: number; - small_tick_miss?: number; } export interface CurrentUserAttributes { @@ -129,7 +112,7 @@ export interface Beatmapset { covers: Covers; creator: string; favourite_count: number; - hype: any; + hype?: Hype; id: number; nsfw: boolean; offset: number; @@ -156,6 +139,11 @@ export interface Covers { "slimcover@2x": string; } +export interface Hype { + current: number; + required: number; +} + export interface User { avatar_url: string; country_code: string; @@ -166,7 +154,7 @@ export interface User { is_deleted: boolean; is_online: boolean; is_supporter: boolean; - last_visit: string; + last_visit?: string; pm_friends_only: boolean; profile_colour: any; username: string; From 895cd340ea846a0c126d14d53e29d4be421638a9 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 24 Feb 2024 13:05:38 +0300 Subject: [PATCH 055/259] more rewrite 1/? --- .../events.ts => beatmap_events_list.ts} | 9 +- api/v2/beatmap_packs_details.ts | 17 ++ api/v2/beatmap_packs_list.ts | 21 +++ api/v2/beatmaps/details.ts | 14 +- api/v2/beatmaps/download.ts | 82 --------- api/v2/beatmaps/lookup.ts | 83 --------- api/v2/beatmaps_download.ts | 165 ++++++++++++++++++ api/v2/beatmaps_lookup.ts | 97 ++++++++++ api/v2/index.ts | 81 --------- api/v2/search.ts | 90 ++++++++++ api/v2/search/index.ts | 89 ---------- api/v2/users/details.ts | 19 -- api/v2/users_list.ts | 21 +++ index.ts | 2 +- routes/v2.ts | 88 ++++++++++ types/index.ts | 14 +- types/v2/beatmaps_lookup_difficulties.ts | 96 ++++++++++ types/v2/beatmaps_packs_details.ts | 74 ++++++++ types/v2/beatmaps_packs_list.ts | 19 ++ utility/request.ts | 128 +++++--------- 20 files changed, 762 insertions(+), 447 deletions(-) rename api/v2/{beatmaps/events.ts => beatmap_events_list.ts} (56%) create mode 100644 api/v2/beatmap_packs_details.ts create mode 100644 api/v2/beatmap_packs_list.ts delete mode 100644 api/v2/beatmaps/download.ts delete mode 100644 api/v2/beatmaps/lookup.ts create mode 100644 api/v2/beatmaps_download.ts create mode 100644 api/v2/beatmaps_lookup.ts delete mode 100644 api/v2/index.ts create mode 100644 api/v2/search.ts delete mode 100644 api/v2/search/index.ts delete mode 100644 api/v2/users/details.ts create mode 100644 api/v2/users_list.ts create mode 100644 routes/v2.ts create mode 100644 types/v2/beatmaps_lookup_difficulties.ts create mode 100644 types/v2/beatmaps_packs_details.ts create mode 100644 types/v2/beatmaps_packs_list.ts diff --git a/api/v2/beatmaps/events.ts b/api/v2/beatmap_events_list.ts similarity index 56% rename from api/v2/beatmaps/events.ts rename to api/v2/beatmap_events_list.ts index 58752c90..4d8f77b9 100644 --- a/api/v2/beatmaps/events.ts +++ b/api/v2/beatmap_events_list.ts @@ -1,6 +1,6 @@ -import { BeatmapsEvents } from "../../../types/v2/beatmaps_events"; -import { beatmap_events_types } from "../../../types"; -import { request } from "../../../utility/request"; +import { BeatmapsEvents } from "../../types/v2/beatmaps_events"; +import { IDefaultParams, beatmap_events_types } from "../../types"; +import { request } from "../../utility/request"; @@ -9,13 +9,14 @@ const name = async (obj: { types: (beatmap_events_types)[]; min_date: string; max_date: string; -}): Promise => { +}, addons: IDefaultParams): Promise => { let url = 'https://osu.ppy.sh/api/v2/beatmapsets/events'; const data = await request(url, { method: 'GET', params: obj, + addons }); return data; diff --git a/api/v2/beatmap_packs_details.ts b/api/v2/beatmap_packs_details.ts new file mode 100644 index 00000000..c21c93ee --- /dev/null +++ b/api/v2/beatmap_packs_details.ts @@ -0,0 +1,17 @@ +import { IDefaultParams } from "../../types"; +import { BeatmapsPacksDetailsResponse } from "../../types/v2/beatmaps_packs_details"; +import { request } from "../../utility/request"; + + + +const name = async (pack_tag: string, addons: IDefaultParams): Promise => { + const data = await request(`https://osu.ppy.sh/api/v2/beatmaps/packs/${pack_tag}`, { + method: 'GET', + addons, + }); + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/beatmap_packs_list.ts b/api/v2/beatmap_packs_list.ts new file mode 100644 index 00000000..075d99a4 --- /dev/null +++ b/api/v2/beatmap_packs_list.ts @@ -0,0 +1,21 @@ +import { IBeatmapPackType, IDefaultParams } from "../../types"; +import { BeatmapsPacksListResponse } from "../../types/v2/beatmaps_packs_list"; +import { request } from "../../utility/request"; + + + +const name = async (params: { + type: IBeatmapPackType; + cursor_string?: string; +}, addons: IDefaultParams): Promise => { + const data = await request(`https://osu.ppy.sh/api/v2/beatmaps/packs`, { + method: 'GET', + params, + addons, + }); + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/beatmaps/details.ts b/api/v2/beatmaps/details.ts index 930ba1df..4acaba08 100644 --- a/api/v2/beatmaps/details.ts +++ b/api/v2/beatmaps/details.ts @@ -1,3 +1,4 @@ +import { IDefaultParams } from "../../../types"; import { BeamapsDetailsDifficulty } from "../../../types/v2/beamaps_details_difficulty"; import { BeamapsDetailsSet } from "../../../types/v2/beamaps_details_set"; import { request } from "../../../utility/request"; @@ -19,26 +20,27 @@ type Response = ? BeamapsDetailsSet : never; -const name = async (obj: T): Promise> => { - const params: any = {}; +const name = async (params: T, addons: IDefaultParams): Promise> => { + const object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; let method = 'GET'; - switch (obj.type) { + switch (params.type) { case 'difficulty': - url += `/beatmaps/${obj.id}`; + url += `/beatmaps/${params.id}`; break; case 'set': - url += `/beatmapsets/${obj.id}`; + url += `/beatmapsets/${params.id}`; break; }; const data = await request(url, { method: method, - params: params, + params: object, + addons }); return data as Response; diff --git a/api/v2/beatmaps/download.ts b/api/v2/beatmaps/download.ts deleted file mode 100644 index 624b6c0a..00000000 --- a/api/v2/beatmaps/download.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { download } from "../../../utility/request"; - - -const name = async (obj: { - from: 'osu' | 'beatconnect' | 'chimu' | 'nerinyan' | 'osu_direct_mirror' | 'sayobot' | 'gatari' | 'ripple' | 'akatsuki' | 'catboy', - beatmapset_id: number; - file_path: string; - no_video?: boolean; - progress_track_fn: (from: string, progress: number) => void; -}): Promise => { - let url = ''; - let headers: any = { - accept: 'application/octet-stream', - }; - - const progress_track = (progress: number) => { - obj.progress_track_fn(obj.from, progress); - }; - - switch (obj.from) { - case 'chimu': - url = `https://api.chimu.moe/v1/download/${obj.beatmapset_id}`; - break; - - case 'beatconnect': - url = `https://beatconnect.io/b/${obj.beatmapset_id}/`; - break; - - case 'sayobot': - url = `https://dl.sayobot.cn/beatmaps/download/${obj.no_video ? 'novideo' : 'full'}/${obj.beatmapset_id}`; - break; - - // DOESNT WORK FOR SOME REASON - // case 'nerinyan': - // url = `https://api.nerinyan.moe/d/${obj.beatmapset_id}${obj.no_video ? '?nv=1' : ''}`; - // headers = { - // accept: 'application/x-osu-beatmap-archive' - // }; - // break; - - case 'osu_direct_mirror': - url = `https://api.osu.direct/d/${obj.beatmapset_id}` - break; - - case 'gatari': - url = `https://osu.gatari.pw/d/${obj.beatmapset_id}`; - headers['Referer'] = 'https://osu.gatari.pw/'; - break; - - case 'ripple': - url = `https://storage.ripple.moe/d/${obj.beatmapset_id}`; - headers['Referer'] = 'https://ripple.moe/'; - break; - - case 'akatsuki': - url = `https://akatsuki.gg/d/${obj.beatmapset_id}`; - headers['Referer'] = 'https://akatsuki.gg/'; - break; - - case 'catboy': - url = `https://catboy.best/d/${obj.beatmapset_id}`; - headers['Referer'] = 'https://catboy.best/'; - break; - - case 'osu': - default: - url = `https://osu.ppy.sh/api/v2/beatmapsets/${obj.beatmapset_id}/download${obj.no_video ? '?noVideo=1' : ''}`; - headers['Referer'] = 'https://osu.ppy.sh/'; - break; - }; - - - const data = await download(url, obj.file_path, { - _callback: obj.progress_track_fn != null, - headers, - callback: progress_track, - }); - return data; -}; - - -export default name; \ No newline at end of file diff --git a/api/v2/beatmaps/lookup.ts b/api/v2/beatmaps/lookup.ts deleted file mode 100644 index 9839da42..00000000 --- a/api/v2/beatmaps/lookup.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { BeatmapsLookupAttributes } from "../../../types/v2/beatmaps_lookup_attributes"; -import { BeatmapsLookupDifficulty } from "../../../types/v2/beatmaps_lookup_difficulty"; -import { BeatmapsLookupSet } from "../../../types/v2/beatmaps_lookup_set"; -import { Modes_enums } from "../../../types/enums"; -import { request } from "../../../utility/request"; -import { Modes_names } from "../../../types"; - - -type params = ({ - type: 'difficulty'; - id: number; - checksum: string; - filename: string; -} | { - type: 'set'; - id: number; -} | { - type: 'attributes'; - id: number; - mods: number; - mode: Modes_names -}); - - -type Response = - T extends 'difficulty' - ? BeatmapsLookupDifficulty - : T extends 'set' - ? BeatmapsLookupSet - : T extends 'attributes' - ? BeatmapsLookupAttributes - : never; - - -const name = async (obj: T): Promise> => { - const params: any = {}; - let url = 'https://osu.ppy.sh/api/v2'; - let method = 'GET'; - - - switch (obj.type) { - case 'difficulty': - url += '/beatmaps/lookup'; - - if (obj.id) params.id = obj.id; - if (obj.checksum) params.checksum = obj.checksum; - if (obj.filename) params.filename = obj.filename; - - break; - - case 'set': - url += '/beatmapsets/lookup'; - - if (obj.id) params.beatmap_id = obj.id; - - break; - - case 'attributes': - url += `/beatmaps/${obj.id}/attributes`; - method = 'POST'; - - if (obj.mods) params.mods = obj.mods; - - if (typeof obj.mode == 'string') params.ruleset = obj.mode; - else if (typeof obj.mode == 'number') params.ruleset_id = Modes_enums[obj.mode]; - - break; - }; - - - const data = await request(url, { - method: method, - params: params, - }); - - if (obj.type == 'attributes') - return data.attributes as Response; - - return data as Response; -}; - - -export default name; \ No newline at end of file diff --git a/api/v2/beatmaps_download.ts b/api/v2/beatmaps_download.ts new file mode 100644 index 00000000..c81bfe20 --- /dev/null +++ b/api/v2/beatmaps_download.ts @@ -0,0 +1,165 @@ +import { IDefaultParams } from "../../types"; +import { download, request } from "../../utility/request"; +import path from "path"; +import fs from "fs"; + + + +type params = ({ + type: 'difficulty'; + + id: number; + host: 'osu' | 'osu_direct_mirror' | 'catboy'; + + file_path: string; + overwrite: boolean; + + progress_track_fn: (host: string, progress: number) => void; +} | { + type: 'set'; + + id: number; + host: 'osu' | 'beatconnect' | 'chimu' | 'nerinyan' | 'osu_direct_mirror' | 'sayobot' | 'gatari' | 'ripple' | 'akatsuki' | 'catboy', + + file_path: string; + no_video?: boolean; + overwrite: boolean; + + progress_track_fn: (host: string, progress: number) => void; +}); + + +const name = (params: T, addons: IDefaultParams): Promise => new Promise((resolve, reject) => { + const { dir } = path.parse(params.file_path); + if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); + + + if (fs.existsSync(params.file_path) && params.overwrite != true) { + return { + type: 'exists', + path: params.file_path, + }; + }; + + + const progress_track = (progress: number) => { + params.progress_track_fn(params.host, progress); + }; + + + let url = ''; + let headers: any = { + accept: 'application/octet-stream', + }; + + + if (params.type == 'set') { + switch (params.host) { + case 'chimu': + url = `https://api.chimu.moe/v1/download/${params.id}`; + break; + + case 'beatconnect': + url = `https://beatconnect.io/b/${params.id}/`; + break; + + case 'sayobot': + url = `https://dl.sayobot.cn/beatmaps/download/${params.no_video ? 'novideo' : 'full'}/${params.id}`; + break; + + // DOESNT WORK FOR SOME REASON + case 'nerinyan': + url = `https://api.nerinyan.moe/d/${params.id}${params.no_video ? '?nv=1' : ''}`; + headers = { + Accept: 'application/x-osu-beatmap-archive' + }; + break; + + case 'osu_direct_mirror': + url = `https://api.osu.direct/d/${params.id}` + break; + + case 'gatari': + url = `https://osu.gatari.pw/d/${params.id}`; + headers['Referer'] = 'https://osu.gatari.pw/'; + break; + + case 'ripple': + url = `https://storage.ripple.moe/d/${params.id}`; + headers['Referer'] = 'https://ripple.moe/'; + break; + + case 'akatsuki': + url = `https://akatsuki.gg/d/${params.id}`; + headers['Referer'] = 'https://akatsuki.gg/'; + break; + + case 'catboy': + url = `https://catboy.best/d/${params.id}`; + headers['Referer'] = 'https://catboy.best/'; + break; + + case 'osu': + default: + url = `https://osu.ppy.sh/api/v2/beatmapsets/${params.id}/download${params.no_video ? '?noVideo=1' : ''}`; + headers['Referer'] = 'https://osu.ppy.sh/'; + break; + }; + + + return download(url, { + _callback: params.progress_track_fn != null, + headers, + addons: addons, + callback: progress_track, + }) + .then((result: any) => { + if (result.error) return resolve(result.error); + + fs.writeFile(params.file_path, result.result, 'utf8', (err) => { + if (err) return reject(err); + + resolve(params.file_path); + }); + }) + .catch(reject); + } else if (params.type == 'difficulty') { + switch (params.host) { + case 'osu_direct_mirror': + url = `https://api.osu.direct/osu/${params.id}?raw=true` + break; + + case 'catboy': + url = `https://catboy.best/osu/${params.id}`; + headers['Referer'] = 'https://catboy.best/'; + break; + + default: + url = `https://osu.ppy.sh/osu/${params.id}`; + break; + }; + + return download(url, { + _callback: params.progress_track_fn != null, + headers, + addons: addons, + callback: progress_track, + }) + // return request(url, { method: "GET" }) + .then((result: any) => { + if (result.error) return resolve(result.error); + + fs.writeFile(params.file_path, result.result, 'utf8', (err) => { + if (err) return reject(err); + + resolve(params.file_path); + }); + }) + .catch(reject); + }; + + return resolve(`Unknown type: ${(params as any).type}`); +}); + + +export default name; \ No newline at end of file diff --git a/api/v2/beatmaps_lookup.ts b/api/v2/beatmaps_lookup.ts new file mode 100644 index 00000000..047eae67 --- /dev/null +++ b/api/v2/beatmaps_lookup.ts @@ -0,0 +1,97 @@ +import { BeatmapsLookupAttributes } from "../../types/v2/beatmaps_lookup_attributes"; +import { BeatmapsLookupDifficulty } from "../../types/v2/beatmaps_lookup_difficulty"; +import { BeatmapsLookupSet } from "../../types/v2/beatmaps_lookup_set"; +import { Modes_enums } from "../../types/enums"; +import { request } from "../../utility/request"; +import { IDefaultParams, Modes_names } from "../../types"; +import { BeatmapsLookupDifficultiesResponse } from "../../types/v2/beatmaps_lookup_difficulties"; + + +type params = ({ + type: 'difficulty'; + id: number; + checksum: string; + filename: string; +} | { + type: 'set'; + id: number; +} | { + type: 'attributes'; + id: number; + mods: number; + mode: Modes_names +} | { + type: 'difficulties'; + ids: number[]; +}); + + +type Response = + T extends 'difficulty' + ? BeatmapsLookupDifficulty + : T extends 'set' + ? BeatmapsLookupSet + : T extends 'attributes' + ? BeatmapsLookupAttributes + : T extends 'difficulties' + ? BeatmapsLookupDifficultiesResponse[] + : never; + + +const name = async (params: T, addons: IDefaultParams): Promise> => { + const object: any = {}; + let url = 'https://osu.ppy.sh/api/v2'; + let method = 'GET'; + + + switch (params.type) { + case 'difficulty': + url += '/beatmaps/lookup'; + + if (params.id) object.id = params.id; + if (params.checksum) object.checksum = params.checksum; + if (params.filename) object.filename = params.filename; + + break; + + case 'set': + url += '/beatmapsets/lookup'; + + if (params.id) object.beatmap_id = params.id; + + break; + + case 'attributes': + url += `/beatmaps/${params.id}/attributes`; + method = 'POST'; + + if (params.mods) object.mods = params.mods; + + if (typeof params.mode == 'string') object.ruleset = params.mode; + else if (typeof params.mode == 'number') object.ruleset_id = Modes_enums[params.mode]; + + break; + + case 'difficulties': + url += `/beatmaps`; + + if (Array.isArray(params.ids)) object['ids[]'] = params.ids; + + break; + }; + + + const data = await request(url, { + method: method, + params: object, + addons, + }); + + + if (params.type == 'attributes') return data.attributes as Response; + if (params.type == 'difficulties') return data.beatmaps as Response; + return data as Response; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/index.ts b/api/v2/index.ts deleted file mode 100644 index e230b37a..00000000 --- a/api/v2/index.ts +++ /dev/null @@ -1,81 +0,0 @@ -import users_details from "./users/details"; -import users_events from "./users/events"; - - -export const users = { - details: users_details, - events: users_events, -}; - - - -import user_details from "./user/details"; -import user_activity from "./user/activity"; - - -export const user = { - details: user_details, - activity: user_activity -}; - - - -import scores_details from "./scores/details"; -import scores_beatmap from "./scores/beatmaps"; -import scores_user_list from "./scores/user/list"; -import scores_user_beatmap from "./scores/user/beatmap"; - -export const scores = { - details: scores_details, - user: { - /** - * @deprecated since 3.0.0. Use ***v2.scores.user.list*** instead - */ - category: scores_user_list, - list: scores_user_list, - beatmap: scores_user_beatmap, - }, - beatmap: scores_beatmap, -}; - - - -import site_ranking_details from "./site/ranking/details"; - -export const site = { - ranking: { - details: site_ranking_details, - }, -}; - - - -import forums_topic_details from './forums/topic/details'; - -export const forums = { - topic: { - details: forums_topic_details - } -}; - - - -import search_all from './search/index'; - -export const search = search_all; - - - -import beatmaps_events from "./beatmaps/events"; -import beatmaps_lookup from "./beatmaps/lookup"; -import beatmaps_details from "./beatmaps/details"; -import beatmaps_download from "./beatmaps/download"; - - -export const beatmaps = { - events: beatmaps_events, - lookup: beatmaps_lookup, - details: beatmaps_details, - download: beatmaps_download, -}; - diff --git a/api/v2/search.ts b/api/v2/search.ts new file mode 100644 index 00000000..0b869ef3 --- /dev/null +++ b/api/v2/search.ts @@ -0,0 +1,90 @@ +import { beatmap_category, beatmap_sorting, beatmap_statuses, Modes_names, beatmap_genres, beatmap_languages, beatmap_ranks, beatmap_extra, IDefaultParams } from "../../types"; +import { Genres_enum, Languages_enum, Modes_enums } from "../../types/enums"; +import { SearchBeatmaps, SearchWiki } from '../../types/v2/search_all'; +import { request } from "../../utility/request"; + + +type params = ({ + type: 'site'; + mode?: 'all' | 'user' | 'wiki_page'; + query?: string; + page?: number; +} | { + _played?: boolean; + _nsfw?: boolean; + + type: 'beatmaps'; + query?: string; + mode?: Modes_names | number; + status?: beatmap_statuses; + category?: (beatmap_category)[]; + + genre?: beatmap_genres | number; + language?: beatmap_languages | number; + + achieved_rank?: (beatmap_ranks)[]; + + extra?: (beatmap_extra)[]; + sort?: beatmap_sorting; + + cursor_string?: string; +}); + +type Response = + T extends 'site' + ? SearchWiki + : T extends 'beatmaps' + ? SearchBeatmaps + : never; + + +const name = async (params: T, addons: IDefaultParams): Promise> => { + const object: any = {}; + let url = 'https://osu.ppy.sh/api/v2'; + + + switch (params.type) { + case 'site': + url += '/search'; + + + object.mode = params.mode; + object.query = params.query; + object.page = params.page; + break; + + case 'beatmaps': + url += '/beatmapsets/search'; + + if (params._played) object.played = params._played ? 'played' : 'unplayed'; + if (params._nsfw) object.nsfw = params._nsfw; + + if (params.query) object.q = params.query; + if (params.mode) object.m = typeof params.mode == 'number' ? params.mode : Modes_enums[params.mode]; + if (params.status) object.s = params.status; + if (params.category) object.c = params.category.join('.'); + + if (params.genre) object.g = typeof params.genre == 'number' ? params.genre : Genres_enum[params.genre]; + if (params.language) object.l = typeof params.language == 'number' ? params.language : Languages_enum[params.language]; + + if (params.achieved_rank) object.r = params.achieved_rank.join('.'); + + if (params.extra) object.e = params.extra.join('.'); + + if (params.sort) object.sort = params.sort; + if (params.cursor_string) object.cursor_string = params.cursor_string; + break; + }; + + + const data = await request(url, { + method: 'GET', + params: object, + addons + }); + + return data as Response; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/search/index.ts b/api/v2/search/index.ts deleted file mode 100644 index b3a4306f..00000000 --- a/api/v2/search/index.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { beatmap_category, beatmap_sorting, beatmap_statuses, Modes_names, beatmap_genres, beatmap_languages, beatmap_ranks, beatmap_extra } from "../../../types"; -import { Genres_enum, Languages_enum, Modes_enums } from "../../../types/enums"; -import { SearchBeatmaps, SearchWiki } from '../../../types/v2/search_all'; -import { request } from "../../../utility/request"; - - -type params = ({ - type: 'site'; - mode?: 'all' | 'user' | 'wiki_page'; - query?: string; - page?: number; -} | { - _played?: boolean; - _nsfw?: boolean; - - type: 'beatmaps'; - query?: string; - mode?: Modes_names | number; - status?: beatmap_statuses; - category?: (beatmap_category)[]; - - genre?: beatmap_genres | number; - language?: beatmap_languages | number; - - achieved_rank?: (beatmap_ranks)[]; - - extra?: (beatmap_extra)[]; - sort?: beatmap_sorting; - - cursor_string?: string; -}); - -type Response = - T extends 'site' - ? SearchWiki - : T extends 'beatmaps' - ? SearchBeatmaps - : never; - - -const name = async (obj: T): Promise> => { - const params: any = {}; - let url = 'https://osu.ppy.sh/api/v2'; - - - switch (obj.type) { - case 'site': - url += '/search'; - - - params.mode = obj.mode; - params.query = obj.query; - params.page = obj.page; - break; - - case 'beatmaps': - url += '/beatmapsets/search'; - - if (obj._played) params.played = obj._played ? 'played' : 'unplayed'; - if (obj._nsfw) params.nsfw = obj._nsfw; - - if (obj.query) params.q = obj.query; - if (obj.mode) params.m = typeof obj.mode == 'number' ? obj.mode : Modes_enums[obj.mode]; - if (obj.status) params.s = obj.status; - if (obj.category) params.c = obj.category.join('.'); - - if (obj.genre) params.g = typeof obj.genre == 'number' ? obj.genre : Genres_enum[obj.genre]; - if (obj.language) params.l = typeof obj.language == 'number' ? obj.language : Languages_enum[obj.language]; - - if (obj.achieved_rank) params.r = obj.achieved_rank.join('.'); - - if (obj.extra) params.e = obj.extra.join('.'); - - if (obj.sort) params.sort = obj.sort; - if (obj.cursor_string) params.cursor_string = obj.cursor_string; - break; - }; - - - const data = await request(url, { - method: 'GET', - params: params, - }); - - return data as Response; -}; - - -export default name; \ No newline at end of file diff --git a/api/v2/users/details.ts b/api/v2/users/details.ts deleted file mode 100644 index 824c695f..00000000 --- a/api/v2/users/details.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { request } from "../../../utility/request"; -import { UsersDetails } from '../../../types/users_details'; - - - -const name = async (ids: number[]): Promise => { - const data = await request(`https://osu.ppy.sh/api/v2/users`, { - method: 'GET', - params: { - 'ids[]': ids - }, - }); - - if (data.users) return data.users; - return data; -}; - - -export default name; \ No newline at end of file diff --git a/api/v2/users_list.ts b/api/v2/users_list.ts new file mode 100644 index 00000000..c8128f5b --- /dev/null +++ b/api/v2/users_list.ts @@ -0,0 +1,21 @@ +import { request } from "../../utility/request"; +import { UsersDetails } from '../../types/users_details'; +import { IDefaultParams } from "../../types"; + + + +const name = async (ids: number[], addons: IDefaultParams): Promise => { + const data = await request(`https://osu.ppy.sh/api/v2/users`, { + method: 'GET', + params: { + 'ids[]': ids + }, + addons + }); + + if (data.users) return data.users; + return data; +}; + + +export default name; \ No newline at end of file diff --git a/index.ts b/index.ts index 54bd5bfe..9465e099 100644 --- a/index.ts +++ b/index.ts @@ -16,4 +16,4 @@ export * as auth from './utility/auth'; export * as Enums from './types/enums'; -export * as v2 from "./api/v2/index"; \ No newline at end of file +export * as v2 from "./routes/v2"; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts new file mode 100644 index 00000000..68c61306 --- /dev/null +++ b/routes/v2.ts @@ -0,0 +1,88 @@ +import users_details from "../api/v2/users_list"; +import users_events from "../api/v2/users/events"; + + +export const users = { + list: users_details, + events: users_events, +}; + + + +import user_details from "../api/v2/user/details"; +import user_activity from "../api/v2/user/activity"; + + +export const user = { + details: user_details, + activity: user_activity +}; + + + +import scores_details from "../api/v2/scores/details"; +import scores_beatmap from "../api/v2/scores/beatmaps"; +import scores_user_list from "../api/v2/scores/user/list"; +import scores_user_beatmap from "../api/v2/scores/user/beatmap"; + +export const scores = { + details: scores_details, + user: { + /** + * @deprecated since 3.0.0. Use ***v2.scores.user.list*** instead + */ + category: scores_user_list, + list: scores_user_list, + beatmap: scores_user_beatmap, + }, + beatmap: scores_beatmap, +}; + + + +import site_ranking_details from "../api/v2/site/ranking/details"; + +export const site = { + ranking: { + details: site_ranking_details, + }, +}; + + + +import forums_topic_details from '../api/v2/forums/topic/details'; + +export const forums = { + topic: { + details: forums_topic_details + } +}; + + + +import search_all from '../api/v2/search'; + +export const search = search_all; + + + +import beatmap_events_list from "../api/v2/beatmap_events_list"; +import beatmaps_lookup from "../api/v2/beatmaps_lookup"; +import beatmaps_details from "../api/v2/beatmaps/details"; +import beatmaps_download from "../api/v2/beatmaps_download"; +import beatmap_packs_list from "../api/v2/beatmap_packs_list"; +import beatmap_packs_details from "../api/v2/beatmap_packs_details"; + + +export const beatmaps = { + packs: { + list: beatmap_packs_list, + details: beatmap_packs_details, + }, + lookup: beatmaps_lookup, + details: beatmaps_details, + events: { + list: beatmap_events_list, + }, + download: beatmaps_download, +}; \ No newline at end of file diff --git a/types/index.ts b/types/index.ts index 05b98302..8fee6e64 100644 --- a/types/index.ts +++ b/types/index.ts @@ -1,3 +1,13 @@ +export type IDefaultParams = { + legacy_only?: boolean; + apiVersion?: '20240130' | ''; + /** + * Only use it if you want to use user authKey to perform requests on their behave + */ + authKey?: string; +}; + + export type Modes_names = 'osu' | 'fruits' | 'mania' | 'taiko'; export type ranking_types = 'charts' | 'country' | 'performance' | 'score'; @@ -60,4 +70,6 @@ export type auth_params = ({ export type auth_response = { access_token: string; expires_in: number; -}; \ No newline at end of file +}; + +export type IBeatmapPackType = 'standard' | 'featured' | 'tournament' | 'loved' | 'chart' | 'theme' | 'artist'; \ No newline at end of file diff --git a/types/v2/beatmaps_lookup_difficulties.ts b/types/v2/beatmaps_lookup_difficulties.ts new file mode 100644 index 00000000..d30d08ff --- /dev/null +++ b/types/v2/beatmaps_lookup_difficulties.ts @@ -0,0 +1,96 @@ +export interface BeatmapsLookupDifficultiesResponse { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + accuracy: number + ar: number + bpm: number + convert: boolean + count_circles: number + count_sliders: number + count_spinners: number + cs: number + deleted_at: any + drain: number + hit_length: number + is_scoreable: boolean + last_updated: string + mode_int: number + passcount: number + playcount: number + ranked: number + url: string + checksum: string + beatmapset: Beatmapset + failtimes: Failtimes + max_combo: number +} + +export interface Beatmapset { + artist: string + artist_unicode: string + covers: Covers + creator: string + favourite_count: number + hype: any + id: number + nsfw: boolean + offset: number + play_count: number + preview_url: string + source: string + spotlight: boolean + status: string + title: string + title_unicode: string + track_id: number + user_id: number + video: boolean + bpm: number + can_be_hyped: boolean + deleted_at: any + discussion_enabled: boolean + discussion_locked: boolean + is_scoreable: boolean + last_updated: string + legacy_thread_url: string + nominations_summary: NominationsSummary + ranked: number + ranked_date: string + storyboard: boolean + submitted_date: string + tags: string + availability: Availability + ratings: number[] +} + +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} + +export interface NominationsSummary { + current: number + required: number +} + +export interface Availability { + download_disabled: boolean + more_information: any +} + +export interface Failtimes { + fail: number[] + exit: number[] +} diff --git a/types/v2/beatmaps_packs_details.ts b/types/v2/beatmaps_packs_details.ts new file mode 100644 index 00000000..7d6789a2 --- /dev/null +++ b/types/v2/beatmaps_packs_details.ts @@ -0,0 +1,74 @@ +export interface BeatmapsPacksDetailsResponse { + author: string + date: string + name: string + no_diff_reduction: boolean + ruleset_id: any + tag: string + url: string + beatmapsets: Beatmapset[] + user_completion_data: UserCompletionData +} + +export interface Beatmapset { + artist: string + artist_unicode: string + covers: Covers + creator: string + favourite_count: number + hype: any + id: number + nsfw: boolean + offset: number + play_count: number + preview_url: string + source: string + spotlight: boolean + status: string + title: string + title_unicode: string + track_id?: number + user_id: number + video: boolean + bpm: number + can_be_hyped: boolean + deleted_at: any + discussion_enabled: boolean + discussion_locked: boolean + is_scoreable: boolean + last_updated: string + legacy_thread_url: string + nominations_summary: NominationsSummary + ranked: number + ranked_date: string + storyboard: boolean + submitted_date: string + tags: string + availability: Availability +} + +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} + +export interface NominationsSummary { + current: number + required: number +} + +export interface Availability { + download_disabled: boolean + more_information: any +} + +export interface UserCompletionData { + completed: boolean + beatmapset_ids: any[] +} diff --git a/types/v2/beatmaps_packs_list.ts b/types/v2/beatmaps_packs_list.ts new file mode 100644 index 00000000..5b33c6f9 --- /dev/null +++ b/types/v2/beatmaps_packs_list.ts @@ -0,0 +1,19 @@ +export interface BeatmapsPacksListResponse { + beatmap_packs: BeatmapPack[] + cursor: Cursor + cursor_string: string +} + +export interface BeatmapPack { + author: string + date: string + name: string + no_diff_reduction: boolean + ruleset_id: any + tag: string + url: string +} + +export interface Cursor { + pack_id: number +} diff --git a/utility/request.ts b/utility/request.ts index 92e76de0..59ef4b33 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -1,11 +1,11 @@ // PACKAGES -import querystring from 'node:querystring'; +import querystring from 'querystring'; import https from 'https'; -import fs from "fs"; // CREDENTIALS import * as auth from "./auth"; +import { IDefaultParams } from '../types'; // TYPES @@ -15,6 +15,7 @@ export interface RequestType { data?: string, headers?: { [key: string]: string }, params?: { [key: string]: any }; + addons?: IDefaultParams; }): Promise; }; @@ -25,7 +26,7 @@ let total_retries = 0; -export const request: RequestType = (url, { method, headers, data, params = {} }): Promise => new Promise((resolve, reject) => { +export const request: RequestType = (url, { method, headers, data, params = {}, addons = {} }): Promise => new Promise((resolve, reject) => { // check required args if (url == null) throw new Error('URL not specified'); @@ -42,13 +43,17 @@ export const request: RequestType = (url, { method, headers, data, params = {} } if (url.includes('https://osu.ppy.sh/api/v2')) { if (!headers) headers = {}; - headers.Authorization = `Bearer ${params.v2 || auth.cache_tokens.v2}`; + headers.Authorization = `Bearer ${addons.authKey || auth.cache_tokens.v2}`; headers.Accept = `application/json`; headers['Content-Type'] = `application/json`; - headers['x-api-version'] = '20240130'; + headers['x-api-version'] = addons.apiVersion == '' ? null : addons.apiVersion || '20240130'; }; + if (addons.legacy_only != null) + params.legacy_only = params.legacy_only == true ? 1 : 0; + + const generate_query = querystring.encode(params); const build_url = url + (generate_query ? `?${generate_query}` : ''); @@ -110,32 +115,17 @@ export const request: RequestType = (url, { method, headers, data, params = {} } * @param {string} dest The file destination * @returns {Promise} The response */ -export const download = (url: string, dest: string, { _callback, headers = {}, data, params, callback }: { +export const download = (url: string, { _callback, headers = {}, data, params, addons, callback }: { _callback: boolean; headers?: { [key: string]: string }, data?: string; params?: any; + addons?: IDefaultParams; callback?: Function; }): Promise => { return new Promise((resolve, reject) => { - - const file = fs.createWriteStream(dest, { encoding: 'utf8' }); - - file.on('error', err => { - fs.unlinkSync(dest); - reject(err); - }); - - file.on('finish', () => { - file.close(); - resolve(dest); - }); - - - if (url.includes('https://osu.ppy.sh/api/v2')) headers['Authorization'] = `Bearer ${params?.v2 || auth.cache_tokens.v2}`; - - if (!headers['accept']) headers['accept'] = `application/octet-stream`; - // if (!headers['content-type']) headers['content-type'] = `application/octet-stream`; + if (url.includes('https://osu.ppy.sh/api/v2')) + headers['Authorization'] = `Bearer ${addons?.authKey || auth.cache_tokens.v2}`; const generate_query = querystring.encode(params); @@ -144,82 +134,58 @@ export const download = (url: string, dest: string, { _callback, headers = {}, d // console.log({ url: build_url, method, headers, data }); const req = https.request(build_url, { method: 'GET', headers }, response => { const { location } = response.headers; - if (location) { - download(location, dest, { _callback, headers, data, params, callback }) + download(location, { _callback, headers, data, params, callback }) .then(resolve) .catch(reject); return; - } + }; - if (response.statusCode === 404) { - resolve({ error: 'file unavailable' }); + if (response.statusCode != 200) { + resolve({ + error: 'file unavailable' + }); return; - } + }; - if (_callback == true && callback !== undefined) { - const totalLength = parseInt(response.headers['content-length']); - let progress = 0; - let progressBar = 0; + let chunk_data = ''; + let progress = 0; + let progressBar = 0; + + + try { + const totalLength = parseInt(response.headers['content-length']); - response.on('data', (chunk) => { - progress += chunk.length; - progressBar = 100 * (progress / totalLength); - callback(progressBar); + response.on('data', function (chunk) { + chunk_data += chunk; + if (_callback == true && callback !== undefined) { + progress += chunk.length; + progressBar = 100 * (progress / totalLength); + callback(progressBar); + }; }); - } - response.pipe(file); + + response.on('end', function () { + resolve({ result: chunk_data }); + }); + } catch (error) { + reject(error); + }; }); + req.setTimeout(TIMEOUT_MS, () => { req.destroy(); reject(new Error(`Request to ${url} time out after ${TIMEOUT_MS}ms`)); }); + if (data) { req.write(data); - } + }; + req.end(); }); -}; - - -// export const download = (url: string, destination: string, { headers, data, params }: { -// headers?: { [key: string]: string }, -// data?: string; -// params?: any -// }) => { -// if (url.includes('https://osu.ppy.sh/api/v2')) headers['Authorization'] = `Bearer ${params?.v2 || auth.cache_tokens.v2}`; - -// if (!headers['accept']) headers['accept'] = `application/octet-stream`; -// if (!headers['content-Type']) headers['content-Type'] = `application/octet-stream`; - - -// return request(url, { method: 'GET', data, headers, params }) -// .then((response: Buffer) => { -// if (!(response instanceof Buffer)) { -// throw new Error('Invalid response format. Expected binary data.'); -// } -// fs.writeFileSync(destination, response); -// }) -// .catch((error: Error) => { -// // Handle errors, such as network issues or failed requests -// console.error('Error downloading file:', error.message); -// throw error; -// }); -// }; - -// export const download = (url: string, destination: string, { headers, data, params }: { -// headers?: { [key: string]: string }, -// data?: string; -// params: any -// }) => new Promise((resolve, reject) => { -// const file = fs.createWriteStream(dest, { encoding: 'utf8' }); - - - -// request(url, { method: 'GET', data, headers, params }) -// .t -// }); \ No newline at end of file +}; \ No newline at end of file From e2336695b26365698218fa180f90688aa7c1c1e4 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 24 Feb 2024 13:16:47 +0300 Subject: [PATCH 056/259] more 2/? --- .../details.ts => beatmaps_details.ts} | 8 +- api/v2/beatmaps_discussions_list.ts | 28 +++ routes/v2.ts | 8 +- types/v2/beatmaps_discussions_list.ts | 174 ++++++++++++++++++ 4 files changed, 213 insertions(+), 5 deletions(-) rename api/v2/{beatmaps/details.ts => beatmaps_details.ts} (74%) create mode 100644 api/v2/beatmaps_discussions_list.ts create mode 100644 types/v2/beatmaps_discussions_list.ts diff --git a/api/v2/beatmaps/details.ts b/api/v2/beatmaps_details.ts similarity index 74% rename from api/v2/beatmaps/details.ts rename to api/v2/beatmaps_details.ts index 4acaba08..5ba8024b 100644 --- a/api/v2/beatmaps/details.ts +++ b/api/v2/beatmaps_details.ts @@ -1,7 +1,7 @@ -import { IDefaultParams } from "../../../types"; -import { BeamapsDetailsDifficulty } from "../../../types/v2/beamaps_details_difficulty"; -import { BeamapsDetailsSet } from "../../../types/v2/beamaps_details_set"; -import { request } from "../../../utility/request"; +import { IDefaultParams } from "../../types"; +import { BeamapsDetailsDifficulty } from "../../types/v2/beamaps_details_difficulty"; +import { BeamapsDetailsSet } from "../../types/v2/beamaps_details_set"; +import { request } from "../../utility/request"; type params = ({ diff --git a/api/v2/beatmaps_discussions_list.ts b/api/v2/beatmaps_discussions_list.ts new file mode 100644 index 00000000..fe40e0dc --- /dev/null +++ b/api/v2/beatmaps_discussions_list.ts @@ -0,0 +1,28 @@ +import { IDefaultParams } from "../../types"; +import { BeatmapsDiscussionsListResponse } from "../../types/v2/beatmaps_discussions_list"; +import { request } from "../../utility/request"; + + + +const name = async (params: { + only_unresolved?: boolean; + user?: number; + beatmap_id?: number; + beatmapset_id?: number; + beatmapset_status?: 'all' | 'ranked' | 'qualified' | 'disqualified' | 'never_qualified' | 'loved'; + message_types?: ('suggestion' | 'problem' | 'mapper_note' | 'praise' | 'hype' | 'review' | 'all')[]; + limit?: number; + sort?: 'id_desc' | 'id_asc'; + cursor_string?: string; +}, addons: IDefaultParams): Promise => { + const data = await request(`https://osu.ppy.sh/api/v2/beatmapsets/discussions`, { + method: 'GET', + params, + addons + }); + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 68c61306..ab313237 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -68,10 +68,11 @@ export const search = search_all; import beatmap_events_list from "../api/v2/beatmap_events_list"; import beatmaps_lookup from "../api/v2/beatmaps_lookup"; -import beatmaps_details from "../api/v2/beatmaps/details"; +import beatmaps_details from "../api/v2/beatmaps_details"; import beatmaps_download from "../api/v2/beatmaps_download"; import beatmap_packs_list from "../api/v2/beatmap_packs_list"; import beatmap_packs_details from "../api/v2/beatmap_packs_details"; +import beatmaps_discussions_list from "../api/v2/beatmaps_discussions_list"; export const beatmaps = { @@ -85,4 +86,9 @@ export const beatmaps = { list: beatmap_events_list, }, download: beatmaps_download, + discussions: { + list: beatmaps_discussions_list, + // posts: , + // votes: , + } }; \ No newline at end of file diff --git a/types/v2/beatmaps_discussions_list.ts b/types/v2/beatmaps_discussions_list.ts new file mode 100644 index 00000000..0e4b075e --- /dev/null +++ b/types/v2/beatmaps_discussions_list.ts @@ -0,0 +1,174 @@ +export interface BeatmapsDiscussionsListResponse { + beatmaps: Beatmap[] + beatmapsets: Beatmapset[] + discussions: Discussion[] + included_discussions: any[] + reviews_config: ReviewsConfig + users: User[] + cursor?: Cursor + cursor_string?: string +} + +export interface Beatmap { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + accuracy: number + ar: number + bpm: number + convert: boolean + count_circles: number + count_sliders: number + count_spinners: number + cs: number + deleted_at?: string + drain: number + hit_length: number + is_scoreable: boolean + last_updated: string + mode_int: number + passcount: number + playcount: number + ranked: number + url: string + checksum?: string +} + +export interface Beatmapset { + artist: string + artist_unicode: string + covers: Covers + creator: string + favourite_count: number + hype?: Hype + id: number + nsfw: boolean + offset: number + play_count: number + preview_url: string + source: string + spotlight: boolean + status: string + title: string + title_unicode: string + track_id: any + user_id: number + video: boolean + bpm: number + can_be_hyped: boolean + deleted_at: any + discussion_enabled: boolean + discussion_locked: boolean + is_scoreable: boolean + last_updated: string + legacy_thread_url: string + nominations_summary: NominationsSummary + ranked: number + ranked_date?: string + storyboard: boolean + submitted_date: string + tags: string + availability: Availability +} + +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} + +export interface Hype { + current: number + required: number +} + +export interface NominationsSummary { + current: number + required: number +} + +export interface Availability { + download_disabled: boolean + more_information: any +} + +export interface Discussion { + id: number + beatmapset_id: number + beatmap_id?: number + user_id: number + deleted_by_id: any + message_type: string + parent_id: any + timestamp?: number + resolved: boolean + can_be_resolved: boolean + can_grant_kudosu: boolean + created_at: string + updated_at: string + deleted_at: any + last_post_at: string + kudosu_denied: boolean + starting_post: StartingPost +} + +export interface StartingPost { + beatmapset_discussion_id: number + created_at: string + deleted_at: any + deleted_by_id: any + id: number + last_editor_id?: number + message: string + system: boolean + updated_at: string + user_id: number +} + +export interface ReviewsConfig { + max_blocks: number +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour?: string + username: string + groups: Group[] +} + +export interface Group { + colour?: string + has_listing: boolean + has_playmodes: boolean + id: number + identifier: string + is_probationary: boolean + name: string + short_name: string + playmodes?: string[] +} + +export interface Cursor { + page: number + limit: number +} From 943e6c347432c13804d99150174fca71ede83df6 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 24 Feb 2024 19:56:59 +0300 Subject: [PATCH 057/259] more 3/? --- api/v2/beatmaps_discussions_posts.ts | 39 ++++++++++++++++++++++++++++ api/v2/beatmaps_discussions_votes.ts | 35 +++++++++++++++++++++++++ routes/v2.ts | 6 +++-- 3 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 api/v2/beatmaps_discussions_posts.ts create mode 100644 api/v2/beatmaps_discussions_votes.ts diff --git a/api/v2/beatmaps_discussions_posts.ts b/api/v2/beatmaps_discussions_posts.ts new file mode 100644 index 00000000..989b7d5c --- /dev/null +++ b/api/v2/beatmaps_discussions_posts.ts @@ -0,0 +1,39 @@ +import { IDefaultParams } from "../../types"; +import { BeatmapsDiscussionsListResponse } from "../../types/v2/beatmaps_discussions_list"; +import { request } from "../../utility/request"; + + + +const name = async (params: { + discussion_id: number; + sort: 'id_desc' | 'id_asc'; + types: ('first' | 'reply' | 'system')[]; + user: number; + + limit: number; + cursor_string?: string; +}, addons: IDefaultParams): Promise => { + if (params.discussion_id) { + // @ts-ignore + params.beatmapset_discussion_id = params.discussion_id; + delete params.discussion_id; + }; + + if (Array.isArray(params.types)) { + // @ts-ignore + params['types[]'] = params.types; + delete params.types; + }; + + + const data = await request(`https://osu.ppy.sh/api/v2/beatmapsets/discussions/posts`, { + method: 'GET', + params, + addons + }); + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/beatmaps_discussions_votes.ts b/api/v2/beatmaps_discussions_votes.ts new file mode 100644 index 00000000..148c7b21 --- /dev/null +++ b/api/v2/beatmaps_discussions_votes.ts @@ -0,0 +1,35 @@ +import { IDefaultParams } from "../../types"; +import { BeatmapsDiscussionsListResponse } from "../../types/v2/beatmaps_discussions_list"; +import { request } from "../../utility/request"; + + + +const name = async (params: { + discussion_id: number; + sort: 'id_desc' | 'id_asc'; + score: '1' | '-1'; + + user: number; + receiver: number; + + limit: number; + cursor_string?: string; +}, addons: IDefaultParams): Promise => { + if (params.discussion_id) { + // @ts-ignore + params.beatmapset_discussion_id = params.discussion_id; + delete params.discussion_id; + }; + + + const data = await request(`https://osu.ppy.sh/api/v2/beatmapsets/discussions/votes`, { + method: 'GET', + params, + addons + }); + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index ab313237..eae7c7aa 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -73,6 +73,8 @@ import beatmaps_download from "../api/v2/beatmaps_download"; import beatmap_packs_list from "../api/v2/beatmap_packs_list"; import beatmap_packs_details from "../api/v2/beatmap_packs_details"; import beatmaps_discussions_list from "../api/v2/beatmaps_discussions_list"; +import beatmaps_discussions_posts from "../api/v2/beatmaps_discussions_posts"; +import beatmaps_discussions_votes from "../api/v2/beatmaps_discussions_votes"; export const beatmaps = { @@ -88,7 +90,7 @@ export const beatmaps = { download: beatmaps_download, discussions: { list: beatmaps_discussions_list, - // posts: , - // votes: , + posts: beatmaps_discussions_posts, + votes: beatmaps_discussions_votes, } }; \ No newline at end of file From 39f77647a171031e4edbe920045c9cdc91e8af9e Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 24 Feb 2024 20:39:49 +0300 Subject: [PATCH 058/259] more 4/? --- api/v2/beatmaps_discussions_posts.ts | 10 ++-- api/v2/beatmaps_discussions_votes.ts | 12 ++--- api/v2/changelogs_details.ts | 20 ++++++++ api/v2/changelogs_list.ts | 73 ++++++++++++++++++++++++++ routes/v2.ts | 77 ++++++++++++++++------------ 5 files changed, 149 insertions(+), 43 deletions(-) create mode 100644 api/v2/changelogs_details.ts create mode 100644 api/v2/changelogs_list.ts diff --git a/api/v2/beatmaps_discussions_posts.ts b/api/v2/beatmaps_discussions_posts.ts index 989b7d5c..c087ae2b 100644 --- a/api/v2/beatmaps_discussions_posts.ts +++ b/api/v2/beatmaps_discussions_posts.ts @@ -5,12 +5,12 @@ import { request } from "../../utility/request"; const name = async (params: { - discussion_id: number; - sort: 'id_desc' | 'id_asc'; - types: ('first' | 'reply' | 'system')[]; - user: number; + discussion_id?: number; + sort?: 'id_desc' | 'id_asc'; + types?: ('first' | 'reply' | 'system')[]; + user?: number; - limit: number; + limit?: number; cursor_string?: string; }, addons: IDefaultParams): Promise => { if (params.discussion_id) { diff --git a/api/v2/beatmaps_discussions_votes.ts b/api/v2/beatmaps_discussions_votes.ts index 148c7b21..05d04c93 100644 --- a/api/v2/beatmaps_discussions_votes.ts +++ b/api/v2/beatmaps_discussions_votes.ts @@ -5,14 +5,14 @@ import { request } from "../../utility/request"; const name = async (params: { - discussion_id: number; - sort: 'id_desc' | 'id_asc'; - score: '1' | '-1'; + discussion_id?: number; + sort?: 'id_desc' | 'id_asc'; + score?: '1' | '-1'; - user: number; - receiver: number; + user?: number; + receiver?: number; - limit: number; + limit?: number; cursor_string?: string; }, addons: IDefaultParams): Promise => { if (params.discussion_id) { diff --git a/api/v2/changelogs_details.ts b/api/v2/changelogs_details.ts new file mode 100644 index 00000000..12bb6bae --- /dev/null +++ b/api/v2/changelogs_details.ts @@ -0,0 +1,20 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (params: { + stream_name: string; + build_version: string; +}, addons: IDefaultParams): Promise => { + const data = await request(`https://osu.ppy.sh/api/v2/changelog/${params.stream_name}/${params.build_version}`, { + method: 'GET', + addons, + }); + + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/changelogs_list.ts b/api/v2/changelogs_list.ts new file mode 100644 index 00000000..9c07e234 --- /dev/null +++ b/api/v2/changelogs_list.ts @@ -0,0 +1,73 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + +type params = ({ + type: 'all'; + from_build?: string; + to_build?: string; + + stream_name?: string; + max_id?: string; + + message_formats?: ('html' | 'markdown')[]; +} | { + type: 'lookup'; + + message_formats: ('html' | 'markdown')[]; + changelog: string; + key: string; +}); + + +type Response = + T extends 'all' + ? any + : T extends 'lookup' + ? any + : never; + + +const name = async (params: T, addons: IDefaultParams) => { + if (params.type == null) return null; + + let object: any = {}; + let url = 'https://osu.ppy.sh/api/v2'; + let method = 'GET'; + + + switch (params.type) { + case 'all': + url += '/changelog'; + + object = { + from: params.from_build, + to: params.to_build, + + stream: params.stream_name, + max_id: params.max_id, + 'message_formats[]': params.message_formats, + }; + break; + + case 'lookup': + url += `/changelog/${params.changelog}`; + + object['message_formats[]'] = params.message_formats; + object['key'] = params.key; + break; + }; + + + const data = await request(url, { + method: method, + params: object, + addons + }); + + + return data as Response; +}; + + +export default name; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index eae7c7aa..993e4449 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -1,3 +1,47 @@ +import beatmap_events_list from "../api/v2/beatmap_events_list"; +import beatmaps_lookup from "../api/v2/beatmaps_lookup"; +import beatmaps_details from "../api/v2/beatmaps_details"; +import beatmaps_download from "../api/v2/beatmaps_download"; +import beatmap_packs_list from "../api/v2/beatmap_packs_list"; +import beatmap_packs_details from "../api/v2/beatmap_packs_details"; +import beatmaps_discussions_list from "../api/v2/beatmaps_discussions_list"; +import beatmaps_discussions_posts from "../api/v2/beatmaps_discussions_posts"; +import beatmaps_discussions_votes from "../api/v2/beatmaps_discussions_votes"; + + +export const beatmaps = { + packs: { + list: beatmap_packs_list, + details: beatmap_packs_details, + }, + lookup: beatmaps_lookup, + details: beatmaps_details, + events: { + list: beatmap_events_list, + }, + download: beatmaps_download, + discussions: { + list: beatmaps_discussions_list, + posts: beatmaps_discussions_posts, + votes: beatmaps_discussions_votes, + } +}; + + + + +import changelogs_list from '../api/v2/changelogs_list'; +import changelogs_details from '../api/v2/changelogs_details'; + + +export const changelogs = { + list: changelogs_list, + details: changelogs_details, +}; + + + + import users_details from "../api/v2/users_list"; import users_events from "../api/v2/users/events"; @@ -62,35 +106,4 @@ export const forums = { import search_all from '../api/v2/search'; -export const search = search_all; - - - -import beatmap_events_list from "../api/v2/beatmap_events_list"; -import beatmaps_lookup from "../api/v2/beatmaps_lookup"; -import beatmaps_details from "../api/v2/beatmaps_details"; -import beatmaps_download from "../api/v2/beatmaps_download"; -import beatmap_packs_list from "../api/v2/beatmap_packs_list"; -import beatmap_packs_details from "../api/v2/beatmap_packs_details"; -import beatmaps_discussions_list from "../api/v2/beatmaps_discussions_list"; -import beatmaps_discussions_posts from "../api/v2/beatmaps_discussions_posts"; -import beatmaps_discussions_votes from "../api/v2/beatmaps_discussions_votes"; - - -export const beatmaps = { - packs: { - list: beatmap_packs_list, - details: beatmap_packs_details, - }, - lookup: beatmaps_lookup, - details: beatmaps_details, - events: { - list: beatmap_events_list, - }, - download: beatmaps_download, - discussions: { - list: beatmaps_discussions_list, - posts: beatmaps_discussions_posts, - votes: beatmaps_discussions_votes, - } -}; \ No newline at end of file +export const search = search_all; \ No newline at end of file From 263c37a070e9ee8aaf87c9b0859ccd1ee0d4daba Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 24 Feb 2024 20:57:26 +0300 Subject: [PATCH 059/259] more 5/? --- api/v2/comments_list.ts | 41 +++++++++++++++++++++++++++++++++++++++++ routes/v2.ts | 10 ++++++++++ 2 files changed, 51 insertions(+) create mode 100644 api/v2/comments_list.ts diff --git a/api/v2/comments_list.ts b/api/v2/comments_list.ts new file mode 100644 index 00000000..1caf960b --- /dev/null +++ b/api/v2/comments_list.ts @@ -0,0 +1,41 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (params: { + commentable_type?: 'news_post' | 'beatmapset'; + + after_id: string; + + commentable_id?: string; + cursor?: { + id: number; + created_at: string; + }; + parent_id?: string, + sort?: 'new' | 'old' | 'top'; +}, addons: IDefaultParams) => { + const object = { + after: params.after_id, + commentable_type: params.commentable_type, + commentable_id: params.commentable_id, + 'cursor[id]': params.cursor?.id, + 'cursor[created_at]': params.cursor?.created_at, + parent_id: params.parent_id, + sort: params.sort, + }; + + + const data = await request(`https://osu.ppy.sh/api/v2/comments`, { + method: 'GET', + params: object, + addons, + }); + + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 993e4449..9a648d4d 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -42,6 +42,16 @@ export const changelogs = { +import comments_list from '../api/v2/comments_list'; + + +export const comments = { + list: comments_list, +}; + + + + import users_details from "../api/v2/users_list"; import users_events from "../api/v2/users/events"; From a8b33e541e6a6b54812c74cc8465f1764ddcd4a3 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 24 Feb 2024 21:16:27 +0300 Subject: [PATCH 060/259] more 6/? --- api/v2/comments_details.ts | 17 +++++++++ api/v2/forum_topic_details.ts | 40 +++++++++++++++++++++ api/v2/forums/topic/details.ts | 23 ------------ api/v2/{users/events.ts => users_events.ts} | 11 +++--- routes/v2.ts | 12 ++++--- 5 files changed, 70 insertions(+), 33 deletions(-) create mode 100644 api/v2/comments_details.ts create mode 100644 api/v2/forum_topic_details.ts delete mode 100644 api/v2/forums/topic/details.ts rename api/v2/{users/events.ts => users_events.ts} (78%) diff --git a/api/v2/comments_details.ts b/api/v2/comments_details.ts new file mode 100644 index 00000000..ed9bea01 --- /dev/null +++ b/api/v2/comments_details.ts @@ -0,0 +1,17 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (comment_id: string, addons: IDefaultParams) => { + const data = await request(`https://osu.ppy.sh/api/v2/comments/${comment_id}`, { + method: 'GET', + addons, + }); + + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/forum_topic_details.ts b/api/v2/forum_topic_details.ts new file mode 100644 index 00000000..2363dc0d --- /dev/null +++ b/api/v2/forum_topic_details.ts @@ -0,0 +1,40 @@ +import { request } from "../../utility/request"; +import { ForumPostDetails } from '../../types/forums_topic_details'; +import { IDefaultParams } from "../../types"; + + +// FIXME: add query params +const name = async (params: { + topic_id: number + + start_id?: string, + end_id?: string, + + limit?: number, + sort?: 'id_asc' | 'id_desc', + + cursor_string?: string, +}, addons: IDefaultParams): Promise => { + const object = { + start: params.start_id, + end: params.end_id, + + sort: params.sort, + limit: params.limit, + + cursor_string: params.cursor_string, + }; + + + const data = await request(`https://osu.ppy.sh/api/v2/forums/topics/${params.topic_id}`, { + method: 'GET', + params: object, + addons, + }); + + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/forums/topic/details.ts b/api/v2/forums/topic/details.ts deleted file mode 100644 index f44ffbab..00000000 --- a/api/v2/forums/topic/details.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { request } from "../../../../utility/request"; -import { ForumPostDetails } from '../../../../types/forums_topic_details'; - - -// FIXME: add query params -const name = async (topic_id: number, obj?: { - sort?: 'id_asc' | 'id_desc', - limit?: number, - start?: string, - end?: string, - cursor_string?: string, -}): Promise => { - const data = await request(`https://osu.ppy.sh/api/v2/forums/topics/${topic_id}`, { - method: 'GET', - params: obj, - - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/api/v2/users/events.ts b/api/v2/users_events.ts similarity index 78% rename from api/v2/users/events.ts rename to api/v2/users_events.ts index ba134456..40a13499 100644 --- a/api/v2/users/events.ts +++ b/api/v2/users_events.ts @@ -1,13 +1,14 @@ -import { request } from "../../../utility/request"; -import { UsersEvents, Event } from '../../../types/users_events'; +import { request } from "../../utility/request"; +import { UsersEvents } from '../../types/users_events'; +import { IDefaultParams } from "../../types"; const name = async ({ sort, cursor_string, type }: { - cursor_string?: string; - sort?: 'id_desc' | 'id_asc', type?: ('achievement' | 'beatmapPlaycount' | 'beatmapsetApprove' | 'beatmapsetDelete' | 'beatmapsetRevive' | 'beatmapsetUpdate' | 'beatmapsetUpload' | 'rank' | 'userSupportAgain' | 'userSupportFirst' | 'userSupportGift' | 'usernameChange')[] -} = {}): Promise => { + sort?: 'id_desc' | 'id_asc', + cursor_string?: string; +} = {}, addons: IDefaultParams): Promise => { const data: UsersEvents = await request(`https://osu.ppy.sh/api/v2/events`, { method: 'GET', params: { sort: sort, cursor_string: cursor_string }, diff --git a/routes/v2.ts b/routes/v2.ts index 9a648d4d..6b8b90a0 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -43,17 +43,19 @@ export const changelogs = { import comments_list from '../api/v2/comments_list'; +import comments_details from '../api/v2/comments_details'; export const comments = { list: comments_list, + details: comments_details, }; import users_details from "../api/v2/users_list"; -import users_events from "../api/v2/users/events"; +import users_events from "../api/v2/users_events"; export const users = { @@ -104,12 +106,12 @@ export const site = { -import forums_topic_details from '../api/v2/forums/topic/details'; +import forums_topic_details from '../api/v2/forum_topic_details'; export const forums = { - topic: { - details: forums_topic_details - } + topics: { + details: forums_topic_details, + }, }; From c6bd31a0407adf7be21344fc71d3b4f7a1a94400 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 24 Feb 2024 23:00:51 +0300 Subject: [PATCH 061/259] more 7/? --- api/v2/assets_backgrounds.ts | 38 ++++++++++++++++ api/v2/assets_dataFiles.ts | 24 ++++++++++ api/v2/news_details.ts | 20 +++++++++ api/v2/news_list.ts | 26 +++++++++++ api/v2/notification_actions.ts | 80 ++++++++++++++++++++++++++++++++++ api/v2/notifications_list.ts | 23 ++++++++++ routes/v2.ts | 36 ++++++++++++++- tools/index.ts | 10 +++++ utility/request.ts | 4 +- 9 files changed, 258 insertions(+), 3 deletions(-) create mode 100644 api/v2/assets_backgrounds.ts create mode 100644 api/v2/assets_dataFiles.ts create mode 100644 api/v2/news_details.ts create mode 100644 api/v2/news_list.ts create mode 100644 api/v2/notification_actions.ts create mode 100644 api/v2/notifications_list.ts create mode 100644 tools/index.ts diff --git a/api/v2/assets_backgrounds.ts b/api/v2/assets_backgrounds.ts new file mode 100644 index 00000000..732a9617 --- /dev/null +++ b/api/v2/assets_backgrounds.ts @@ -0,0 +1,38 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + +type params = ({ + type: 'seasonal'; +}); + +type Response = + T extends 'site' + ? any + : T extends 'beatmaps' + ? any + : never; + + +const name = async (params: T, addons: IDefaultParams): Promise> => { + let url = 'https://osu.ppy.sh/api/v2'; + + switch (params.type) { + case 'seasonal': + url += `/seasonal-backgrounds`; + + break; + }; + + + const data = await request(url, { + method: 'GET', + addons, + }); + + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/assets_dataFiles.ts b/api/v2/assets_dataFiles.ts new file mode 100644 index 00000000..9c6b6f30 --- /dev/null +++ b/api/v2/assets_dataFiles.ts @@ -0,0 +1,24 @@ +import { request } from "../../utility/request"; + + + +const name = async () => { + const data = await request(`https://data.ppy.sh/`, { + method: 'GET', + }); + + + const array = data.split('\n') + .filter((r: string) => r.includes(` r != null); + + + return array; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/news_details.ts b/api/v2/news_details.ts new file mode 100644 index 00000000..78e6e580 --- /dev/null +++ b/api/v2/news_details.ts @@ -0,0 +1,20 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (params: { + news_id: string; + key?: 'id' | null; +}, addons: IDefaultParams) => { + const data = await request(`https://osu.ppy.sh/api/v2/news/${params.news_id}`, { + method: 'GET', + params: { key: params?.key }, + addons, + }); + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/news_list.ts b/api/v2/news_list.ts new file mode 100644 index 00000000..626cf813 --- /dev/null +++ b/api/v2/news_list.ts @@ -0,0 +1,26 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (params: { + from_year?: string; + + limit?: string; + cursor_string?: string; +} = {}, addons: IDefaultParams) => { + const data = await request(`https://osu.ppy.sh/api/v2/news`, { + method: 'GET', + params: { + year: params.from_year, + limit: params.limit, + cursor_string: params.cursor_string, + }, + addons, + }); + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/notification_actions.ts b/api/v2/notification_actions.ts new file mode 100644 index 00000000..d923dac8 --- /dev/null +++ b/api/v2/notification_actions.ts @@ -0,0 +1,80 @@ +import { request } from "../../utility/request"; +import { IDefaultParams } from "../../types"; +import { postData } from "../../tools"; + + +type params = ({ + type: 'mark_as_readed'; + + ids: number[]; + + identities?: { + category: string; + object_id: string + object_type: string + }[]; + + notifications?: { + category: string; + id: number; + object_id: string; + object_type: string; + }[] +}); + + +type Response = + T extends 'mark_as_readed' + ? any + : never; + + +const name = async (params: T, addons: IDefaultParams): Promise => { + const object: string[] = []; + let url = 'https://osu.ppy.sh/api/v2'; + let method = 'GET'; + + + return 'doesnt work'; + + switch (params.type) { + case 'mark_as_readed': + url += '/notifications/mark-read'; + method = 'POST'; + + + // params.ids.forEach((r, index) => object[`identities[${index}][id]`] = r); + + if (Array.isArray(params.notifications)) { + const formData = postData(params.notifications); + + object.push(formData); + }; + + if (Array.isArray(params.identities)) { + const formData = postData(params.identities); + + object.push(formData); + }; + break; + }; + + + const data = await request(url, { + method: method, + headers: { + Accept: `application/json`, + "Content-Type": "application/x-www-form-urlencoded", + }, + // data: JSON.stringify(object), + + data: encodeURI(object.join('&')), + addons, + }); + + + return data as Response; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/notifications_list.ts b/api/v2/notifications_list.ts new file mode 100644 index 00000000..d08f112d --- /dev/null +++ b/api/v2/notifications_list.ts @@ -0,0 +1,23 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (params: { + max_id: string; + unreaded_only: boolean; +}, addons: IDefaultParams) => { + const data = await request(`https://osu.ppy.sh/api/v2/notifications`, { + method: 'GET', + params: { max_id: params.max_id }, + addons, + }); + + if (params.unreaded_only == true) + data.notifications = data.notifications.filter((r: any) => r.is_read == false); + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 6b8b90a0..6502fc9e 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -118,4 +118,38 @@ export const forums = { import search_all from '../api/v2/search'; -export const search = search_all; \ No newline at end of file +export const search = search_all; + + + +import assets_backgrounds from "../api/v2/assets_backgrounds"; +import assets_dataFiles from "../api/v2/assets_dataFiles"; + + +export const assets = { + backgrounds: assets_backgrounds, + dataFiles: assets_dataFiles +}; + + + +import news_list from "../api/v2/news_list"; +import news_details from "../api/v2/news_details"; + + +export const news = { + list: news_list, + details: news_details, +}; + + + + +import notifications_list from '../api/v2/notifications_list'; +import notification_actions from '../api/v2/notification_actions'; + + +export const notifications = { + list: notifications_list, + action: notification_actions, +}; \ No newline at end of file diff --git a/tools/index.ts b/tools/index.ts new file mode 100644 index 00000000..19246fc1 --- /dev/null +++ b/tools/index.ts @@ -0,0 +1,10 @@ +export const postData = (array: any[]) => { + const data = array.map((data, index) => { + return Object.entries(data).map(([key, value]) => { + return `notifications[${index}][${key}]=${encodeURIComponent(value as any)}`; + }).join('&'); + }).join('&'); + + + return data; +}; \ No newline at end of file diff --git a/utility/request.ts b/utility/request.ts index 59ef4b33..aaabd61c 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -44,8 +44,8 @@ export const request: RequestType = (url, { method, headers, data, params = {}, if (!headers) headers = {}; headers.Authorization = `Bearer ${addons.authKey || auth.cache_tokens.v2}`; - headers.Accept = `application/json`; - headers['Content-Type'] = `application/json`; + if (!headers.Accept) headers.Accept = `application/json`; + if (!headers['Content-Type']) headers['Content-Type'] = `application/json`; headers['x-api-version'] = addons.apiVersion == '' ? null : addons.apiVersion || '20240130'; }; From 38ba41601c09871516eaa2221e96f80286eddd6d Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 25 Feb 2024 14:00:43 +0300 Subject: [PATCH 062/259] more 8/? --- .gitignore | 4 +- api/v2/assets_backgrounds.ts | 2 +- api/v2/beatmap_events_list.ts | 2 +- api/v2/beatmap_packs_details.ts | 2 +- api/v2/beatmap_packs_list.ts | 2 +- api/v2/beatmaps_details.ts | 2 +- api/v2/beatmaps_discussions_list.ts | 2 +- api/v2/beatmaps_discussions_posts.ts | 2 +- api/v2/beatmaps_discussions_votes.ts | 2 +- api/v2/beatmaps_download.ts | 2 +- api/v2/beatmaps_lookup.ts | 2 +- api/v2/changelogs_details.ts | 2 +- api/v2/changelogs_list.ts | 2 +- api/v2/comments_details.ts | 2 +- api/v2/comments_list.ts | 2 +- api/v2/forum_topic_details.ts | 2 +- api/v2/news_details.ts | 2 +- api/v2/news_list.ts | 2 +- api/v2/notification_actions.ts | 2 +- api/v2/notifications_list.ts | 2 +- api/v2/ranking_list.ts | 133 +++++++++++++++++++++++++++ api/v2/search.ts | 2 +- api/v2/site/ranking/details.ts | 23 ----- api/v2/spotlights_list.ts | 16 ++++ api/v2/users_events.ts | 2 +- api/v2/users_list.ts | 2 +- routes/v2.ts | 28 ++++-- 27 files changed, 192 insertions(+), 56 deletions(-) create mode 100644 api/v2/ranking_list.ts delete mode 100644 api/v2/site/ranking/details.ts create mode 100644 api/v2/spotlights_list.ts diff --git a/.gitignore b/.gitignore index 990e20c9..c94b2af8 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ /wiki /node_modules index.js -package-lock.json \ No newline at end of file +package-lock.json +.ts +1.ts \ No newline at end of file diff --git a/api/v2/assets_backgrounds.ts b/api/v2/assets_backgrounds.ts index 732a9617..7bcb2a33 100644 --- a/api/v2/assets_backgrounds.ts +++ b/api/v2/assets_backgrounds.ts @@ -14,7 +14,7 @@ type Response = : never; -const name = async (params: T, addons: IDefaultParams): Promise> => { +const name = async (params: T, addons?: IDefaultParams): Promise> => { let url = 'https://osu.ppy.sh/api/v2'; switch (params.type) { diff --git a/api/v2/beatmap_events_list.ts b/api/v2/beatmap_events_list.ts index 4d8f77b9..b4b911ad 100644 --- a/api/v2/beatmap_events_list.ts +++ b/api/v2/beatmap_events_list.ts @@ -9,7 +9,7 @@ const name = async (obj: { types: (beatmap_events_types)[]; min_date: string; max_date: string; -}, addons: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { let url = 'https://osu.ppy.sh/api/v2/beatmapsets/events'; diff --git a/api/v2/beatmap_packs_details.ts b/api/v2/beatmap_packs_details.ts index c21c93ee..0e6ea26d 100644 --- a/api/v2/beatmap_packs_details.ts +++ b/api/v2/beatmap_packs_details.ts @@ -4,7 +4,7 @@ import { request } from "../../utility/request"; -const name = async (pack_tag: string, addons: IDefaultParams): Promise => { +const name = async (pack_tag: string, addons?: IDefaultParams): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/beatmaps/packs/${pack_tag}`, { method: 'GET', addons, diff --git a/api/v2/beatmap_packs_list.ts b/api/v2/beatmap_packs_list.ts index 075d99a4..5564c8cc 100644 --- a/api/v2/beatmap_packs_list.ts +++ b/api/v2/beatmap_packs_list.ts @@ -7,7 +7,7 @@ import { request } from "../../utility/request"; const name = async (params: { type: IBeatmapPackType; cursor_string?: string; -}, addons: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/beatmaps/packs`, { method: 'GET', params, diff --git a/api/v2/beatmaps_details.ts b/api/v2/beatmaps_details.ts index 5ba8024b..86a1bd2e 100644 --- a/api/v2/beatmaps_details.ts +++ b/api/v2/beatmaps_details.ts @@ -20,7 +20,7 @@ type Response = ? BeamapsDetailsSet : never; -const name = async (params: T, addons: IDefaultParams): Promise> => { +const name = async (params: T, addons?: IDefaultParams): Promise> => { const object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; let method = 'GET'; diff --git a/api/v2/beatmaps_discussions_list.ts b/api/v2/beatmaps_discussions_list.ts index fe40e0dc..f1894d66 100644 --- a/api/v2/beatmaps_discussions_list.ts +++ b/api/v2/beatmaps_discussions_list.ts @@ -14,7 +14,7 @@ const name = async (params: { limit?: number; sort?: 'id_desc' | 'id_asc'; cursor_string?: string; -}, addons: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/beatmapsets/discussions`, { method: 'GET', params, diff --git a/api/v2/beatmaps_discussions_posts.ts b/api/v2/beatmaps_discussions_posts.ts index c087ae2b..a1e0fefe 100644 --- a/api/v2/beatmaps_discussions_posts.ts +++ b/api/v2/beatmaps_discussions_posts.ts @@ -12,7 +12,7 @@ const name = async (params: { limit?: number; cursor_string?: string; -}, addons: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { if (params.discussion_id) { // @ts-ignore params.beatmapset_discussion_id = params.discussion_id; diff --git a/api/v2/beatmaps_discussions_votes.ts b/api/v2/beatmaps_discussions_votes.ts index 05d04c93..c8ed1f9c 100644 --- a/api/v2/beatmaps_discussions_votes.ts +++ b/api/v2/beatmaps_discussions_votes.ts @@ -14,7 +14,7 @@ const name = async (params: { limit?: number; cursor_string?: string; -}, addons: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { if (params.discussion_id) { // @ts-ignore params.beatmapset_discussion_id = params.discussion_id; diff --git a/api/v2/beatmaps_download.ts b/api/v2/beatmaps_download.ts index c81bfe20..f32de435 100644 --- a/api/v2/beatmaps_download.ts +++ b/api/v2/beatmaps_download.ts @@ -29,7 +29,7 @@ type params = ({ }); -const name = (params: T, addons: IDefaultParams): Promise => new Promise((resolve, reject) => { +const name = (params: T, addons?: IDefaultParams): Promise => new Promise((resolve, reject) => { const { dir } = path.parse(params.file_path); if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); diff --git a/api/v2/beatmaps_lookup.ts b/api/v2/beatmaps_lookup.ts index 047eae67..cd149424 100644 --- a/api/v2/beatmaps_lookup.ts +++ b/api/v2/beatmaps_lookup.ts @@ -38,7 +38,7 @@ type Response = : never; -const name = async (params: T, addons: IDefaultParams): Promise> => { +const name = async (params: T, addons?: IDefaultParams): Promise> => { const object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; let method = 'GET'; diff --git a/api/v2/changelogs_details.ts b/api/v2/changelogs_details.ts index 12bb6bae..652b1899 100644 --- a/api/v2/changelogs_details.ts +++ b/api/v2/changelogs_details.ts @@ -6,7 +6,7 @@ import { request } from "../../utility/request"; const name = async (params: { stream_name: string; build_version: string; -}, addons: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/changelog/${params.stream_name}/${params.build_version}`, { method: 'GET', addons, diff --git a/api/v2/changelogs_list.ts b/api/v2/changelogs_list.ts index 9c07e234..123b63d7 100644 --- a/api/v2/changelogs_list.ts +++ b/api/v2/changelogs_list.ts @@ -28,7 +28,7 @@ type Response = : never; -const name = async (params: T, addons: IDefaultParams) => { +const name = async (params: T, addons?: IDefaultParams) => { if (params.type == null) return null; let object: any = {}; diff --git a/api/v2/comments_details.ts b/api/v2/comments_details.ts index ed9bea01..7444161b 100644 --- a/api/v2/comments_details.ts +++ b/api/v2/comments_details.ts @@ -3,7 +3,7 @@ import { request } from "../../utility/request"; -const name = async (comment_id: string, addons: IDefaultParams) => { +const name = async (comment_id: string, addons?: IDefaultParams) => { const data = await request(`https://osu.ppy.sh/api/v2/comments/${comment_id}`, { method: 'GET', addons, diff --git a/api/v2/comments_list.ts b/api/v2/comments_list.ts index 1caf960b..bd384d0f 100644 --- a/api/v2/comments_list.ts +++ b/api/v2/comments_list.ts @@ -15,7 +15,7 @@ const name = async (params: { }; parent_id?: string, sort?: 'new' | 'old' | 'top'; -}, addons: IDefaultParams) => { +}, addons?: IDefaultParams) => { const object = { after: params.after_id, commentable_type: params.commentable_type, diff --git a/api/v2/forum_topic_details.ts b/api/v2/forum_topic_details.ts index 2363dc0d..0470ebbb 100644 --- a/api/v2/forum_topic_details.ts +++ b/api/v2/forum_topic_details.ts @@ -14,7 +14,7 @@ const name = async (params: { sort?: 'id_asc' | 'id_desc', cursor_string?: string, -}, addons: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { const object = { start: params.start_id, end: params.end_id, diff --git a/api/v2/news_details.ts b/api/v2/news_details.ts index 78e6e580..8ba8714f 100644 --- a/api/v2/news_details.ts +++ b/api/v2/news_details.ts @@ -6,7 +6,7 @@ import { request } from "../../utility/request"; const name = async (params: { news_id: string; key?: 'id' | null; -}, addons: IDefaultParams) => { +}, addons?: IDefaultParams) => { const data = await request(`https://osu.ppy.sh/api/v2/news/${params.news_id}`, { method: 'GET', params: { key: params?.key }, diff --git a/api/v2/news_list.ts b/api/v2/news_list.ts index 626cf813..1c6edab4 100644 --- a/api/v2/news_list.ts +++ b/api/v2/news_list.ts @@ -8,7 +8,7 @@ const name = async (params: { limit?: string; cursor_string?: string; -} = {}, addons: IDefaultParams) => { +} = {}, addons?: IDefaultParams) => { const data = await request(`https://osu.ppy.sh/api/v2/news`, { method: 'GET', params: { diff --git a/api/v2/notification_actions.ts b/api/v2/notification_actions.ts index d923dac8..eb44ab42 100644 --- a/api/v2/notification_actions.ts +++ b/api/v2/notification_actions.ts @@ -29,7 +29,7 @@ type Response = : never; -const name = async (params: T, addons: IDefaultParams): Promise => { +const name = async (params: T, addons?: IDefaultParams): Promise => { const object: string[] = []; let url = 'https://osu.ppy.sh/api/v2'; let method = 'GET'; diff --git a/api/v2/notifications_list.ts b/api/v2/notifications_list.ts index d08f112d..07d5a423 100644 --- a/api/v2/notifications_list.ts +++ b/api/v2/notifications_list.ts @@ -6,7 +6,7 @@ import { request } from "../../utility/request"; const name = async (params: { max_id: string; unreaded_only: boolean; -}, addons: IDefaultParams) => { +}, addons?: IDefaultParams) => { const data = await request(`https://osu.ppy.sh/api/v2/notifications`, { method: 'GET', params: { max_id: params.max_id }, diff --git a/api/v2/ranking_list.ts b/api/v2/ranking_list.ts new file mode 100644 index 00000000..5df08687 --- /dev/null +++ b/api/v2/ranking_list.ts @@ -0,0 +1,133 @@ +import { request } from "../../utility/request"; +import { IDefaultParams, Modes_names } from "../../types"; + + +type params = { + page?: number; +} & ({ + type: 'charts'; + + spotlight_id?: string; + + filter?: 'all' | 'friends'; + mode?: Modes_names; +} | { + type: 'country'; + + filter?: 'all' | 'friends'; + mode?: Modes_names; +} | { + type: 'performance'; + + filter?: 'all' | 'friends'; + country_code?: string; + + mode?: Modes_names; + variant?: '4k' | '7k'; +} | { + type: 'score'; + + filter?: 'all' | 'friends'; + mode?: Modes_names; +} | { + type: 'kudosu'; +}); + + +type Response = + T extends 'charts' + ? any + : T extends 'country' + ? any + : T extends 'performance' + ? any + : T extends 'score' + ? any + : T extends 'kudosu' + ? any + : never; + + +const name = async (params: T, addons?: IDefaultParams): Promise | { error: string }> => { + if (params.type == null) + return { + error: 'Ranking type not specified', + }; + + if (params.type != 'kudosu' && params.mode == null) + return { + error: 'Gamemode not specified', + };; + + + let object: any = {}; + let url = 'https://osu.ppy.sh/api/v2'; + let method = 'GET'; + + switch (params.type) { + case 'charts': + url += `/rankings/${params.mode}/${params.type}`; + + object = { + 'cursor[page]': params.page, + filter: params.filter, + spotlight: params.spotlight_id, + }; + break; + + case 'country': + url += `/rankings/${params.mode}/${params.type}`; + + object = { + 'cursor[page]': params.page, + filter: params.filter, + }; + break; + + case 'performance': + url += `/rankings/${params.mode}/${params.type}`; + + object = { + 'cursor[page]': params.page, + filter: params.filter, + country: params.country_code, + variant: params.variant, + }; + break; + + case 'score': + url += `/rankings/${params.mode}/${params.type}`; + + object = { + 'cursor[page]': params.page, + filter: params.filter, + }; + break; + + case 'kudosu': + url += `/rankings/kudosu`; + + object.page = params.page; + break; + }; + + + const data = await request(url, { + method: method, + params: object, + addons, + }); + + + if ('error' in data) + return { + error: 'Api returned error, check your request parameters' + }; + + + if (params.type == 'kudosu') return data.ranking as Response; + return data as Response; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/search.ts b/api/v2/search.ts index 0b869ef3..8dafc35f 100644 --- a/api/v2/search.ts +++ b/api/v2/search.ts @@ -38,7 +38,7 @@ type Response = : never; -const name = async (params: T, addons: IDefaultParams): Promise> => { +const name = async (params: T, addons?: IDefaultParams): Promise> => { const object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; diff --git a/api/v2/site/ranking/details.ts b/api/v2/site/ranking/details.ts deleted file mode 100644 index 269abd04..00000000 --- a/api/v2/site/ranking/details.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Modes_names, ranking_types, country_codes } from "../../../../types"; -import { request } from "../../../../utility/request"; -import { RankingDetails } from '../../../../types/ranking_details'; - - - -const name = async (mode: Modes_names, type: ranking_types, object?: { - country?: country_codes, - "cursor[page]"?: number, - filter?: 'all' | 'friends', - spotlight_id?: number, - variant?: '4k' | '7k', -}): Promise => { - const data = await request(`https://osu.ppy.sh/api/v2/rankings/${mode}/${type}`, { - method: 'GET', - params: object, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/api/v2/spotlights_list.ts b/api/v2/spotlights_list.ts new file mode 100644 index 00000000..5cd968e3 --- /dev/null +++ b/api/v2/spotlights_list.ts @@ -0,0 +1,16 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (addons?: IDefaultParams) => { + const data = await request(`https://osu.ppy.sh/api/v2/spotlights`, { + method: 'GET', + addons, + }); + + return data.spotlights; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/users_events.ts b/api/v2/users_events.ts index 40a13499..97ca4522 100644 --- a/api/v2/users_events.ts +++ b/api/v2/users_events.ts @@ -8,7 +8,7 @@ const name = async ({ sort, cursor_string, type }: { type?: ('achievement' | 'beatmapPlaycount' | 'beatmapsetApprove' | 'beatmapsetDelete' | 'beatmapsetRevive' | 'beatmapsetUpdate' | 'beatmapsetUpload' | 'rank' | 'userSupportAgain' | 'userSupportFirst' | 'userSupportGift' | 'usernameChange')[] sort?: 'id_desc' | 'id_asc', cursor_string?: string; -} = {}, addons: IDefaultParams): Promise => { +} = {}, addons?: IDefaultParams): Promise => { const data: UsersEvents = await request(`https://osu.ppy.sh/api/v2/events`, { method: 'GET', params: { sort: sort, cursor_string: cursor_string }, diff --git a/api/v2/users_list.ts b/api/v2/users_list.ts index c8128f5b..ce7bff38 100644 --- a/api/v2/users_list.ts +++ b/api/v2/users_list.ts @@ -4,7 +4,7 @@ import { IDefaultParams } from "../../types"; -const name = async (ids: number[], addons: IDefaultParams): Promise => { +const name = async (ids: number[], addons?: IDefaultParams): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/users`, { method: 'GET', params: { diff --git a/routes/v2.ts b/routes/v2.ts index 6502fc9e..be233ee8 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -96,16 +96,6 @@ export const scores = { -import site_ranking_details from "../api/v2/site/ranking/details"; - -export const site = { - ranking: { - details: site_ranking_details, - }, -}; - - - import forums_topic_details from '../api/v2/forum_topic_details'; export const forums = { @@ -152,4 +142,22 @@ import notification_actions from '../api/v2/notification_actions'; export const notifications = { list: notifications_list, action: notification_actions, +}; + + + +import ranking_list from "../api/v2/ranking_list"; + + +export const ranking = { + list: ranking_list, +}; + + + +import spotlights_list from "../api/v2/spotlights_list"; + + +export const spotlights = { + list: spotlights_list, }; \ No newline at end of file From 755de750111ab682e14171a1a6cb8af279544d24 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 25 Feb 2024 16:07:47 +0300 Subject: [PATCH 063/259] more 9/? --- api/v2/beatmaps_actions.ts | 57 ++++++ api/v2/forums_topics_actions.ts | 164 ++++++++++++++++++ ...ic_details.ts => forums_topics_details.ts} | 0 api/v2/notification_actions.ts | 9 +- routes/v2.ts | 11 +- tools/index.ts | 15 +- 6 files changed, 244 insertions(+), 12 deletions(-) create mode 100644 api/v2/beatmaps_actions.ts create mode 100644 api/v2/forums_topics_actions.ts rename api/v2/{forum_topic_details.ts => forums_topics_details.ts} (100%) diff --git a/api/v2/beatmaps_actions.ts b/api/v2/beatmaps_actions.ts new file mode 100644 index 00000000..607e164c --- /dev/null +++ b/api/v2/beatmaps_actions.ts @@ -0,0 +1,57 @@ +import { request } from "../../utility/request"; +import { IDefaultParams } from "../../types"; +import { postDataObject } from "../../tools"; + + +type params = ({ + type: 'favourite'; + + beatmapset_id: number; + add: boolean; +}); + + +type Response = + T extends 'difficulty' + ? any + : T extends 'difficulties' + ? any + : never; + + +const name = async (params: T, addons?: IDefaultParams): Promise | { error: string }> => { + return { + error: 'TEMPORARY NOT WORKING, have no clue why', + }; + if (params.type == null) + return { + error: 'Type not specified', + }; + + const object: any = {}; + let url = 'https://osu.ppy.sh/api/v2'; + let method = 'POST'; + + + switch (params.type) { + case 'favourite': + url += `/beatmapsets/${params.beatmapset_id}/favourites`; + + object['action'] = params.add == true ? 'favourite' : 'unfavourite'; + break; + }; + + + const data = await request(url, { + method: method, + // params: object, + data: postDataObject('', object), + addons, + }); + + + return data as Response; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/forums_topics_actions.ts b/api/v2/forums_topics_actions.ts new file mode 100644 index 00000000..e95442b8 --- /dev/null +++ b/api/v2/forums_topics_actions.ts @@ -0,0 +1,164 @@ +import { request } from "../../utility/request"; +import { IDefaultParams } from "../../types"; + + +type params = ({ + type: 'create'; + forum_id: number; + + title: string; + message: string; + + enable_poll: boolean; + poll?: { + allow_vote_change?: boolean; + hide_results?: boolean; + + title: string; + options: string[]; + + max_votes_per_user?: number; + duration_days?: number; + }; +} | { + type: 'reply'; + + topic_id: number; + message: string; +} | { + type: 'edit_post'; + + post_id: number; + message: string; +} | { + type: 'edit_topic'; + + topic_id?: number; + post_id?: number; + + title?: string; + message?: string; +}); + + +type Response = + T extends 'difficulty' + ? any + : T extends 'difficulties' + ? any + : never; + + +const name = async (params: T, addons?: IDefaultParams): Promise> => { + let object: any = {}; + const body: any[] = []; + + let urls = []; + let methods = []; + const fields = []; + + + switch (params.type) { + case 'create': + urls.push(`https://osu.ppy.sh/api/v2/forums/topics`); + methods.push('POST'); + + object['forum_id'] = params.forum_id; + + object['title'] = params.title; + object['body'] = params.message; + + + object['with_poll'] = params.enable_poll; + if (params.enable_poll != true) { + body.push(object); + break; + }; + + + object['forum_topic_poll[vote_change]'] = params.poll.allow_vote_change; + object['forum_topic_poll[hide_results]'] = params.poll.hide_results; + + object['forum_topic_poll[title]'] = params.poll.title; + object['forum_topic_poll[options]'] = params.poll.options; + + object['forum_topic_poll[max_options]'] = params.poll.max_votes_per_user; + object['forum_topic_poll[length_days]'] = params.poll.duration_days; + + body.push(object); + break; + + case 'reply': + urls.push(`https://osu.ppy.sh/api/v2/forums/topics/${params.topic_id}/reply`); + methods.push('POST'); + + object['body'] = params.message; + + body.push(object); + break; + + case 'edit_post': + urls.push(`https://osu.ppy.sh/api/v2//forums/posts/${params.post_id}`); + methods.push('PUT'); + + object['body'] = params.message; + + body.push(object); + break; + + case 'edit_topic': + if (params.topic_id && (params.title != null && params.title != '')) { + // @ts DOESNT WORK + urls.push(`https://osu.ppy.sh/api/v2/forums/topics/${params.topic_id}`); + methods.push('PUT'); + + object['forum_topic[topic_title]'] = params.title; + + body.push(object); + fields.push('topic'); + + object = {}; + }; + + + if (params.post_id && (params.message != null && params.message != '')) { + urls.push(`https://osu.ppy.sh/api/v2/forums/posts/${params.post_id}`); + methods.push('PUT'); + + object['body'] = params.message; + + body.push(object); + fields.push('post'); + + object = {}; + }; + break; + }; + + + const results: any[] = []; + for (let i = 0; i < urls.length; i++) { + const url = urls[i]; + + const data = await request(url, { + method: methods[i], + // params: object, + // params: body[i], + data: JSON.stringify(body[i]), + addons, + }); + + results.push(data); + }; + + + if (params.type == 'edit_topic') { + let result = fields.map((r, index) => ({ [r]: results[index] })); + return result as Response; + }; + + return results[0] as Response; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/forum_topic_details.ts b/api/v2/forums_topics_details.ts similarity index 100% rename from api/v2/forum_topic_details.ts rename to api/v2/forums_topics_details.ts diff --git a/api/v2/notification_actions.ts b/api/v2/notification_actions.ts index eb44ab42..518f177c 100644 --- a/api/v2/notification_actions.ts +++ b/api/v2/notification_actions.ts @@ -1,6 +1,5 @@ import { request } from "../../utility/request"; import { IDefaultParams } from "../../types"; -import { postData } from "../../tools"; type params = ({ @@ -46,15 +45,15 @@ const name = async (params: T, addons?: IDefaultParams): Promi // params.ids.forEach((r, index) => object[`identities[${index}][id]`] = r); if (Array.isArray(params.notifications)) { - const formData = postData(params.notifications); + // const formData = postData(params.notifications); - object.push(formData); + // object.push(formData); }; if (Array.isArray(params.identities)) { - const formData = postData(params.identities); + // const formData = postData(params.identities); - object.push(formData); + // object.push(formData); }; break; }; diff --git a/routes/v2.ts b/routes/v2.ts index be233ee8..5bdf4c02 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -8,6 +8,8 @@ import beatmaps_discussions_list from "../api/v2/beatmaps_discussions_list"; import beatmaps_discussions_posts from "../api/v2/beatmaps_discussions_posts"; import beatmaps_discussions_votes from "../api/v2/beatmaps_discussions_votes"; +import beatmaps_actions from "../api/v2/beatmaps_actions"; + export const beatmaps = { packs: { @@ -24,7 +26,8 @@ export const beatmaps = { list: beatmaps_discussions_list, posts: beatmaps_discussions_posts, votes: beatmaps_discussions_votes, - } + }, + actions: beatmaps_actions, }; @@ -96,11 +99,13 @@ export const scores = { -import forums_topic_details from '../api/v2/forum_topic_details'; +import forums_topic_details from '../api/v2/forums_topics_details'; +import forums_topics_actions from '../api/v2/forums_topics_actions'; export const forums = { topics: { details: forums_topic_details, + actions: forums_topics_actions, }, }; @@ -141,7 +146,7 @@ import notification_actions from '../api/v2/notification_actions'; export const notifications = { list: notifications_list, - action: notification_actions, + actions: notification_actions, }; diff --git a/tools/index.ts b/tools/index.ts index 19246fc1..12fad69c 100644 --- a/tools/index.ts +++ b/tools/index.ts @@ -1,10 +1,17 @@ -export const postData = (array: any[]) => { +export const postDataArray = (field_name: string, array: any[]) => { const data = array.map((data, index) => { - return Object.entries(data).map(([key, value]) => { - return `notifications[${index}][${key}]=${encodeURIComponent(value as any)}`; - }).join('&'); + return postDataObject(`${field_name}[${index}]`, data); }).join('&'); return data; +}; + +export const postDataObject = (field_name: string, object: object) => { + return Object.entries(object).map(([key, value]) => { + if (field_name == '') + return `${key}=${encodeURIComponent(value as any)}`; + + return `${field_name}[${key}]=${encodeURIComponent(value as any)}`; + }).join('&'); }; \ No newline at end of file From cea9ba1dbcb5bfccfc79870f30d38ecc4869f02d Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 25 Feb 2024 16:50:43 +0300 Subject: [PATCH 064/259] more 10/? --- api/v2/comments_actions.ts | 52 +++++++++++++++ api/v2/scores/beatmaps.ts | 21 ------ api/v2/scores/user/beatmap.ts | 33 ---------- api/v2/scores/user/list.ts | 44 ------------- api/v2/scores_list.ts | 121 ++++++++++++++++++++++++++++++++++ routes/v2.ts | 27 ++++---- 6 files changed, 186 insertions(+), 112 deletions(-) create mode 100644 api/v2/comments_actions.ts delete mode 100644 api/v2/scores/beatmaps.ts delete mode 100644 api/v2/scores/user/beatmap.ts delete mode 100644 api/v2/scores/user/list.ts create mode 100644 api/v2/scores_list.ts diff --git a/api/v2/comments_actions.ts b/api/v2/comments_actions.ts new file mode 100644 index 00000000..0c6cd204 --- /dev/null +++ b/api/v2/comments_actions.ts @@ -0,0 +1,52 @@ +import { request } from "../../utility/request"; +import { IDefaultParams } from "../../types"; + + +type params = ({ + type: 'difficulty'; +} | { + type: 'set'; + id: number; +}); + + +type Response = + T extends 'difficulty' + ? any + : T extends 'difficulties' + ? any + : never; + + +const name = async (params: T, addons?: IDefaultParams): Promise | { error: string }> => { + return { error: 'lazer ...' }; + const object: any = {}; + let url = 'https://osu.ppy.sh/api/v2'; + let method = 'GET'; + + + switch (params.type) { + case 'difficulty': + url += `/beatmaps/lookup`; + + break; + + case 'set': + url += `/beatmaps/lookup`; + + break; + }; + + + const data = await request(url, { + method: method, + params: object, + addons, + }); + + + return data as Response; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/scores/beatmaps.ts b/api/v2/scores/beatmaps.ts deleted file mode 100644 index 7bea1e67..00000000 --- a/api/v2/scores/beatmaps.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { request } from "../../../utility/request"; -import { Modes_names } from '../../../types'; - - - -const name = async (beatmap_id: number, obj?: { - mode?: Modes_names, - mods?: string[], - type?: 'global' | 'country' | 'friend', -}) => { - const data = await request(`https://osu.ppy.sh/api/v2/beatmaps/${beatmap_id}/scores`, { - method: 'GET', - params: obj, - }); - - if (!data.scores) return data; - return data.scores.map((v: any, i: number) => ({ position: i + 1, ...v })); -}; - - -export default name; \ No newline at end of file diff --git a/api/v2/scores/user/beatmap.ts b/api/v2/scores/user/beatmap.ts deleted file mode 100644 index 0325f370..00000000 --- a/api/v2/scores/user/beatmap.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { ScoresUserBeatmap } from "../../../../types/v2/scores_user_beamap"; -import { request } from "../../../../utility/request"; -import { Modes_names } from "../../../../types"; - - - -const name = async (beatmap_id: number, user_id: number, obj: { - mode?: Modes_names, - mods?: string[], - best_only?: boolean, -} = {}): Promise => { - let url = `https://osu.ppy.sh/api/v2/beatmaps/${beatmap_id}/scores/users/${user_id}`; - if (!obj.best_only) url += '/all'; - - - const data = await request(url, { - method: 'GET', - params: obj, - }); - - - if (obj.best_only == true) { - data.score.position = data.position; - return [data.score]; - }; - - - if (data.scores) return data.scores - return data; -}; - - -export default name; \ No newline at end of file diff --git a/api/v2/scores/user/list.ts b/api/v2/scores/user/list.ts deleted file mode 100644 index 0eb6c727..00000000 --- a/api/v2/scores/user/list.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { request } from "../../../../utility/request"; -import { Modes_names } from "../../../../types"; -import mods from '../../../../tools/mods'; -import { ScoresUser } from '../../../../types/scores_user'; - - - -const name = async (user_id: number, type: 'recent' | 'best' | 'firsts' | 'pinned', object?: { - include_fails?: boolean, - mode?: Modes_names, - limit?: number, - offset?: number, - mods?: number -}): Promise => { - if (object.include_fails != null) - // @ts-ignore - object.include_fails = object.include_fails == true ? 1 : 0; - - const data = await request(`https://osu.ppy.sh/api/v2/users/${user_id}/scores/${type}`, { - method: 'GET', - params: object, - }); - - // check if scores exists. Sometimes there can an error - if (Array.isArray(data)) { - const transform: ScoresUser[] = data.map((v: ScoresUser, i) => { - const id = v.mods.map(r => r.acronym).filter(r => r != 'CL').join(''); - - return { - index: i + 1, - mods_id: mods.id(id) || 0, - ...v - }; - }); - - if (object?.mods) return transform.filter(r => (r.mods_id & object.mods) > 0); - return transform; - }; - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/api/v2/scores_list.ts b/api/v2/scores_list.ts new file mode 100644 index 00000000..d3be1f13 --- /dev/null +++ b/api/v2/scores_list.ts @@ -0,0 +1,121 @@ +import { request } from "../../utility/request"; +import { IDefaultParams, Modes_names } from "../../types"; + + +type params = { + mode?: Modes_names; +} & ({ + type: 'leaderboard' | 'solo_scores'; + + leaderboard_type?: 'global' | 'country' | 'friend', + beatmap_id: number; + mods?: string[]; +} | { + type: 'beatmap_best'; + + beatmap_id: number; + user_id: number; + mods?: string[]; +} | { + type: 'beatmap_all'; + + beatmap_id: number; + user_id: number; +} | { + type: 'user_best' | 'user_firsts' | 'user_recent' | 'user_pinned'; + + user_id: number; + + include_fails?: boolean; + + offset?: number; + limit?: number; +}); + + +type Response = + T extends 'difficulty' + ? any + : T extends 'difficulties' + ? any + : never; + + +const name = async (params: T, addons?: IDefaultParams): Promise> => { + const object: any = {}; + let url = 'https://osu.ppy.sh/api/v2'; + let method = 'GET'; + + + switch (params.type) { + case 'leaderboard': + url += `/beatmaps/${params.beatmap_id}/scores`; + + + object['type'] = params.leaderboard_type; + object['mode'] = params.mode; + object['mods[]'] = params.mods; + break; + + case 'beatmap_best': + url += `/beatmaps/${params.beatmap_id}/scores/users/${params.user_id}`; + + + object['mode'] = params.mode; + object['mods[]'] = params.mods; + break; + + case 'beatmap_all': + url += `/beatmaps/${params.beatmap_id}/scores/users/${params.user_id}/all`; + + + object['mode'] = params.mode; + break; + + case 'user_best': + case 'user_firsts': + case 'user_recent': + case 'user_pinned': + url += `/users/${params.user_id}/scores/${params.type.replace('user_', '')}`; + + + object['mode'] = params.mode; + object['limit'] = params.limit; + object['offset'] = params.offset; + object['include_fails'] = params.include_fails == true ? 1 : params.include_fails == false ? 0 : undefined; + break; + + case 'solo_scores': + url += `/beatmaps/${params.beatmap_id}/solo-scores`; + + + object['type'] = params.leaderboard_type; + object['mode'] = params.mode; + object['mods[]'] = params.mods; + break; + }; + + + const data = await request(url, { + method: method, + params: object, + addons, + }); + + + if ('error' in data) { + return data; + }; + + if (['leaderboard', 'beatmap_all'].includes(params.type)) { + data.scores.forEach((r: any, index: number) => r.index = index); + return data.scores as Response; + }; + + if (params.type != 'beatmap_best') data.forEach((r: any, index: number) => r.index = index); + + return data as Response; +}; + + +export default name; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 5bdf4c02..9841d10f 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -79,22 +79,21 @@ export const user = { -import scores_details from "../api/v2/scores/details"; -import scores_beatmap from "../api/v2/scores/beatmaps"; -import scores_user_list from "../api/v2/scores/user/list"; -import scores_user_beatmap from "../api/v2/scores/user/beatmap"; +import scores_list from "../api/v2/scores_list"; + export const scores = { - details: scores_details, - user: { - /** - * @deprecated since 3.0.0. Use ***v2.scores.user.list*** instead - */ - category: scores_user_list, - list: scores_user_list, - beatmap: scores_user_beatmap, - }, - beatmap: scores_beatmap, + // details: scores_details, + // user: { + // /** + // * @deprecated since 3.0.0. Use ***v2.scores.user.list*** instead + // */ + // category: scores_user_list, + // list: scores_user_list, + // beatmap: scores_user_beatmap, + // }, + // beatmap: scores_beatmap, + list: scores_list, }; From 761b03266edcac5f08e1f817cebc51494b65cb09 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 25 Feb 2024 23:00:26 +0300 Subject: [PATCH 065/259] more 11/? --- api/v2/beatmaps_download.ts | 46 ++++++++------------------ api/v2/scores/details.ts | 16 ---------- api/v2/scores_details.ts | 21 ++++++++++++ api/v2/scores_download.ts | 23 +++++++++++++ routes/v2.ts | 14 +++----- utility/request.ts | 64 ++++++++++++++++++------------------- 6 files changed, 93 insertions(+), 91 deletions(-) delete mode 100644 api/v2/scores/details.ts create mode 100644 api/v2/scores_details.ts create mode 100644 api/v2/scores_download.ts diff --git a/api/v2/beatmaps_download.ts b/api/v2/beatmaps_download.ts index f32de435..cf47540d 100644 --- a/api/v2/beatmaps_download.ts +++ b/api/v2/beatmaps_download.ts @@ -29,16 +29,13 @@ type params = ({ }); -const name = (params: T, addons?: IDefaultParams): Promise => new Promise((resolve, reject) => { +const name = async (params: T, addons?: IDefaultParams): Promise => { const { dir } = path.parse(params.file_path); if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); if (fs.existsSync(params.file_path) && params.overwrite != true) { - return { - type: 'exists', - path: params.file_path, - }; + return 'exists'; }; @@ -107,22 +104,14 @@ const name = (params: T, addons?: IDefaultParams): Promise { - if (result.error) return resolve(result.error); + }); - fs.writeFile(params.file_path, result.result, 'utf8', (err) => { - if (err) return reject(err); - resolve(params.file_path); - }); - }) - .catch(reject); + return data; } else if (params.type == 'difficulty') { switch (params.host) { case 'osu_direct_mirror': @@ -139,27 +128,20 @@ const name = (params: T, addons?: IDefaultParams): Promise { - if (result.error) return resolve(result.error); - - fs.writeFile(params.file_path, result.result, 'utf8', (err) => { - if (err) return reject(err); - - resolve(params.file_path); - }); - }) - .catch(reject); + }); + + + return data; }; - return resolve(`Unknown type: ${(params as any).type}`); -}); + + return `Unknown type: ${(params as any).type}`; +}; export default name; \ No newline at end of file diff --git a/api/v2/scores/details.ts b/api/v2/scores/details.ts deleted file mode 100644 index 83066512..00000000 --- a/api/v2/scores/details.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { request } from "../../../utility/request"; -import { Modes_names } from "../../../types"; -import { ScoresDetails } from '../../../types/scores_details'; - - - -const name = async (score_id: number): Promise => { - const data = await request(`https://osu.ppy.sh/api/v2/scores/${score_id}`, { - method: 'GET', - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/api/v2/scores_details.ts b/api/v2/scores_details.ts new file mode 100644 index 00000000..3d268886 --- /dev/null +++ b/api/v2/scores_details.ts @@ -0,0 +1,21 @@ +import { IDefaultParams, Modes_names } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (params: { + id: number; + mode?: Modes_names; +}, addons?: IDefaultParams) => { + let url = params.mode ? `https://osu.ppy.sh/api/v2/scores/${params.mode}/${params.id}` : `https://osu.ppy.sh/api/v2/scores/${params.id}`; + + const data = await request(url, { + method: 'GET', + addons, + }); + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/scores_download.ts b/api/v2/scores_download.ts new file mode 100644 index 00000000..08c93196 --- /dev/null +++ b/api/v2/scores_download.ts @@ -0,0 +1,23 @@ +import { Modes_names } from "../../types"; +import { download } from "../../utility/request"; + + + +const name = async (params: { + id: number; + mode?: Modes_names; + file_path?: string; +}) => { + let url = params.mode ? `https://osu.ppy.sh/api/v2/scores/${params.mode}/${params.id}` : `https://osu.ppy.sh/api/v2/scores/${params.id}`; + + + const data = await download(`${url}/download`, params.file_path, { + _callback: false, + }); + + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 9841d10f..17ffd3b1 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -80,20 +80,14 @@ export const user = { import scores_list from "../api/v2/scores_list"; +import scores_details from "../api/v2/scores_details"; +import scores_download from "../api/v2/scores_download"; export const scores = { - // details: scores_details, - // user: { - // /** - // * @deprecated since 3.0.0. Use ***v2.scores.user.list*** instead - // */ - // category: scores_user_list, - // list: scores_user_list, - // beatmap: scores_user_beatmap, - // }, - // beatmap: scores_beatmap, list: scores_list, + details: scores_details, + download: scores_download, }; diff --git a/utility/request.ts b/utility/request.ts index aaabd61c..e86c2519 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -1,6 +1,7 @@ // PACKAGES import querystring from 'querystring'; import https from 'https'; +import fs from 'fs'; // CREDENTIALS @@ -115,17 +116,17 @@ export const request: RequestType = (url, { method, headers, data, params = {}, * @param {string} dest The file destination * @returns {Promise} The response */ -export const download = (url: string, { _callback, headers = {}, data, params, addons, callback }: { +export const download = (url: string, dest: string, { _callback, headers = {}, data, params, callback }: { _callback: boolean; headers?: { [key: string]: string }, data?: string; params?: any; - addons?: IDefaultParams; callback?: Function; }): Promise => { return new Promise((resolve, reject) => { - if (url.includes('https://osu.ppy.sh/api/v2')) - headers['Authorization'] = `Bearer ${addons?.authKey || auth.cache_tokens.v2}`; + if (url.includes('https://osu.ppy.sh/api/v2')) headers['Authorization'] = `Bearer ${params?.v2 || auth.cache_tokens.v2}`; + + if (!headers['accept']) headers['accept'] = `application/octet-stream`; const generate_query = querystring.encode(params); @@ -134,58 +135,55 @@ export const download = (url: string, { _callback, headers = {}, data, params, a // console.log({ url: build_url, method, headers, data }); const req = https.request(build_url, { method: 'GET', headers }, response => { const { location } = response.headers; + if (location) { - download(location, { _callback, headers, data, params, callback }) + download(location, dest, { _callback, headers, data, params, callback }) .then(resolve) .catch(reject); return; - }; + } - if (response.statusCode != 200) { - resolve({ - error: 'file unavailable' - }); - return; - }; + const file = fs.createWriteStream(dest, { encoding: 'utf8' }); + file.on('error', err => { + fs.unlinkSync(dest); + reject(err); + }); - let chunk_data = ''; - let progress = 0; - let progressBar = 0; + file.on('finish', () => { + file.close(); + resolve(dest); + }); + if (response.statusCode === 404) { + resolve('file unavailable'); + return; + } - try { + if (_callback == true && callback !== undefined) { const totalLength = parseInt(response.headers['content-length']); - response.on('data', function (chunk) { - chunk_data += chunk; - if (_callback == true && callback !== undefined) { - progress += chunk.length; - progressBar = 100 * (progress / totalLength); - callback(progressBar); - }; - }); - + let progress = 0; + let progressBar = 0; - response.on('end', function () { - resolve({ result: chunk_data }); + response.on('data', (chunk) => { + progress += chunk.length; + progressBar = 100 * (progress / totalLength); + callback(progressBar); }); - } catch (error) { - reject(error); - }; - }); + } + response.pipe(file); + }); req.setTimeout(TIMEOUT_MS, () => { req.destroy(); reject(new Error(`Request to ${url} time out after ${TIMEOUT_MS}ms`)); }); - if (data) { req.write(data); }; - req.end(); }); }; \ No newline at end of file From 0f2e9e744edd5e8a5ef2f444fce8af593b521f48 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 25 Feb 2024 23:34:37 +0300 Subject: [PATCH 066/259] more 12/? --- api/v2/user/activity.ts | 24 ------------------------ api/v2/user/details.ts | 31 ------------------------------- api/v2/users_activity.ts | 25 +++++++++++++++++++++++++ api/v2/users_beatmaps.ts | 27 +++++++++++++++++++++++++++ api/v2/users_details.ts | 22 ++++++++++++++++++++++ api/v2/users_kudosu.ts | 25 +++++++++++++++++++++++++ routes/v2.ts | 22 ++++++++++------------ 7 files changed, 109 insertions(+), 67 deletions(-) delete mode 100644 api/v2/user/activity.ts delete mode 100644 api/v2/user/details.ts create mode 100644 api/v2/users_activity.ts create mode 100644 api/v2/users_beatmaps.ts create mode 100644 api/v2/users_details.ts create mode 100644 api/v2/users_kudosu.ts diff --git a/api/v2/user/activity.ts b/api/v2/user/activity.ts deleted file mode 100644 index 001c382b..00000000 --- a/api/v2/user/activity.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { request } from "../../../utility/request"; -import { Modes_names } from "../../../types"; -import { UserDetails } from '../../../types/user_details'; - - - -const name = async ({ user, limit, offset }: { - user: number; - limit: number; - offset: string; -}): Promise => { - let url = `https://osu.ppy.sh/api/v2/users/${user}/recent_activity`; - - - const data = await request(url, { - method: 'GET', - params: { limit, offset }, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/api/v2/user/details.ts b/api/v2/user/details.ts deleted file mode 100644 index 1db3a9db..00000000 --- a/api/v2/user/details.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { request } from "../../../utility/request"; -import { Modes_names } from "../../../types"; -import { UserDetails } from '../../../types/user_details'; - - - -const name = async ({ myself, user, mode, key }: { - myself?: boolean; - user?: number; - mode?: Modes_names; - key?: 'id' | 'username'; -}): Promise => { - let url = 'https://osu.ppy.sh/api/v2'; - - - if (myself == true) url += '/me'; - else if (user != null) url += `/users/${user}`; - - if (mode != null) url += `/${mode}`; - - - const data = await request(url, { - method: 'GET', - params: { key }, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/api/v2/users_activity.ts b/api/v2/users_activity.ts new file mode 100644 index 00000000..f1ce2994 --- /dev/null +++ b/api/v2/users_activity.ts @@ -0,0 +1,25 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (params: { + id: number; + limit?: number; + offset?: number; +}, addons?: IDefaultParams) => { + const data = await request(`https://osu.ppy.sh/api/v2/users/${params.id}/recent_activity`, { + method: 'GET', + params: { + limit: params.limit, + offset: params.offset, + }, + addons, + }); + + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/users_beatmaps.ts b/api/v2/users_beatmaps.ts new file mode 100644 index 00000000..fe6c32af --- /dev/null +++ b/api/v2/users_beatmaps.ts @@ -0,0 +1,27 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (params: { + type: 'favourite' | 'graveyard' | 'guest' | 'loved' | 'most_played' | 'nominated' | 'pending' | 'ranked'; + id: number; + + limit?: number; + offset?: number; +}, addons?: IDefaultParams) => { + const data = await request(`https://osu.ppy.sh/api/v2/users/${params.id}/beatmapsets/${params.type}`, { + method: 'GET', + params: { + limit: params.limit, + offset: params.offset, + }, + addons, + }); + + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/users_details.ts b/api/v2/users_details.ts new file mode 100644 index 00000000..00b490a9 --- /dev/null +++ b/api/v2/users_details.ts @@ -0,0 +1,22 @@ +import { IDefaultParams, Modes_names } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (params: { + id: number; + mode?: Modes_names; + key?: 'id' | 'username'; +}, addons?: IDefaultParams) => { + const data = await request(`https://osu.ppy.sh/api/v2/users/${params.id}${params.mode ? `/${params.mode}` : ''}`, { + method: 'GET', + params: { key: params.key }, + addons, + }); + + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/users_kudosu.ts b/api/v2/users_kudosu.ts new file mode 100644 index 00000000..8fdbbb33 --- /dev/null +++ b/api/v2/users_kudosu.ts @@ -0,0 +1,25 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (params: { + id: number; + limit?: number; + offset?: number; +}, addons?: IDefaultParams) => { + const data = await request(`https://osu.ppy.sh/api/v2/users/${params.id}/kudosu`, { + method: 'GET', + params: { + limit: params.limit, + offset: params.offset, + }, + addons, + }); + + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 17ffd3b1..5b3a9cf1 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -57,27 +57,25 @@ export const comments = { -import users_details from "../api/v2/users_list"; +import users_list from "../api/v2/users_list"; import users_events from "../api/v2/users_events"; +import users_details from "../api/v2/users_details"; +import users_activity from "../api/v2/users_activity"; +import users_beatmaps from "../api/v2/users_beatmaps"; +import users_kudosu from "../api/v2/users_kudosu"; export const users = { - list: users_details, + list: users_list, + kudosu: users_kudosu, events: users_events, + details: users_details, + beatmaps: users_beatmaps, + activity: users_activity, }; -import user_details from "../api/v2/user/details"; -import user_activity from "../api/v2/user/activity"; - - -export const user = { - details: user_details, - activity: user_activity -}; - - import scores_list from "../api/v2/scores_list"; import scores_details from "../api/v2/scores_details"; From 5f62aebee7884adf33dfe4e7f314880b5260c5db Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 26 Feb 2024 05:48:08 +0300 Subject: [PATCH 067/259] more 13/? --- api/v2/chat_actions.ts | 68 ++++++++++++++++++++++++++++++ api/v2/chat_channels_actions.ts | 75 +++++++++++++++++++++++++++++++++ api/v2/chat_channels_list.ts | 14 ++++++ api/v2/chat_details.ts | 16 +++++++ api/v2/chat_list.ts | 30 +++++++++++++ api/v2/chat_messages.ts | 24 +++++++++++ api/v2/chat_updates.ts | 29 +++++++++++++ api/v2/matches_details.ts | 17 ++++++++ api/v2/matches_list.ts | 32 ++++++++++++++ api/v2/me_details.ts | 19 +++++++++ api/v2/me_download_quota.ts | 14 ++++++ api/v2/me_friends.ts | 16 +++++++ api/v2/notification_actions.ts | 18 +++----- api/v2/wiki_details.ts | 19 +++++++++ routes/v2.ts | 57 +++++++++++++++++++++++++ utility/request.ts | 7 +++ 16 files changed, 443 insertions(+), 12 deletions(-) create mode 100644 api/v2/chat_actions.ts create mode 100644 api/v2/chat_channels_actions.ts create mode 100644 api/v2/chat_channels_list.ts create mode 100644 api/v2/chat_details.ts create mode 100644 api/v2/chat_list.ts create mode 100644 api/v2/chat_messages.ts create mode 100644 api/v2/chat_updates.ts create mode 100644 api/v2/matches_details.ts create mode 100644 api/v2/matches_list.ts create mode 100644 api/v2/me_details.ts create mode 100644 api/v2/me_download_quota.ts create mode 100644 api/v2/me_friends.ts create mode 100644 api/v2/wiki_details.ts diff --git a/api/v2/chat_actions.ts b/api/v2/chat_actions.ts new file mode 100644 index 00000000..bd531598 --- /dev/null +++ b/api/v2/chat_actions.ts @@ -0,0 +1,68 @@ +import { request } from "../../utility/request"; +import { IDefaultParams } from "../../types"; + + +type params = ({ + type: 'new'; + + is_action: boolean; + + user_id: number; + message: string; + + uuid?: string; +} | { + type: 'keepalive'; + + history_since?: number; + since?: number; +}); + + +type Response = + T extends 'difficulty' + ? any + : T extends 'difficulties' + ? any + : never; + + +const name = async (params: T, addons?: IDefaultParams): Promise> => { + const object: any = {}; + let url = 'https://osu.ppy.sh/api/v2'; + let method = 'POST'; + + + switch (params.type) { + case 'new': + url += `/chat/new`; + method = 'POST'; + + object['is_action'] = params.is_action; + object['target_id'] = params.user_id; + object['message'] = params.message; + object['uuid'] = params.uuid; + break; + + case 'keepalive': + url += `/chat/ack`; + method = 'POST'; + + object['history_since'] = params.history_since; + object['since'] = params.since; + break; + }; + + + const data = await request(url, { + method: method, + params: object, + addons, + }); + + + return data as Response; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/chat_channels_actions.ts b/api/v2/chat_channels_actions.ts new file mode 100644 index 00000000..a9da0937 --- /dev/null +++ b/api/v2/chat_channels_actions.ts @@ -0,0 +1,75 @@ +import { request } from "../../utility/request"; +import { IDefaultParams } from "../../types"; + + +type params = ({ + type: 'send'; + + is_action: boolean; + + id: number; + message: string; +} | { + type: 'join' | 'leave'; + + id: number; + user_id: number; +} | { + type: 'readed'; + + channel_id: number; + message_id: number; +}); + + +type Response = + T extends 'difficulty' + ? any + : T extends 'difficulties' + ? any + : never; + + +const name = async (params: T, addons?: IDefaultParams): Promise> => { + const object: any = {}; + let url = 'https://osu.ppy.sh/api/v2'; + let method = 'POST'; + + + switch (params.type) { + case 'send': + url += `/chat/channels/${params.id}/messages`; + + object['message'] = params.message; + object['is_action'] = params.is_action; + break; + + case 'join': + url += `/chat/channels/${params.id}/users/${params.user_id}`; + method = 'PUT'; + break; + + case 'leave': + url += `/chat/channels/${params.id}/users/${params.user_id}`; + method = 'DELETE'; + break; + + case 'readed': + url += `/chat/channels/${params.channel_id}/mark-as-read/${params.message_id}`; + method = 'PUT'; + break; + }; + + + const data = await request(url, { + method: method, + params: object, + addons, + }); + + + return data as Response; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/chat_channels_list.ts b/api/v2/chat_channels_list.ts new file mode 100644 index 00000000..103e3a4b --- /dev/null +++ b/api/v2/chat_channels_list.ts @@ -0,0 +1,14 @@ +import { request } from "../../utility/request"; + + + +const name = async () => { + const data = await request(`https://osu.ppy.sh/api/v2/chat/channels`, { + method: 'GET', + }); + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/chat_details.ts b/api/v2/chat_details.ts new file mode 100644 index 00000000..38c5ea74 --- /dev/null +++ b/api/v2/chat_details.ts @@ -0,0 +1,16 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (channel_id: number, addons?: IDefaultParams) => { + const data = await request(`https://osu.ppy.sh/api/v2/chat/channels/${channel_id}`, { + method: 'GET', + addons, + }); + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/chat_list.ts b/api/v2/chat_list.ts new file mode 100644 index 00000000..76ce1e22 --- /dev/null +++ b/api/v2/chat_list.ts @@ -0,0 +1,30 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (params: { + unreaded?: boolean; + sort?: 'date_desc' | 'date_asc'; +}, addons?: IDefaultParams) => { + let data = await request(`https://osu.ppy.sh/api/v2/chat/presence/`, { + method: 'GET', + addons + }); + + + if (params?.sort == 'date_asc') + data.sort((a: any, b: any) => a.last_message_id - b.last_message_id); + else + data.sort((a: any, b: any) => b.last_message_id - a.last_message_id); + + + if (params.unreaded == true) + data = data.filter((r: any) => r.last_read_id != r.last_message_id); + + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/chat_messages.ts b/api/v2/chat_messages.ts new file mode 100644 index 00000000..dfc236bf --- /dev/null +++ b/api/v2/chat_messages.ts @@ -0,0 +1,24 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (params: { + id: number; + limit?: number; + since?: number; + until?: number; + return_object?: boolean; +}, addons?: IDefaultParams) => { + const data = await request(`https://osu.ppy.sh/api/v2/chat/channels/${params.id}/messages`, { + method: 'GET', + params, + addons, + }); + + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/chat_updates.ts b/api/v2/chat_updates.ts new file mode 100644 index 00000000..623537b4 --- /dev/null +++ b/api/v2/chat_updates.ts @@ -0,0 +1,29 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (params: { + after_id: number; + includes: ('presence' | 'silences' | 'messages')[]; + history_since: number; +}, addons?: IDefaultParams) => { + const object = { + 'history_since': params.history_since, + 'includes[]': params.includes, + 'since': params.after_id, + }; + + + const data = await request(`https://osu.ppy.sh/api/v2/chat/updates`, { + method: 'GET', + params: object, + addons, + }); + + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/matches_details.ts b/api/v2/matches_details.ts new file mode 100644 index 00000000..e4e5e319 --- /dev/null +++ b/api/v2/matches_details.ts @@ -0,0 +1,17 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (match_id: number, addons?: IDefaultParams) => { + const data = await request(`https://osu.ppy.sh/api/v2/matches/${match_id}`, { + method: 'GET', + addons, + }); + + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/matches_list.ts b/api/v2/matches_list.ts new file mode 100644 index 00000000..814197fc --- /dev/null +++ b/api/v2/matches_list.ts @@ -0,0 +1,32 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (params: { + limit: number; + sort: 'id_desc' | 'id_asc', + /** + * Use cursor.match_id + */ + after_id: number; +}, addons?: IDefaultParams) => { + const object = { + limit: params.limit, + sort: params.sort, + 'cursor[match_id]': params.after_id, + }; + + + const data = await request(`https://osu.ppy.sh/api/v2/matches`, { + method: 'GET', + params: object, + addons, + }); + + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/me_details.ts b/api/v2/me_details.ts new file mode 100644 index 00000000..fddb940c --- /dev/null +++ b/api/v2/me_details.ts @@ -0,0 +1,19 @@ +import { IDefaultParams, Modes_names } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (addons?: IDefaultParams & { mode: Modes_names }) => { + let url = 'https://osu.ppy.sh/api/v2/me'; + if (addons?.mode) url += `/${addons.mode}`; + + const data = await request(url, { + method: 'GET', + addons, + }); + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/me_download_quota.ts b/api/v2/me_download_quota.ts new file mode 100644 index 00000000..a0ef864c --- /dev/null +++ b/api/v2/me_download_quota.ts @@ -0,0 +1,14 @@ +import { request } from "../../utility/request"; + + + +const name = async () => { + const data = await request(`https://osu.ppy.sh/api/v2/me/download-quota-check`, { + method: 'GET', + }); + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/me_friends.ts b/api/v2/me_friends.ts new file mode 100644 index 00000000..3f6a13e6 --- /dev/null +++ b/api/v2/me_friends.ts @@ -0,0 +1,16 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (addons?: IDefaultParams) => { + const data = await request(`https://osu.ppy.sh/api/v2/friends`, { + method: 'GET', + addons, + }); + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/notification_actions.ts b/api/v2/notification_actions.ts index 518f177c..9ad05c57 100644 --- a/api/v2/notification_actions.ts +++ b/api/v2/notification_actions.ts @@ -29,13 +29,11 @@ type Response = const name = async (params: T, addons?: IDefaultParams): Promise => { - const object: string[] = []; + const object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; let method = 'GET'; - return 'doesnt work'; - switch (params.type) { case 'mark_as_readed': url += '/notifications/mark-read'; @@ -46,14 +44,16 @@ const name = async (params: T, addons?: IDefaultParams): Promi if (Array.isArray(params.notifications)) { // const formData = postData(params.notifications); - // object.push(formData); + + object['notifications'] = params.notifications; }; if (Array.isArray(params.identities)) { // const formData = postData(params.identities); - // object.push(formData); + + object['identities'] = params.identities; }; break; }; @@ -61,13 +61,7 @@ const name = async (params: T, addons?: IDefaultParams): Promi const data = await request(url, { method: method, - headers: { - Accept: `application/json`, - "Content-Type": "application/x-www-form-urlencoded", - }, - // data: JSON.stringify(object), - - data: encodeURI(object.join('&')), + data: JSON.stringify(object), addons, }); diff --git a/api/v2/wiki_details.ts b/api/v2/wiki_details.ts new file mode 100644 index 00000000..7e2a5ed4 --- /dev/null +++ b/api/v2/wiki_details.ts @@ -0,0 +1,19 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (params: { + locale: string; + path_name: string; +}, addons?: IDefaultParams) => { + const data = await request(`https://osu.ppy.sh/api/v2/wiki/${params.locale}/${params.path_name}`, { + method: 'GET', + addons, + }); + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 5b3a9cf1..32b6b473 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -156,4 +156,61 @@ import spotlights_list from "../api/v2/spotlights_list"; export const spotlights = { list: spotlights_list, +}; + + + +import wiki_details from "../api/v2/wiki_details"; + + +export const wiki = { + details: wiki_details, +}; + + + +import me_details from "../api/v2/me_details"; +import me_friends from "../api/v2/me_friends"; +import me_download_quota from "../api/v2/me_download_quota"; + + +export const me = { + download_quota: me_download_quota, + friends: me_friends, + details: me_details, +}; + + + +import matches_list from "../api/v2/matches_list"; +import matches_details from "../api/v2/matches_details"; + + +export const matches = { + list: matches_list, + details: matches_details, +}; + + + +import chat_channels_list from "../api/v2/chat_channels_list"; +import chat_channels_actions from "../api/v2/chat_channels_actions"; + +import chat_list from "../api/v2/chat_list"; +import chat_messages from "../api/v2/chat_messages"; +import chat_updates from "../api/v2/chat_updates"; +import chat_details from "../api/v2/chat_details"; +import chat_actions from "../api/v2/chat_actions"; + + +export const chat = { + channels: { + list: chat_channels_list, + actions: chat_channels_actions, + }, + list: chat_list, + messages: chat_messages, + updates: chat_updates, + details: chat_details, + actions: chat_actions, }; \ No newline at end of file diff --git a/utility/request.ts b/utility/request.ts index e86c2519..dc724910 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -60,6 +60,13 @@ export const request: RequestType = (url, { method, headers, data, params = {}, // console.log({ url: build_url, method, headers, data }); const req = https.request(build_url, { method, headers }, (response) => { + const { location } = response.headers; + if (location) { + request(location, { method, headers, data, params, addons }) + .then(resolve) + .catch(reject); + return; + }; const chunks: any[] = []; // handle response events From a548986dc3ce79257fe5138930502e9511d5091d Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Tue, 27 Feb 2024 00:25:52 +0300 Subject: [PATCH 068/259] more 14/? --- api/v2/comments_actions.ts | 61 ++++++++++++++++++++++++++++----- api/v2/comments_list.ts | 12 +++---- api/v2/forums_topics_actions.ts | 6 +++- api/v2/notifications_list.ts | 2 +- api/v2/session_actions.ts | 50 +++++++++++++++++++++++++++ routes/v2.ts | 11 ++++++ 6 files changed, 125 insertions(+), 17 deletions(-) create mode 100644 api/v2/session_actions.ts diff --git a/api/v2/comments_actions.ts b/api/v2/comments_actions.ts index 0c6cd204..48cb20cb 100644 --- a/api/v2/comments_actions.ts +++ b/api/v2/comments_actions.ts @@ -3,10 +3,30 @@ import { IDefaultParams } from "../../types"; type params = ({ - type: 'difficulty'; + type: 'new'; + + commentable_type?: 'news_post' | 'beatmapset'; + id?: number; + parent_id?: string; + + message?: string; } | { - type: 'set'; - id: number; + type: 'edit'; + + id?: number; + message?: string; +} | { + type: 'delete'; + + id?: number; +} | { + type: 'vote'; + + id?: number; +} | { + type: 'unvote'; + + id?: number; }); @@ -19,20 +39,43 @@ type Response = const name = async (params: T, addons?: IDefaultParams): Promise | { error: string }> => { - return { error: 'lazer ...' }; const object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; - let method = 'GET'; + let method = 'POST'; switch (params.type) { - case 'difficulty': - url += `/beatmaps/lookup`; + case 'new': + url += `/comments`; + + if (params.commentable_type) object['comment[commentable_type]'] = params.commentable_type; + if (params.parent_id) object['comment[parent_id]'] = params.parent_id; + if (params.id) object['comment[commentable_id]'] = params.id; + if (params.message) object['comment[message]'] = params.message; + break; + + case 'edit': + url += `/comments/${params.id}`; + method = 'PUT'; + + object['comment[message]'] = params.message; + break; + + case 'delete': + url += `/comments/${params.id}`; + method = 'DELETE'; + + break; + + case 'vote': + url += `/comments/${params.id}/vote`; + method = 'POST'; break; - case 'set': - url += `/beatmaps/lookup`; + case 'unvote': + url += `/comments/${params.id}/vote`; + method = 'DELETE'; break; }; diff --git a/api/v2/comments_list.ts b/api/v2/comments_list.ts index bd384d0f..b0c5761b 100644 --- a/api/v2/comments_list.ts +++ b/api/v2/comments_list.ts @@ -4,22 +4,22 @@ import { request } from "../../utility/request"; const name = async (params: { - commentable_type?: 'news_post' | 'beatmapset'; + type?: 'news_post' | 'beatmapset' | 'Build'; + id?: string; - after_id: string; + parent_id?: string; + after_id?: string; - commentable_id?: string; cursor?: { id: number; created_at: string; }; - parent_id?: string, sort?: 'new' | 'old' | 'top'; }, addons?: IDefaultParams) => { const object = { after: params.after_id, - commentable_type: params.commentable_type, - commentable_id: params.commentable_id, + commentable_type: params.type, + commentable_id: params.id, 'cursor[id]': params.cursor?.id, 'cursor[created_at]': params.cursor?.created_at, parent_id: params.parent_id, diff --git a/api/v2/forums_topics_actions.ts b/api/v2/forums_topics_actions.ts index e95442b8..84afe88f 100644 --- a/api/v2/forums_topics_actions.ts +++ b/api/v2/forums_topics_actions.ts @@ -112,7 +112,11 @@ const name = async (params: T, addons?: IDefaultParams): Promi urls.push(`https://osu.ppy.sh/api/v2/forums/topics/${params.topic_id}`); methods.push('PUT'); - object['forum_topic[topic_title]'] = params.title; + object = { + forum_topic: { + 'topic_title': params.title, + }, + }; body.push(object); fields.push('topic'); diff --git a/api/v2/notifications_list.ts b/api/v2/notifications_list.ts index 07d5a423..eeabf4c1 100644 --- a/api/v2/notifications_list.ts +++ b/api/v2/notifications_list.ts @@ -13,7 +13,7 @@ const name = async (params: { addons, }); - if (params.unreaded_only == true) + if (params.unreaded_only == true && !('error' in data)) data.notifications = data.notifications.filter((r: any) => r.is_read == false); return data; diff --git a/api/v2/session_actions.ts b/api/v2/session_actions.ts new file mode 100644 index 00000000..e7140483 --- /dev/null +++ b/api/v2/session_actions.ts @@ -0,0 +1,50 @@ +import { request } from "../../utility/request"; +import { IDefaultParams } from "../../types"; + + +type params = ({ + type: 'verify'; +} | { + type: 'reissue'; +}); + + +type Response = + T extends 'difficulty' + ? any + : T extends 'difficulties' + ? any + : never; + + +const name = async (params: T, addons?: IDefaultParams): Promise> => { + const object: any = {}; + let url = 'https://osu.ppy.sh/api/v2'; + let method = 'POST'; + + + switch (params.type) { + case 'verify': + url += `/session/verify`; + + break; + + case 'reissue': + url += `/session/verify/reissue`; + + break; + }; + + + const data = await request(url, { + method: method, + params: object, + addons, + }); + + + return data as Response; +}; + + +export default name; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 32b6b473..c495b5c4 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -47,11 +47,13 @@ export const changelogs = { import comments_list from '../api/v2/comments_list'; import comments_details from '../api/v2/comments_details'; +import comments_actions from '../api/v2/comments_actions'; export const comments = { list: comments_list, details: comments_details, + actions: comments_actions, }; @@ -213,4 +215,13 @@ export const chat = { updates: chat_updates, details: chat_details, actions: chat_actions, +}; + + + +import session_actions from "../api/v2/session_actions"; + + +export const session = { + actions: session_actions, }; \ No newline at end of file From 871979fc16454d711bd81b9d5af073ebdd1c9bbd Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Tue, 27 Feb 2024 01:24:50 +0300 Subject: [PATCH 069/259] more 15/? --- api/v2/rooms_details.ts | 20 ++++++++++++++++++++ api/v2/rooms_list.ts | 42 +++++++++++++++++++++++++++++++++++++++++ routes/v2.ts | 11 +++++++++++ types/index.ts | 2 +- 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 api/v2/rooms_details.ts create mode 100644 api/v2/rooms_list.ts diff --git a/api/v2/rooms_details.ts b/api/v2/rooms_details.ts new file mode 100644 index 00000000..5fa908fd --- /dev/null +++ b/api/v2/rooms_details.ts @@ -0,0 +1,20 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (params: { + id: number | 'latest'; +}, addons?: IDefaultParams) => { + const data = await request(`https://osu.ppy.sh/api/v2/rooms/${params.id}`, { + method: 'GET', + params, + addons, + }); + + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/rooms_list.ts b/api/v2/rooms_list.ts new file mode 100644 index 00000000..7206daeb --- /dev/null +++ b/api/v2/rooms_list.ts @@ -0,0 +1,42 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (params: { + type?: 'playlists' | 'realtime'; + show?: 'all' | 'active' | 'ended' | 'participated' | 'owned'; + + query?: string; + + limit?: number; + sort?: 'ended' | 'created'; + + cursor_string?: string; +}, addons?: IDefaultParams) => { + const object = { + type_group: params.type, + mode: params.show, + sort: params.sort, + limit: params.limit, + cursor_string: params.cursor_string, + }; + + if (addons == null) + addons = { apiVersion: '99999999' } + + const data = await request(`https://osu.ppy.sh/api/v2/rooms`, { + method: 'GET', + params: object, + addons, + }); + + if (params?.query && !('error' in data)) + data.rooms = data.rooms.filter((r: any) => r.name.toLowerCase().includes(params.query.trim().toLowerCase())) + + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index c495b5c4..b991a423 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -224,4 +224,15 @@ import session_actions from "../api/v2/session_actions"; export const session = { actions: session_actions, +}; + + + +import rooms_list from "../api/v2/rooms_list"; +import rooms_details from "../api/v2/rooms_details"; + + +export const rooms = { + list: rooms_list, + details: rooms_details, }; \ No newline at end of file diff --git a/types/index.ts b/types/index.ts index 8fee6e64..e2d2a01c 100644 --- a/types/index.ts +++ b/types/index.ts @@ -1,6 +1,6 @@ export type IDefaultParams = { legacy_only?: boolean; - apiVersion?: '20240130' | ''; + apiVersion?: '20240130' | '99999999' | null | ''; /** * Only use it if you want to use user authKey to perform requests on their behave */ From 900ab7e7525e15af0a42b7ea0d10a36addd6fba2 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Tue, 27 Feb 2024 02:03:52 +0300 Subject: [PATCH 070/259] now only 1 route is left --- api/v2/rooms_leaderboard.ts | 20 ++++++++++ api/v2/rooms_scores.ts | 78 +++++++++++++++++++++++++++++++++++++ api/v2/session_actions.ts | 8 ++++ routes/v2.ts | 4 ++ utility/request.ts | 4 +- 5 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 api/v2/rooms_leaderboard.ts create mode 100644 api/v2/rooms_scores.ts diff --git a/api/v2/rooms_leaderboard.ts b/api/v2/rooms_leaderboard.ts new file mode 100644 index 00000000..2f5fd115 --- /dev/null +++ b/api/v2/rooms_leaderboard.ts @@ -0,0 +1,20 @@ +import { IDefaultParams } from "../../types"; +import { request } from "../../utility/request"; + + + +const name = async (params: { + id: number; + limit?: number; +}, addons?: IDefaultParams) => { + const data = await request(`https://osu.ppy.sh/api/v2/rooms/${params.id}/leaderboard`, { + method: 'GET', + params, + addons, + }); + + return data; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/rooms_scores.ts b/api/v2/rooms_scores.ts new file mode 100644 index 00000000..39baa460 --- /dev/null +++ b/api/v2/rooms_scores.ts @@ -0,0 +1,78 @@ +import { request } from "../../utility/request"; +import { IDefaultParams } from "../../types"; + + +type params = ({ + type: 'all'; + + id: number; + playlist_id: number; + + limit?: number; + sort?: 'score_asc' | 'score_desc'; + + cursor_string?: string; +} | { + type: 'single'; + + id: number; + playlist_id: number; + score_id: number; +} | { + type: 'user_highest'; + + id: number; + playlist_id: number; + user_id: number; +}); + + +type Response = + T extends 'difficulty' + ? any + : T extends 'difficulties' + ? any + : never; + + +const name = async (params: T, addons?: IDefaultParams): Promise> => { + let object: any = {}; + let url = 'https://osu.ppy.sh/api/v2'; + let method = 'GET'; + + + switch (params.type) { + case 'all': + url += `/rooms/${params.id}/playlist/${params.playlist_id}/scores`; + + object = { + limit: params.limit, + sort: params.sort, + cursor_string: params.cursor_string, + }; + break; + + case 'single': + url += `/rooms/${params.id}/playlist/${params.playlist_id}/scores/${params.score_id}`; + + break; + + case 'user_highest': + url += `/rooms/${params.id}/playlist/${params.playlist_id}/scores/users/${params.user_id}`; + + break; + }; + + + const data = await request(url, { + method: method, + params: object, + addons, + }); + + + return data as Response; +}; + + +export default name; \ No newline at end of file diff --git a/api/v2/session_actions.ts b/api/v2/session_actions.ts index e7140483..877c4f50 100644 --- a/api/v2/session_actions.ts +++ b/api/v2/session_actions.ts @@ -6,6 +6,8 @@ type params = ({ type: 'verify'; } | { type: 'reissue'; +} | { + type: 'delete'; }); @@ -32,6 +34,12 @@ const name = async (params: T, addons?: IDefaultParams): Promi case 'reissue': url += `/session/verify/reissue`; + break; + + case 'delete': + url += `/oauth/tokens/current`; + method = 'DELETE'; + break; }; diff --git a/routes/v2.ts b/routes/v2.ts index b991a423..cc5f89ff 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -230,9 +230,13 @@ export const session = { import rooms_list from "../api/v2/rooms_list"; import rooms_details from "../api/v2/rooms_details"; +import rooms_leaderboard from "../api/v2/rooms_leaderboard"; +import rooms_scores from "../api/v2/rooms_scores"; export const rooms = { list: rooms_list, + scores: rooms_scores, details: rooms_details, + leaderboard: rooms_leaderboard, }; \ No newline at end of file diff --git a/utility/request.ts b/utility/request.ts index dc724910..b75ce867 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -58,7 +58,7 @@ export const request: RequestType = (url, { method, headers, data, params = {}, const generate_query = querystring.encode(params); const build_url = url + (generate_query ? `?${generate_query}` : ''); - // console.log({ url: build_url, method, headers, data }); + // console.log({ url: build_url, method, headers, data, generate_query, params }); // debug const req = https.request(build_url, { method, headers }, (response) => { const { location } = response.headers; if (location) { @@ -67,6 +67,8 @@ export const request: RequestType = (url, { method, headers, data, params = {}, .catch(reject); return; }; + + // console.log(response.statusCode, response.statusMessage, response.headers.accept); // debug const chunks: any[] = []; // handle response events From 44656164e7ababfb230715986c09f019cb964258 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Tue, 27 Feb 2024 22:41:17 +0300 Subject: [PATCH 071/259] delete old v2 --- src/api/v2/index.ts | 425 ------------------ src/api/v2/routes/.pre | 29 -- .../v2/routes/assets/seasonalBackgrounds.ts | 30 -- .../v2/routes/beatmap/discussions/details.ts | 89 ---- .../v2/routes/beatmap/discussions/posts.ts | 71 --- .../v2/routes/beatmap/discussions/votes.ts | 77 ---- .../v2/routes/beatmap/set/addToFavourites.ts | 47 -- src/api/v2/routes/beatmaps/details.ts | 38 -- src/api/v2/routes/beatmaps/events.ts | 59 --- src/api/v2/routes/beatmaps/search.ts | 175 -------- src/api/v2/routes/changelogs/details.ts | 41 -- src/api/v2/routes/changelogs/list.ts | 64 --- src/api/v2/routes/changelogs/lookup.ts | 53 --- src/api/v2/routes/chat/channels/details.ts | 35 -- src/api/v2/routes/chat/channels/join.ts | 46 -- src/api/v2/routes/chat/channels/leave.ts | 46 -- src/api/v2/routes/chat/channels/list.ts | 28 -- .../v2/routes/chat/channels/messages/list.ts | 58 --- .../chat/channels/messages/markAsReaded.ts | 43 -- .../v2/routes/chat/channels/messages/send.ts | 48 -- src/api/v2/routes/chat/new.ts | 53 --- src/api/v2/routes/chat/updates.ts | 52 --- src/api/v2/routes/comments/details.ts | 34 -- src/api/v2/routes/comments/edit.ts | 42 -- src/api/v2/routes/comments/list.ts | 75 ---- src/api/v2/routes/comments/new.ts | 65 --- src/api/v2/routes/comments/remove.ts | 34 -- src/api/v2/routes/comments/vote.ts | 41 -- src/api/v2/routes/forums/post/edit.ts | 42 -- src/api/v2/routes/forums/topic/details.ts | 71 --- src/api/v2/routes/forums/topic/edit.ts | 77 ---- src/api/v2/routes/forums/topic/new.ts | 109 ----- src/api/v2/routes/forums/topic/reply.ts | 42 -- src/api/v2/routes/matches/details.ts | 34 -- src/api/v2/routes/matches/list.ts | 28 -- src/api/v2/routes/notifications/list.ts | 37 -- .../v2/routes/notifications/markAsReaded.ts | 47 -- src/api/v2/routes/room/details.ts | 33 -- src/api/v2/routes/room/leaderboard.ts | 33 -- src/api/v2/routes/rooms/list.ts | 67 --- src/api/v2/routes/scores/beatmap.ts | 59 --- src/api/v2/routes/scores/download.ts | 43 -- src/api/v2/routes/scores/user/beatmap.ts | 74 --- src/api/v2/routes/site/news/details.ts | 42 -- src/api/v2/routes/site/news/list.ts | 59 --- src/api/v2/routes/site/search.ts | 54 --- src/api/v2/routes/site/spotlights/list.ts | 29 -- src/api/v2/routes/site/wiki.ts | 41 -- src/api/v2/routes/user/activity.ts | 52 --- src/api/v2/routes/user/beatmaps/category.ts | 58 --- src/api/v2/routes/user/beatmaps/kudosu.ts | 52 --- .../v2/routes/user/beatmaps/most_played.ts | 52 --- src/api/v2/routes/user/details.ts | 50 --- src/api/v2/routes/user/me/details.ts | 35 -- src/api/v2/routes/user/me/download/quota.ts | 31 -- src/api/v2/routes/user/me/friends.ts | 29 -- src/api/v2/routes/users/details.ts | 38 -- src/api/v2/routes/users/groups/list.ts | 41 -- 58 files changed, 3357 deletions(-) delete mode 100644 src/api/v2/index.ts delete mode 100644 src/api/v2/routes/.pre delete mode 100644 src/api/v2/routes/assets/seasonalBackgrounds.ts delete mode 100644 src/api/v2/routes/beatmap/discussions/details.ts delete mode 100644 src/api/v2/routes/beatmap/discussions/posts.ts delete mode 100644 src/api/v2/routes/beatmap/discussions/votes.ts delete mode 100644 src/api/v2/routes/beatmap/set/addToFavourites.ts delete mode 100644 src/api/v2/routes/beatmaps/details.ts delete mode 100644 src/api/v2/routes/beatmaps/events.ts delete mode 100644 src/api/v2/routes/beatmaps/search.ts delete mode 100644 src/api/v2/routes/changelogs/details.ts delete mode 100644 src/api/v2/routes/changelogs/list.ts delete mode 100644 src/api/v2/routes/changelogs/lookup.ts delete mode 100644 src/api/v2/routes/chat/channels/details.ts delete mode 100644 src/api/v2/routes/chat/channels/join.ts delete mode 100644 src/api/v2/routes/chat/channels/leave.ts delete mode 100644 src/api/v2/routes/chat/channels/list.ts delete mode 100644 src/api/v2/routes/chat/channels/messages/list.ts delete mode 100644 src/api/v2/routes/chat/channels/messages/markAsReaded.ts delete mode 100644 src/api/v2/routes/chat/channels/messages/send.ts delete mode 100644 src/api/v2/routes/chat/new.ts delete mode 100644 src/api/v2/routes/chat/updates.ts delete mode 100644 src/api/v2/routes/comments/details.ts delete mode 100644 src/api/v2/routes/comments/edit.ts delete mode 100644 src/api/v2/routes/comments/list.ts delete mode 100644 src/api/v2/routes/comments/new.ts delete mode 100644 src/api/v2/routes/comments/remove.ts delete mode 100644 src/api/v2/routes/comments/vote.ts delete mode 100644 src/api/v2/routes/forums/post/edit.ts delete mode 100644 src/api/v2/routes/forums/topic/details.ts delete mode 100644 src/api/v2/routes/forums/topic/edit.ts delete mode 100644 src/api/v2/routes/forums/topic/new.ts delete mode 100644 src/api/v2/routes/forums/topic/reply.ts delete mode 100644 src/api/v2/routes/matches/details.ts delete mode 100644 src/api/v2/routes/matches/list.ts delete mode 100644 src/api/v2/routes/notifications/list.ts delete mode 100644 src/api/v2/routes/notifications/markAsReaded.ts delete mode 100644 src/api/v2/routes/room/details.ts delete mode 100644 src/api/v2/routes/room/leaderboard.ts delete mode 100644 src/api/v2/routes/rooms/list.ts delete mode 100644 src/api/v2/routes/scores/beatmap.ts delete mode 100644 src/api/v2/routes/scores/download.ts delete mode 100644 src/api/v2/routes/scores/user/beatmap.ts delete mode 100644 src/api/v2/routes/site/news/details.ts delete mode 100644 src/api/v2/routes/site/news/list.ts delete mode 100644 src/api/v2/routes/site/search.ts delete mode 100644 src/api/v2/routes/site/spotlights/list.ts delete mode 100644 src/api/v2/routes/site/wiki.ts delete mode 100644 src/api/v2/routes/user/activity.ts delete mode 100644 src/api/v2/routes/user/beatmaps/category.ts delete mode 100644 src/api/v2/routes/user/beatmaps/kudosu.ts delete mode 100644 src/api/v2/routes/user/beatmaps/most_played.ts delete mode 100644 src/api/v2/routes/user/details.ts delete mode 100644 src/api/v2/routes/user/me/details.ts delete mode 100644 src/api/v2/routes/user/me/download/quota.ts delete mode 100644 src/api/v2/routes/user/me/friends.ts delete mode 100644 src/api/v2/routes/users/details.ts delete mode 100644 src/api/v2/routes/users/groups/list.ts diff --git a/src/api/v2/index.ts b/src/api/v2/index.ts deleted file mode 100644 index 9f8f1b6d..00000000 --- a/src/api/v2/index.ts +++ /dev/null @@ -1,425 +0,0 @@ - -import user_activity, { description as user_activity_desc } from "./routes/user/activity"; -import user_details, { description as user_details_desc } from "./routes/user/details"; -import user_me_details, { description as user_me_details_desc } from "./routes/user/me/details"; -import user_me_friends, { description as user_me_friends_desc } from "./routes/user/me/friends"; -import user_me_download_quota, { description as user_me_download_quota_desc } from "./routes/user/me/download/quota"; -import user_beatmaps_category, { description as user_beatmaps_category_desc } from "./routes/user/beatmaps/category"; -import user_beatmaps_most_played, { description as user_beatmaps_most_played_desc } from "./routes/user/beatmaps/most_played"; -import user_beatmaps_kudosu, { description as user_beatmaps_kudosu_desc } from "./routes/user/beatmaps/kudosu"; - -export const user = { - activity: user_activity, - details: user_details, - - beatmaps: { - kudosu: user_beatmaps_kudosu, - category: user_beatmaps_category, - most_played: user_beatmaps_most_played, - }, - - me: { - details: user_me_details, - friends: user_me_friends, - download: { - quota: user_me_download_quota - } - }, -}; - - - -import users_details, { description as users_details_desc } from "./routes/users/details"; -import users_events, { description as users_events_desc } from "./routes/users/events"; -import users_groups_list, { description as users_groups_list_desc } from "./routes/users/groups/list"; - -export const users = { - details: users_details, - events: users_events, - groups: { - list: users_groups_list, - }, -}; - - - -import scores_details, { description as scores_details_desc } from "./routes/scores/details"; -import scores_download, { description as scores_download_desc } from "./routes/scores/download"; -import scores_user_category, { description as scores_user_category_desc } from "./routes/scores/user/category"; -import scores_user_beatmap, { description as scores_user_beatmap_desc } from "./routes/scores/user/beatmap"; -import scores_beatmap, { description as scores_beatmap_desc } from "./routes/scores/beatmap"; - -export const scores = { - details: scores_details, - download: scores_download, - - beatmap: scores_beatmap, - - user: { - category: scores_user_category, - beatmap: scores_user_beatmap, - }, -}; - - - -import beatmap_id_details, { description as beatmap_id_details_desc } from "./routes/beatmap/id/details"; -import beatmap_id_attributes, { description as beatmap_id_attributes_desc } from "./routes/beatmap/id/attributes"; -import beatmap_id_lookup, { description as beatmap_id_lookup_desc } from "./routes/beatmap/id/lookup"; -import beatmap_set_details, { description as beatmap_set_details_desc } from "./routes/beatmap/set/details"; -import beatmap_set_lookup, { description as beatmap_set_lookup_desc } from "./routes/beatmap/set/lookup"; -import beatmap_set_download, { description as beatmap_set_download_desc } from "./routes/beatmap/set/download"; -import beatmap_set_addToFavourites, { description as beatmap_set_addToFavourites_desc } from "./routes/beatmap/set/addToFavourites"; -import beatmap_discussions_details, { description as beatmap_discussions_details_desc } from "./routes/beatmap/discussions/details"; -import beatmap_discussions_posts, { description as beatmap_discussions_posts_desc } from "./routes/beatmap/discussions/posts"; -import beatmap_discussions_votes, { description as beatmap_discussions_votes_desc } from "./routes/beatmap/discussions/votes"; - -export const beatmap = { - id: { - attributes: beatmap_id_attributes, - lookup: beatmap_id_lookup, - details: beatmap_id_details, - }, - set: { - lookup: beatmap_set_lookup, - details: beatmap_set_details, - download: beatmap_set_download, - addToFavourites: beatmap_set_addToFavourites, - }, - discussions: { - votes: beatmap_discussions_votes, - posts: beatmap_discussions_posts, - details: beatmap_discussions_details, - }, -}; - - - -import beatmaps_details, { description as beatmaps_details_desc } from "./routes/beatmaps/details"; -import beatmaps_search, { description as beatmaps_search_desc } from "./routes/beatmaps/search"; -import beatmaps_events, { description as beatmaps_events_desc } from "./routes/beatmaps/events"; - -export const beatmaps = { - details: beatmaps_details, - search: beatmaps_search, - events: beatmaps_events, -}; - - - -import forums_topic_details, { description as forums_topic_details_desc } from "./routes/forums/topic/details"; -import forums_topic_edit, { description as forums_topic_edit_desc } from "./routes/forums/topic/edit"; -import forums_post_edit, { description as forums_post_edit_desc } from "./routes/forums/post/edit"; -import forums_topic_new, { description as forums_topic_new_desc } from "./routes/forums/topic/new"; -import forums_topic_reply, { description as forums_topic_reply_desc } from "./routes/forums/topic/reply"; -// import forums_topic_vote, { description as forums_topic_vote_desc } from "./routes/forums/topic/vote"; -// - -export const forums = { - topic: { - new: forums_topic_new, - edit: forums_topic_edit, - reply: forums_topic_reply, - // vote: forums_topic_vote, - details: forums_topic_details, - }, - post: { - edit: forums_post_edit - }, -}; - - - -import assets_seasonalBackgrounds, { description as assets_seasonalBackgrounds_desc } from "./routes/assets/seasonalBackgrounds"; - -export const assets = { - seasonalBackgrounds: assets_seasonalBackgrounds, -}; - - - -import changelogs_list, { description as changelogs_list_desc } from "./routes/changelogs/list"; -import changelogs_lookup, { description as changelogs_lookup_desc } from "./routes/changelogs/lookup"; -import changelogs_details, { description as changelogs_details_desc } from "./routes/changelogs/details"; - -export const changelogs = { - list: changelogs_list, - lookup: changelogs_lookup, - details: changelogs_details, -}; - - - -import comments_list, { description as comments_list_desc } from "./routes/comments/list"; -import comments_details, { description as comments_details_desc } from "./routes/comments/details"; -import comments_new, { description as comments_new_desc } from "./routes/comments/new"; -import comments_edit, { description as comments_edit_desc } from "./routes/comments/edit"; -import comments_remove, { description as comments_remove_desc } from "./routes/comments/remove"; -import comments_vote, { description as comments_vote_desc } from "./routes/comments/vote"; - -export const comments = { - new: comments_new, - edit: comments_edit, - list: comments_list, - vote: comments_vote, - remove: comments_remove, - details: comments_details, -}; - - - -import site_search, { description as site_search_desc } from "./routes/site/search"; -import site_wiki, { description as site_wiki_desc } from "./routes/site/wiki"; -import site_spotlights_list, { description as site_spotlights_list_desc } from "./routes/site/spotlights/list"; -import site_ranking_details, { description as site_ranking_details_desc } from "./routes/site/ranking/details"; -import site_news_list, { description as site_news_list_desc } from "./routes/site/news/list"; -import site_news_details, { description as site_news_details_desc } from "./routes/site/news/details"; - -export const site = { - search: site_search, - wiki: site_wiki, - spotlights: { - list: site_spotlights_list, - }, - ranking: { - details: site_ranking_details, - }, - news: { - list: site_news_list, - details: site_news_details, - }, -}; - - - -import matches_list, { description as matches_list_desc } from "./routes/matches/list"; -import matches_details, { description as matches_details_desc } from "./routes/matches/details"; -export const matches = { - list: matches_list, - details: matches_details, -}; - - - -import rooms_list, { description as rooms_list_desc } from "./routes/rooms/list"; - -export const rooms = { - list: rooms_list, -}; - - - -import room_details, { description as room_details_desc } from "./routes/room/details"; -import room_leaderboard, { description as room_leaderboard_desc } from "./routes/room/leaderboard"; - -export const room = { - details: room_details, - leaderboard: room_leaderboard, -}; - - - -import notifications_list, { description as notifications_list_desc } from "./routes/notifications/list"; -import notifications_markAsReaded, { description as notifications_markAsReaded_desc } from "./routes/notifications/markAsReaded"; - -export const notifications = { - list: notifications_list, - // markAsReaded: notifications_markAsReaded, // TODO: -}; - - - -import chat_channels_list, { description as chat_channels_list_desc } from "./routes/chat/channels/list"; -import chat_channels_details, { description as chat_channels_details_desc } from "./routes/chat/channels/details"; -import chat_channels_join, { description as chat_channels_join_desc } from "./routes/chat/channels/join"; -import chat_channels_leave, { description as chat_channels_leave_desc } from "./routes/chat/channels/leave"; -import chat_new, { description as chat_new_desc } from "./routes/chat/new"; -import chat_updates, { description as chat_updates_desc } from "./routes/chat/updates"; -import chat_channels_messages_list, { description as chat_channels_messages_list_desc } from "./routes/chat/channels/messages/list"; -import chat_channels_messages_send, { description as chat_channels_messages_send_desc } from "./routes/chat/channels/messages/send"; -import chat_channels_messages_markAsReaded, { description as chat_channels_messages_markAsReaded_desc } from "./routes/chat/channels/messages/markAsReaded"; - -export const chat = { - new: chat_new, - updates: chat_updates, - channels: { - list: chat_channels_list, - join: chat_channels_join, - leave: chat_channels_leave, - details: chat_channels_details, - messages: { - list: chat_channels_messages_list, - send: chat_channels_messages_send, - markAsReaded: chat_channels_messages_markAsReaded, - } - }, -}; - - - -export const description = { - user: { - activity: user_activity_desc, - details: user_details_desc, - - beatmaps: { - kudosu: user_beatmaps_kudosu_desc, - category: user_beatmaps_category_desc, - most_played: user_beatmaps_most_played_desc, - }, - - me: { - details: user_me_details_desc, - friends: user_me_friends_desc, - download: { - quota: user_me_download_quota_desc, - }, - }, - }, - users: { - details: users_details_desc, - events: users_events_desc, - groups: { - list: users_groups_list_desc, - }, - }, - scores: { - details: scores_details_desc, - download: scores_download_desc, - - beatmap: scores_beatmap_desc, - - user: { - category: scores_user_category_desc, - beatmap: scores_user_beatmap_desc, - }, - }, - beatmap: { - id: { - attributes: beatmap_id_attributes_desc, - lookup: beatmap_id_lookup_desc, - details: beatmap_id_details_desc, - }, - set: { - lookup: beatmap_set_lookup_desc, - details: beatmap_set_details_desc, - download: beatmap_set_download_desc, - addToFavourites: beatmap_set_addToFavourites_desc, - }, - discussions: { - votes: beatmap_discussions_votes_desc, - posts: beatmap_discussions_posts_desc, - details: beatmap_discussions_details_desc, - }, - }, - beatmaps: { - details: beatmaps_details_desc, - search: beatmaps_search_desc, - events: beatmaps_events_desc, - }, - forums: { - topic: { - new: forums_topic_new_desc, - edit: forums_topic_edit_desc, - reply: forums_topic_reply_desc, - // vote: forums_topic_vote_desc, - details: forums_topic_details_desc, - }, - post: { - edit: forums_post_edit_desc, - // details: forums_topic_details_desc, - }, - }, - assets: { - seasonalBackgrounds: assets_seasonalBackgrounds_desc, - }, - changelogs: { - list: changelogs_list_desc, - lookup: changelogs_lookup_desc, - details: changelogs_details_desc, - }, - comments: { - new: comments_new_desc, - edit: comments_edit_desc, - list: comments_list_desc, - vote: comments_vote_desc, - remove: comments_remove_desc, - details: comments_details_desc, - }, - site: { - search: site_search_desc, - wiki: site_wiki_desc, - spotlights: { - list: site_spotlights_list_desc, - }, - ranking: { - details: site_ranking_details_desc, - }, - news: { - list: site_news_list_desc, - details: site_news_details_desc, - }, - }, - matches: { - list: matches_list_desc, - details: matches_details_desc, - }, - rooms: { - list: rooms_list_desc, - }, - room: { - details: room_details_desc, - leaderboard: room_leaderboard_desc, - }, - notifications: { - list: notifications_list_desc, - markAsReaded: notifications_markAsReaded_desc, - }, - chat: { - new: chat_new_desc, - updates: chat_updates_desc, - channels: { - list: chat_channels_list_desc, - join: chat_channels_join_desc, - leave: chat_channels_leave_desc, - details: chat_channels_details_desc, - messages: { - list: chat_channels_messages_list_desc, - send: chat_channels_messages_send_desc, - markAsReaded: chat_channels_messages_markAsReaded_desc, - } - }, - }, -}; - - - -/* -POST /chat/ack -POST /chat/channels -GET /chat/presence - -POST /rooms -GET /rooms/{room}/playlist/{playlist}/scores/users/{user} -GET /rooms/{room}/playlist/{playlist}/scores -GET /rooms/{room}/playlist/{playlist}/scores/{score} -PUT /rooms/{room}/users/{user} -DELETE /rooms/{room}/users/{user} -POST /rooms/{room}/playlist/{playlist}/scores -PUT /rooms/{room}/playlist/{playlist}/scores/{score} - -POST /beatmaps/{beatmap}/solo/scores -PUT /beatmaps/{beatmap}/solo/scores/{token} - -POST /reports - - - - - - - - - - -*/ \ No newline at end of file diff --git a/src/api/v2/routes/.pre b/src/api/v2/routes/.pre deleted file mode 100644 index cb270775..00000000 --- a/src/api/v2/routes/.pre +++ /dev/null @@ -1,29 +0,0 @@ -import { types } from '../../../types/v2_users_details'; -import { Description } from '../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - -export const description: Description = { - auth: 3, - title: __filename, - method: 'GET', - description: '', - params: [ - - ], -}; - - -const name: types = async (obj) => { - const data = await request(``, { - method: 'GET', - params: obj, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/assets/seasonalBackgrounds.ts b/src/api/v2/routes/assets/seasonalBackgrounds.ts deleted file mode 100644 index d573c747..00000000 --- a/src/api/v2/routes/assets/seasonalBackgrounds.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { types } from '../../../../types/v2_assets_seasonalBackgrounds'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return array of seasonal backgrounds', - params: [ - ], - - return: 'response', -}; - - -const name: types = async () => { - const data = await request(`seasonal-backgrounds`, { - method: 'GET', - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/beatmap/discussions/details.ts b/src/api/v2/routes/beatmap/discussions/details.ts deleted file mode 100644 index f617aa63..00000000 --- a/src/api/v2/routes/beatmap/discussions/details.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { types } from '../../../../../types/v2_beatmap_discussions_details'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return details of beatmap discussion', - params: [ - { - name: 'object', - params: [ - { - type: 'number', - name: 'beatmap_id', - optional: true, - description: 'beatmap id', - }, - { - type: 'number', - name: 'beatmapset_id', - optional: true, - description: 'beatmapset id', - }, - { - type: 'string', - name: 'beatmapset_status', - optional: true, - description: '\`\`\`all\`\`\` or \`\`\`ranked\`\`\` or \`\`\`qualified\`\`\` or \`\`\`disqualified\`\`\` or \`\`\`never_qualified\`\`\` or \`\`\`loved\`\`\`', - }, - { - type: 'number', - name: 'limit', - optional: true, - description: 'Maximum number of results', - }, - { - type: 'string[]', - name: 'message_types', - optional: true, - description: '\`\`\`suggestion\`\`\` or \`\`\`problem\`\`\` or \`\`\`mapper_note\`\`\` or \`\`\`praise\`\`\` or \`\`\`hype\`\`\` or \`\`\`review\`\`\` or \`\`\`all\`\`\`', - }, - { - type: 'boolean', - name: 'only_unresolved', - optional: true, - description: '\`\`\`true\`\`\` or \`\`\`false\`\`\`', - }, - { - type: 'number', - name: 'page', - optional: true, - description: 'Search result page', - }, - { - type: 'string', - name: 'sort', - optional: true, - description: '\`\`\`id_desc\`\`\` or \`\`\`id_asc\`\`\`', - }, - { - type: 'number', - name: 'user', - optional: true, - description: 'id of the user', - }, - ] - } - ], -}; - - - -const name: types = async (obj) => { - const data = await request(`beatmapsets/discussions`, { - method: 'GET', - params: obj, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/beatmap/discussions/posts.ts b/src/api/v2/routes/beatmap/discussions/posts.ts deleted file mode 100644 index f1b78c31..00000000 --- a/src/api/v2/routes/beatmap/discussions/posts.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { types } from '../../../../../types/v2_beatmap_discussions_posts'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return posts from beatmap set discussions', - params: [ - { - name: 'object', - params: [ - { - type: 'number', - name: 'beatmapset_discussion_id', - optional: true, - description: 'id of beatmap set id', - }, - { - type: 'number', - name: 'limit', - optional: true, - description: 'Maximum number of results', - }, - { - type: 'number', - name: 'page', - optional: true, - description: 'Search page', - }, - { - type: 'string', - name: 'sort', - optional: true, - description: '\`\`\`id_desc\`\`\` or \`\`\`id_asc\`\`\`', - }, - { - type: 'string[]', - name: 'types', - optional: true, - description: '\`\`\`first\`\`\` or \`\`\`replay\`\`\` or \`\`\`system\`\`\`', - }, - { - type: 'number', - name: 'user', - optional: true, - description: 'id of the user', - }, - ], - }, - ], -}; - - - -const name: types = async (obj) => { - const data = await request(`beatmapsets/discussions/posts`, { - method: 'GET', - params: obj, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/beatmap/discussions/votes.ts b/src/api/v2/routes/beatmap/discussions/votes.ts deleted file mode 100644 index 7c084f58..00000000 --- a/src/api/v2/routes/beatmap/discussions/votes.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { types } from '../../../../../types/v2_beatmap_discussions_votes'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return votes (+discussions, users) from beatmap set discussions', - params: [ - { - name: 'object', - params: [ - { - type: 'number', - name: 'beatmapset_discussion_id', - optional: true, - description: 'id of beatmap set id', - }, - { - type: 'number', - name: 'limit', - optional: true, - description: 'Maximum number of results', - }, - { - type: 'number', - name: 'page', - optional: true, - description: 'Search page', - }, - { - type: 'number', - name: 'receiver', - optional: true, - description: 'id of the user', - }, - { - type: 'number', - name: 'score', - optional: true, - description: '\`\`\`1\`\`\` for up vote, \`\`\`-1\`\`\` for down vote', - }, - { - type: 'string', - name: 'sort', - optional: true, - description: '\`\`\`id_desc\`\`\` or \`\`\`id_asc\`\`\`', - }, - { - type: 'number', - name: 'user', - optional: true, - description: 'id of the user', - }, - ], - }, - ], -}; - - - -const name: types = async (obj) => { - const data = await request(`beatmapsets/discussions/votes`, { - method: 'GET', - params: obj, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/beatmap/set/addToFavourites.ts b/src/api/v2/routes/beatmap/set/addToFavourites.ts deleted file mode 100644 index eb156af8..00000000 --- a/src/api/v2/routes/beatmap/set/addToFavourites.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { types } from '../../../../../types/v2_beatmap_set_addToFavourites'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 0, - title: __filename, - method: 'POST', - description: 'Added specified beatmapset to favourite list', - params: [ - { - type: 'number', - name: 'beatmapset_id', - optional: false, - description: 'id of the beatmap set', - }, - { - type: 'boolean', - name: 'action', - optional: false, - description: 'true/false', - }, - ], -}; - - - -const name: types = async (beatmapset_id, action) => { - let _action = ''; - - if (action == true) _action = 'favourite'; - if (action == false) _action = 'unfavourite'; - - const data = await request(`beatmapsets/${beatmapset_id}/favourites`, { - method: 'POST', - params: { action: _action } - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/beatmaps/details.ts b/src/api/v2/routes/beatmaps/details.ts deleted file mode 100644 index f51173d4..00000000 --- a/src/api/v2/routes/beatmaps/details.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { types, response } from '../../../../types/v2_beatmaps_details'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return array of specified beatmaps (limit 50 beatmaps)', - params: [ - { - type: 'number[]', - name: 'ids', - optional: false, - description: 'Array of beatmap ids', - }, - ], -}; - - - -const name: types = async (ids) => { - const data = await request(`beatmaps`, { - method: 'GET', - params: { ids }, - }); - - if (data.beatmaps) return data.beatmaps; - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/beatmaps/events.ts b/src/api/v2/routes/beatmaps/events.ts deleted file mode 100644 index dd5f2f04..00000000 --- a/src/api/v2/routes/beatmaps/events.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { types } from '../../../../types/v2_beatmaps_events'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return list of beatmaps events (Nominations, bubbles and etc)', - params: [ - { - name: 'object', - params: [ - { - type: 'string/number', - name: 'user', - optional: true, - description: 'id of the user', - }, - { - type: 'string[]', - name: 'types', - optional: true, - description: '\`\`\`nominate\`\`\` or \`\`\`qualify\`\`\` or \`\`\`rank\`\`\` or \`\`\`love\`\`\` or \`\`\`nomination_reset\`\`\` or \`\`\`nomination_reset_received\`\`\` or \`\`\`disqualify\`\`\` or \`\`\`remove_from_loved\`\`\` or \`\`\`kudosu_gain\`\`\` or \`\`\`kudosu_lost\`\`\` or \`\`\`genre_edit\`\`\` or \`\`\`language_edit\`\`\` or \`\`\`nsfw_toggle\`\`\` or \`\`\`offset_edit\`\`\` or \`\`\`issue_resolve\`\`\` or \`\`\`issue_reopen\`\`\` or \`\`\`beatmap_owner_change\`\`\` or \`\`\`kudosu_allow\`\`\` or \`\`\`kudosu_deny\`\`\` or \`\`\`approve\`\`\` or \`\`\`kudosu_recalculate\`\`\` or \`\`\`discussion_delete\`\`\` or \`\`\`discussion_restore\`\`\` or \`\`\`discussion_post_delete\`\`\` or \`\`\`discussion_post_restore\`\`\`', - }, - { - type: 'string', - name: 'min_date', - optional: true, - description: 'Date from', - }, - { - type: 'string', - name: 'max_date', - optional: true, - description: 'Date to', - }, - ], - } - ], -}; - - - -const name: types = async (obj) => { - const data = await request(`beatmapsets/events`, { - method: 'GET', - params: obj, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/beatmaps/search.ts b/src/api/v2/routes/beatmaps/search.ts deleted file mode 100644 index 20d5b8cf..00000000 --- a/src/api/v2/routes/beatmaps/search.ts +++ /dev/null @@ -1,175 +0,0 @@ -import { types } from '../../../../types/v2_beatmaps_search'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - -const _mode = [ - 'osu', - 'taiko', - 'fruits', - 'mania' -]; - -const _genre = [ - '', - 'Unspecified', - 'Video Game', - 'Anime', - 'Rock', - 'Pop', - 'Other', - 'Novelty', - 'Hip Hop', - 'Electronic', - 'Metal', - 'Classical', - 'Folk', - 'Jazz', -]; - -const _language = [ - 'English', - 'Chinese', - 'French', - 'German', - 'Italian', - 'Japanese', - 'Korean', - 'Spanish', - 'Swedish', - 'Russian', - 'Polish', - 'Instrumental', - 'Unspecified', - 'Other', -]; - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return list of beatmaps', - params: [ - { - name: 'object', - params: [ - { - type: 'string', - name: 'query', - optional: true, - description: 'search query, song \`\`title\`\` / \`\`artist\`\`, \`\`stars\`\`, \`\`bpm\`\`, \`\`date\`\` and etc.', - }, - { - type: 'string', - name: 'sort', - optional: true, - description: '\`\`\`title_desc\`\`\` or \`\`\`title_asc\`\`\` or \`\`\`artist_desc\`\`\` or \`\`\`artist_asc\`\`\` or \`\`\`difficulty_desc\`\`\` or \`\`\`difficulty_asc\`\`\` or \`\`\`updated_desc\`\`\` or \`\`\`updated_asc\`\`\` or \`\`\`ranked_desc\`\`\` or \`\`\`ranked_asc\`\`\` or \`\`\`rating_desc\`\`\` or \`\`\`rating_asc\`\`\` or \`\`\`plays_desc\`\`\` or \`\`\`plays_asc\`\`\` or \`\`\`favourites_desc\`\`\` or \`\`\`favourites_asc\`\`\`', - }, - { - type: 'string[]', - name: 'general', - optional: true, - description: '\`\`\`converts\`\`\` or \`\`\`follows\`\`\` or \`\`\`recommended\`\`\` or \`\`\`\`featured_artists\`\`\`\` or \`\`\`\`spotlights\`\`\`\`', - }, - { - type: 'string', - name: 'mode', - optional: true, - description: '\`\`\`osu\`\`\` or \`\`\`fruits\`\`\` or \`\`\`mania\`\`\` or \`\`\`taiko\`\`\`', - }, - { - type: 'string', - name: 'section', - optional: true, - description: '\`\`\`ranked\`\`\` or \`\`\`qualified\`\`\` or \`\`\`loved\`\`\` or \`\`\`favourites\`\`\` or \`\`\`pending\`\`\` or \`\`\`wip\`\`\` or \`\`\`graveyard\`\`\` or \`\`\`mine\`\`\`', - }, - { - type: 'string', - name: 'genre', - optional: true, - description: '\`\`\`Unspecified\`\`\` or \`\`\`Video Game\`\`\` or \`\`\`Anime\`\`\` or \`\`\`Rock\`\`\` or \`\`\`Pop\`\`\` or \`\`\`Other\`\`\` or \`\`\`Novelty\`\`\` or \`\`\`Hip Hop\`\`\` or \`\`\`Electronic\`\`\` or \`\`\`Metal\`\`\` or \`\`\`Classical\`\`\` or \`\`\`Folk\`\`\` or \`\`\`Jazz\`\`\`', - }, - { - type: 'string', - name: 'language', - optional: true, - description: '\`\`\`English\`\`\` or \`\`\`Chinese\`\`\` or \`\`\`French\`\`\` or \`\`\`German\`\`\` or \`\`\`Italian\`\`\` or \`\`\`Japanese\`\`\` or \`\`\`Korean\`\`\` or \`\`\`Spanish\`\`\` or \`\`\`Swedish\`\`\` or \`\`\`Russian\`\`\` or \`\`\`Polish\`\`\` or \`\`\`Instrumental\`\`\` or \`\`\`Unspecified\`\`\` or \`\`\`Other\`\`\`', - }, - { - type: 'string', - name: 'include', - optional: true, - description: '\`\`\`video\`\`\` or \`\`\`storyboard\`\`\`', - }, - { - type: 'string[]', - name: 'rank', - optional: true, - description: '\`\`\`XH\`\`\` or \`\`\`X\`\`\` or \`\`\`SH\`\`\` or \`\`\`S\`\`\` or \`\`\`A\`\`\` or \`\`\`B\`\`\` or \`\`\`C\`\`\` or \`\`\`D\`\`\`', - }, - { - type: 'boolean', - name: 'nfsw', - optional: true, - description: '\`\`\`true\`\`\` or \`\`\`false\`\`\`', - }, - { - type: 'string', - name: 'played', - optional: true, - description: '\`\`\`played\`\`\` or \`\`\`unplayed\`\`\`' - }, - { - type: 'string', - name: 'cursor_string', - optional: true, - description: 'Pagination cursor' - }, - ] - } - ], - notes: [ - { - params: ['nsfw'], - description: 'Those parameters require to login via lazer', - } - ], -}; - - - -const name: types = async (filters) => { - const obj: any = {}; - - if (filters) { - if (filters.query) obj.q = filters.query; - if (filters.general) obj.c = filters.general.toString().split(',').join('.'); - if (filters.mode) obj.m = _mode.indexOf(filters.mode).toString(); - if (filters.section) obj.s = filters.section; - if (filters.nfsw) obj.nsfw = ''; - else obj.nsfw = false; - if (filters.genre) obj.g = _genre.indexOf(filters.genre).toString(); - if (filters.language) obj.l = _language.indexOf(filters.language).toString(); - if (filters.include) obj.e = filters.include.toString().split(',').join('.'); - if (filters.rank) obj.r = filters.rank.toString().split(',').join('.'); - - if (filters.sort) obj.sort = filters.sort; - if (filters.cursor_string) obj.cursor_string = filters.cursor_string; - if (filters.played) obj.played = filters.played; - } - const data = await request(`beatmapsets/search/`, { - method: 'GET', - params: obj, - }); - - // console.log(obj); - - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/changelogs/details.ts b/src/api/v2/routes/changelogs/details.ts deleted file mode 100644 index 82afbbe2..00000000 --- a/src/api/v2/routes/changelogs/details.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { types } from '../../../../types/v2_changelogs_details'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Returns details of the specified build', - params: [ - { - type: 'string', - name: 'stream', - optional: false, - description: '\`\`\`stable40\`\`\` or \`\`\`stable\`\`\` or \`\`\`beta40\`\`\` or \`\`\`cuttingedge\`\`\` or \`\`\`lazer\`\`\` or \`\`\`web\`\`\`', - }, - { - type: 'string', - name: 'build', - options: false, - optional: false, - description: '\`\`\`id\`\`\` or \`\`\`name\`\`\` of the build', - }, - ], -}; - - -const name: types = async (stream, build) => { - const data = await request(`changelog/${stream}/${build}`, { - method: 'GET', - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/changelogs/list.ts b/src/api/v2/routes/changelogs/list.ts deleted file mode 100644 index 26b6e07e..00000000 --- a/src/api/v2/routes/changelogs/list.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { types } from '../../../../types/v2_changelogs_list'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Returns a listing of update streams, builds, and changelog entries', - params: [ - { - name: 'object', - params: [ - { - type: 'string', - name: 'from', - optional: true, - description: 'Minimum build version', - }, - { - type: 'string', - name: 'to', - optional: true, - description: 'Maximum build version', - }, - { - type: 'number', - name: 'max_id', - optional: true, - description: 'Maximum build ID', - }, - { - type: 'string', - name: 'stream', - optional: true, - description: '\`\`\`stable40\`\`\` or \`\`\`stable\`\`\` or \`\`\`beta40\`\`\` or \`\`\`cuttingedge\`\`\` or \`\`\`lazer\`\`\` or \`\`\`web\`\`\`', - }, - { - type: 'string[]', - name: 'message_formats', - optional: true, - description: '\`\`\`html\`\`\` or \`\`\`markdown\`\`\`', - }, - ], - } - ], -}; - - -const name: types = async (obj) => { - const data = await request(`changelog`, { - method: 'GET', - params: obj, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/changelogs/lookup.ts b/src/api/v2/routes/changelogs/lookup.ts deleted file mode 100644 index 50625769..00000000 --- a/src/api/v2/routes/changelogs/lookup.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { types } from '../../../../types/v2_changelogs_lookup'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Returns details of the specified build', - params: [ - { - type: 'string/number', - name: 'changelog', - optional: false, - description: 'Build version, update stream name, or build ID', - }, - { - name: 'object', - params: [ - { - type: 'string', - name: 'key', - options: false, - optional: false, - description: 'Unset to query by build version or stream name, or \`\`\`id\`\`\` to query by build ID.', - }, - { - type: 'string[]', - name: 'message_formats', - optional: false, - description: '\`\`\`html\`\`\` or \`\`\`markdown\`\`\`', - }, - ] - }, - ], -}; - - -const name: types = async (changelog, obj) => { - const data = await request(`changelog/${changelog}`, { - method: 'GET', - params: obj, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/chat/channels/details.ts b/src/api/v2/routes/chat/channels/details.ts deleted file mode 100644 index da30b9fb..00000000 --- a/src/api/v2/routes/chat/channels/details.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { types } from '../../../../../types/v2_chat_channels_details'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 0, - title: __filename, - method: 'GET', - description: 'Return details about specified channel (only channel that you joined to)', - params: [ - { - type: 'number', - name: 'channel', - optional: true, - description: 'id of the channel', - }, - ], - return: 'response', -}; - - -const name: types = async (channel) => { - const data = await request(`chat/channels/${channel}`, { - method: 'GET', - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/chat/channels/join.ts b/src/api/v2/routes/chat/channels/join.ts deleted file mode 100644 index e84a5994..00000000 --- a/src/api/v2/routes/chat/channels/join.ts +++ /dev/null @@ -1,46 +0,0 @@ -// import { types } from '../../../../../types/v2_chat_channels_join'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - -export const description: Description = { - auth: 0, - title: __filename, - method: 'GET', - description: 'Join channel by id', - params: [ - { - type: 'number', - name: 'channel_id', - optional: false, - description: 'Channel id', - }, - { - type: 'number', - name: 'user_id', - optional: false, - description: 'User id', - } - ], - return: 'response', -}; - -export interface types { - (channel_id: number, user_id: number): Promise<{ - - }[]>; -}; - - -const name: types = async (channel_id, user_id) => { - const data = await request(`chat/channels/${channel_id}/users/${user_id}`, { - method: 'PUT', - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/chat/channels/leave.ts b/src/api/v2/routes/chat/channels/leave.ts deleted file mode 100644 index 6da73477..00000000 --- a/src/api/v2/routes/chat/channels/leave.ts +++ /dev/null @@ -1,46 +0,0 @@ -// import { types } from '../../../../../types/v2_chat_channels_join'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - -export const description: Description = { - auth: 0, - title: __filename, - method: 'GET', - description: 'Remove channel by id', - params: [ - { - type: 'number', - name: 'channel_id', - optional: false, - description: 'Channel id', - }, - { - type: 'number', - name: 'user_id', - optional: false, - description: 'User id', - } - ], - return: 'response', -}; - -export interface types { - (channel_id: number, user_id: number): Promise<{ - - }[]>; -}; - - -const name: types = async (channel_id, user_id) => { - const data = await request(`chat/channels/${channel_id}/users/${user_id}`, { - method: 'DELETE', - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/chat/channels/list.ts b/src/api/v2/routes/chat/channels/list.ts deleted file mode 100644 index 0c3b4831..00000000 --- a/src/api/v2/routes/chat/channels/list.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { types } from '../../../../../types/v2_chat_channels_list'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 0, - title: __filename, - method: 'GET', - description: 'Return list of channels', - params: [], - return: 'response', -}; - - -const name: types = async () => { - const data = await request(`chat/channels`, { - method: 'GET', - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/chat/channels/messages/list.ts b/src/api/v2/routes/chat/channels/messages/list.ts deleted file mode 100644 index a8235c3c..00000000 --- a/src/api/v2/routes/chat/channels/messages/list.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { types } from '../../../../../../types/v2_chat_channels_messages_list'; -import { Description } from '../../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 0, - title: __filename, - method: 'GET', - description: 'Return chat messages for a specific channel', - params: [ - { - type: 'number', - name: 'channel_id', - optional: false, - description: 'id of the channel', - }, - { - name: 'object', - params: [ - { - type: 'number', - name: 'limit', - optional: true, - description: 'Maximum number of results (Max 50)', - }, - { - type: 'number', - name: 'since', - optional: true, - description: 'Messages after the specified message id will be returned', - }, - { - type: 'number', - name: 'until', - optional: true, - description: 'Messages up to but not including the specified message id will be returned', - }, - ] - }, - ], -}; - - -const name: types = async (channel_id, object) => { - const data = await request(`chat/channels/${channel_id}/messages`, { - method: 'GET', - params: object, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/chat/channels/messages/markAsReaded.ts b/src/api/v2/routes/chat/channels/messages/markAsReaded.ts deleted file mode 100644 index 51678161..00000000 --- a/src/api/v2/routes/chat/channels/messages/markAsReaded.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { types } from '../../../../../../types/v2_chat_channels_messages_markAsReaded'; -import { Description } from '../../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 0, - title: __filename, - method: 'PUT', - description: 'This endpoint marks the channel as having being read up to the given \`\`\`message_id\`\`\`', - params: [ - { - type: 'number', - name: 'channel_id', - options: false, - optional: true, - description: 'The \`\`\`channel_id\`\`\` of the channel to mark as read', - }, - { - type: 'number', - name: 'message_id', - options: false, - optional: true, - description: 'The \`\`\`message_id\`\`\` of the message to mark as read up to', - }, - ], -}; - - -const name: types = async (channel_id, message_id) => { - const data = await request(`chat/channels/${channel_id}/mark-as-read/${message_id}`, { - method: 'PUT', - params: { channel_id, message_id } - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/chat/channels/messages/send.ts b/src/api/v2/routes/chat/channels/messages/send.ts deleted file mode 100644 index e9fa7ea1..00000000 --- a/src/api/v2/routes/chat/channels/messages/send.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { types } from '../../../../../../types/v2_chat_channels_messages_send'; -import { Description } from '../../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 0, - title: __filename, - method: 'GET', - description: 'Send message to chat channel', - params: [ - { - type: 'number', - name: 'channel_id', - optional: false, - description: 'The channel_id of the channel to send message to', - }, - { - type: 'number', - name: 'message', - optional: false, - description: 'Message to send', - }, - { - type: 'number', - name: 'is_action', - optional: false, - description: 'Whether the message is an action', - }, - ], - return: 'response', -}; - - -const name: types = async (channel_id, message, is_action) => { - const data = await request(`chat/channels/${channel_id}/messages`, { - method: 'POST', - data: JSON.stringify({ message, is_action }), - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/chat/new.ts b/src/api/v2/routes/chat/new.ts deleted file mode 100644 index 1b6c4f08..00000000 --- a/src/api/v2/routes/chat/new.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { types } from '../../../../types/v2_chat_new'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - -export const description: Description = { - auth: 3, - title: __filename, - method: 'GET', - description: 'Send new message to user', - params: [ - { - type: 'string', - name: 'target_id', - optional: false, - description: 'User id to start PM with', - }, - { - type: 'string', - name: 'message', - optional: false, - description: 'message to send', - }, - { - type: 'boolean', - name: 'is_action', - optional: true, - description: 'whether the message is an action', - }, - { - type: 'string', - name: 'uuid', - optional: true, - description: 'client-side message identifier which will be sent back in response and websocket json', - }, - ], - return: 'response', -}; - - -const name: types = async (target_id, message, is_action, uuid) => { - const data = await request(`chat/new`, { - method: 'POST', - data: JSON.stringify({ target_id, message, is_action, uuid }), - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/chat/updates.ts b/src/api/v2/routes/chat/updates.ts deleted file mode 100644 index 6de8ab95..00000000 --- a/src/api/v2/routes/chat/updates.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { types } from '../../../../types/v2_chat_updates'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - -export const description: Description = { - auth: 0, - title: __filename, - method: 'GET', - description: `This endpoint returns new messages since the given message_id along with updated channel 'presence' data.`, - params: [ - { - name: 'object', - params: [ - { - type: 'number', - name: 'history_since', - optional: true, - description: 'UserSilence after the specified id to return', - }, - { - type: 'string[]', - name: 'includes', - optional: true, - description: '\`\`\`presence\`\`\`, \`\`\`messages\`\`\`, \`\`\`silences\`\`\`', - }, - { - type: 'number', - name: 'since', - optional: false, - description: 'Messages after the specified message_id to return', - }, - ], - } - ], - return: 'response', -}; - - -const name: types = async (obj) => { - const data = await request(`chat/updates`, { - method: 'GET', - params: { ...obj }, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/comments/details.ts b/src/api/v2/routes/comments/details.ts deleted file mode 100644 index c1fa5df7..00000000 --- a/src/api/v2/routes/comments/details.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { types } from '../../../../types/v2_comments_details'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Gets a comment and its replies up to 2 levels deep', - params: [ - { - type: 'number', - name: 'comment', - optional: false, - description: 'id of the comment', - }, - ], -}; - - -const name: types = async (comment) => { - const data = await request(`comments/${comment}`, { - method: 'GET', - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/comments/edit.ts b/src/api/v2/routes/comments/edit.ts deleted file mode 100644 index 008d0869..00000000 --- a/src/api/v2/routes/comments/edit.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { types } from '../../../../types/v2_comments_edit'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Edit your comment by id', - params: [ - { - type: 'number', - name: 'comment_id', - description: 'Comment id', - }, - { - type: 'string', - name: 'message', - description: 'Text of the message', - }, - ], - return: 'response', -}; - - -const name: types = async (comment_id, message) => { - const data = await request(`comments/${comment_id}`, { - method: 'PUT', - params: { - 'comment[message]': message, - }, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/comments/list.ts b/src/api/v2/routes/comments/list.ts deleted file mode 100644 index 935e10e6..00000000 --- a/src/api/v2/routes/comments/list.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { types } from '../../../../types/v2_comments_list'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Returns a list comments and their replies up to 2 levels deep', - params: [ - { - name: 'object', - params: [ - { - type: 'string', - name: 'commentable_type', - optional: true, - description: '\`\`\`news_post\`\`\` or \`\`\`beatmapset\`\`\`', - }, - { - type: 'string', - name: 'commentable_id', - optional: true, - description: 'id of the resource to get comments for', - }, - { - name: 'cursor', - params: [ - { - type: 'number', - name: 'id', - optional: true, - description: '', - }, - { - type: 'string', - name: 'created_at', - optional: true, - description: '', - }, - ] - }, - { - type: 'string', - name: 'parent_id', - optional: true, - description: 'id of the comment parent', - }, - { - type: 'string', - name: 'sort', - optional: true, - description: '\`\`\`new\`\`\` or \`\`\`old\`\`\` or \`\`\`top\`\`\`', - }, - ], - } - ], -}; - - -const name: types = async (obj) => { - const data = await request(`comments`, { - method: 'GET', - params: obj, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/comments/new.ts b/src/api/v2/routes/comments/new.ts deleted file mode 100644 index fd88d5a4..00000000 --- a/src/api/v2/routes/comments/new.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { types } from '../../../../types/v2_comments_new'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Posts a new comment to a comment thread', - params: [ - { - name: 'comment', - params: [ - { - type: 'string', - name: 'commentable_id', - optional: true, - description: 'Resource ID the comment thread is attached to', - }, - { - type: 'string', - name: 'commentable_type', - optional: true, - description: '\`\`\`news_post\`\`\` or \`\`\`beatmapset\`\`\`', - }, - { - type: 'string', - name: 'message', - optional: true, - description: 'Text of the comment', - }, - { - type: 'string', - name: 'parent_id', - optional: true, - description: 'The id of the comment to reply to, null if not a reply', - }, - ], - } - ], - return: 'response', -}; - - -const name: types = async (object) => { - const obj: any = {}; - if (object.commentable_id) obj['comment[commentable_id]'] = object.commentable_id; - if (object.commentable_type) obj['comment[commentable_type]'] = object.commentable_type; - if (object.message) obj['comment[message]'] = object.message; - if (object.parent_id) obj['comment[parent_id]'] = object.parent_id; - - const data = await request(`comments`, { - method: 'POST', - params: obj, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/comments/remove.ts b/src/api/v2/routes/comments/remove.ts deleted file mode 100644 index 87279bcf..00000000 --- a/src/api/v2/routes/comments/remove.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { types } from '../../../../types/v2_comments_remove'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Delete your comment by id', - params: [ - { - type: 'number', - name: 'comment_id', - description: 'Comment id', - } - ], - return: 'response', -}; - - -const name: types = async (comment_id) => { - const data = await request(`comments/${comment_id}`, { - method: 'DELETE', - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/comments/vote.ts b/src/api/v2/routes/comments/vote.ts deleted file mode 100644 index 7582d56d..00000000 --- a/src/api/v2/routes/comments/vote.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { types } from '../../../../types/v2_comments_vote'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Delete your comment by id', - params: [ - { - type: 'number', - name: 'comment_id', - description: 'Comment id', - }, - { - type: 'boolean', - name: 'type', - options: false, - description: '\`\`\`true\`\`\` (Upvote) or \`\`\`false\`\`\` (Downvote)', - }, - - ], - return: 'response', -}; - - -const name: types = async (comment_id, type) => { - const data = await request(`comments/${comment_id}/vote`, { - method: type == true ? 'POST' : 'DELETE', - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/forums/post/edit.ts b/src/api/v2/routes/forums/post/edit.ts deleted file mode 100644 index 881d6e3b..00000000 --- a/src/api/v2/routes/forums/post/edit.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { types } from '../../../../../types/v2_forums_post_edit'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 0, - title: __filename, - method: 'GET', - description: '', - params: [ - { - type: 'number', - name: 'post_id', - optional: false, - description: 'Post id', - }, - { - type: 'number', - name: 'body', - optional: false, - description: 'Body of the post', - }, - ], - return: 'response', -}; - - -const name: types = async (post_id, body) => { - const data = await request(`forums/posts/${post_id}`, { - method: 'PUT', - data: JSON.stringify({ body }), - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/forums/topic/details.ts b/src/api/v2/routes/forums/topic/details.ts deleted file mode 100644 index 25bfb238..00000000 --- a/src/api/v2/routes/forums/topic/details.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { types } from '../../../../../types/v2_forums_topic_details'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return topic data and posts list', - params: [ - { - type: 'number', - name: 'topic', - optional: false, - description: 'Topic id', - }, - { - name: 'object', - params: [ - { - type: 'string', - name: 'cursor_string', - optional: true, - description: 'Parameter for pagination', - }, - { - type: 'string', - name: 'sort', - optional: true, - description: '\`\`\`id_asc\`\`\` or \`\`\`id_desc\`\`\`', - }, - { - type: 'number', - name: 'limit', - optional: true, - description: 'Maximum number of posts to be returned (20 default, 50 at most)', - }, - { - type: 'string', - name: 'start', - optional: true, - description: 'First post id to be returned with sort set to id_asc. This parameter is ignored if cursor_string is specified', - }, - { - type: 'string', - name: 'end', - optional: true, - description: 'Last post id to be returned with sort set to id_desc. This parameter is ignored if cursor_string is specified.', - }, - ] - }, - ], -}; - - - -const name: types = async (topic, obj) => { - const data = await request(`forums/topics/${topic}`, { - method: 'GET', - params: obj, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/forums/topic/edit.ts b/src/api/v2/routes/forums/topic/edit.ts deleted file mode 100644 index 0680d395..00000000 --- a/src/api/v2/routes/forums/topic/edit.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { types, response } from '../../../../../types/v2_forums_topic_edit'; -import { response as topic_types } from '../../../../../types/v2_forums_topic_details'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 0, - title: __filename, - method: 'GET', - description: 'Edit your topic and post from the forum', - params: [ - { - type: 'number', - name: 'topic_id', - optional: false, - description: 'Topic id', - }, - { - name: 'object', - params: [ - { - type: 'string', - name: 'title', - optional: true, - description: 'New title', - }, - { - type: 'string', - name: 'body', - optional: true, - description: 'New body', - }, - ], - }, - ], - return: 'response', -}; - - -const name: types = async (topic_id, object) => { - const post: topic_types = await request(`forums/topics/${topic_id}`, { - method: 'GET', - }); - - const response: any = {}; - - if (object.title) { - const data = await request(`forums/topics/${topic_id}`, { - method: 'PUT', - data: JSON.stringify({ - "forum_topic[topic_title]": post.topic.title, - }), - }); - - response.title = data; - }; - - if (object.body) { - const data = await request(`forums/posts/${post.topic.first_post_id}`, { - method: 'PUT', - data: JSON.stringify({ - body: post.posts[0].body.raw, - }) - }); - - response.body = data; - }; - - return response; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/forums/topic/new.ts b/src/api/v2/routes/forums/topic/new.ts deleted file mode 100644 index 820e1db9..00000000 --- a/src/api/v2/routes/forums/topic/new.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { types } from '../../../../../types/v2_forums_topic_new'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 0, - title: __filename, - method: 'GET', - description: 'Edit your topic and post from the forum', - params: [ - { - type: 'number', - name: 'forum_id', - optional: false, - description: 'Forum id', - }, - { - name: 'object', - params: [ - { - type: 'string', - name: 'title', - optional: false, - description: 'Title of the topic', - }, - { - type: 'string', - name: 'body', - optional: false, - description: 'Body of the topic', - }, - ], - }, - { - name: 'poll', - params: [ - { - type: 'string', - name: 'title', - optional: false, - description: 'Title of the poll.', - }, - { - type: 'string[]', - name: 'options', - optional: false, - description: 'Newline-separated list of voting options. BBCode is supported.', - }, - { - type: 'boolean', - name: 'hide_results', - optional: true, - description: 'Hide results of the poll until voting period ends', - }, - { - type: 'number', - name: 'length_days', - optional: true, - description: 'Number of days for voting period. 0 means the voting will never ends (default: 0). This parameter is required if hide_results option is enabled.', - }, - { - type: 'number', - name: 'max_options', - optional: true, - description: 'This is the number of options each user may select when voting.', - }, - { - type: 'boolean', - name: 'vote_change', - optional: true, - description: 'Enable this to allow user to change their votes (default: false).', - }, - ], - }, - ], - return: 'response', -}; - - -const name: types = async (forum_id, object, poll) => { - const obj: any = { forum_id }; - if (object.title) obj.title = object.title; - if (object.body) obj.body = object.body; - - if (poll != null) obj.with_poll = true; - - if (poll) { - if (poll.title) obj['forum_topic_poll[title]'] = poll.title; - if (poll.options) obj['forum_topic_poll[options]'] = poll.options.toString().split(',').join('%0D%0A'); - if (poll.hide_results) obj['forum_topic_poll[hide_results]'] = poll.hide_results; - if (poll.length_days) obj['forum_topic_poll[length_days]'] = poll.length_days; - if (poll.max_options) obj['forum_topic_poll[max_options]'] = poll.max_options; - if (poll.vote_change) obj['forum_topic_poll[vote_change]'] = poll.vote_change; - }; - - const data = await request(`forums/topics`, { - method: 'POST', - data: JSON.stringify(obj), - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/forums/topic/reply.ts b/src/api/v2/routes/forums/topic/reply.ts deleted file mode 100644 index 1c9caa39..00000000 --- a/src/api/v2/routes/forums/topic/reply.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { types } from '../../../../../types/v2_forums_topic_reply'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 0, - title: __filename, - method: 'GET', - description: 'Edit your topic and post from the forum', - params: [ - { - type: 'number', - name: 'topic_id', - optional: false, - description: 'Topic id', - }, - { - type: 'number', - name: 'body', - optional: false, - description: 'Message body', - }, - ], - return: 'response', -}; - - -const name: types = async (topic_id, body) => { - const data = await request(`forums/topics/${topic_id}/reply`, { - method: 'POST', - data: JSON.stringify({ body }), - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/matches/details.ts b/src/api/v2/routes/matches/details.ts deleted file mode 100644 index af1d92bb..00000000 --- a/src/api/v2/routes/matches/details.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { types } from '../../../../types/v2_matches_details'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return match data for specified id', - params: [ - { - type: 'number', - name: 'match', - optional: false, - description: 'id of the match', - }, - ], -}; - - -const name: types = async (match) => { - const data = await request(`matches/${match}`, { - method: 'GET', - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/matches/list.ts b/src/api/v2/routes/matches/list.ts deleted file mode 100644 index b88382f8..00000000 --- a/src/api/v2/routes/matches/list.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { types } from '../../../../types/v2_matches_list'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return array of the matches', - params: [], - return: 'response', -}; - - -const name: types = async () => { - const data = await request(`matches`, { - method: 'GET', - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/notifications/list.ts b/src/api/v2/routes/notifications/list.ts deleted file mode 100644 index aa47c567..00000000 --- a/src/api/v2/routes/notifications/list.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { types } from "../../../../types/v2_notifications_list"; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 0, - title: __filename, - method: 'GET', - description: `This endpoint returns a list of the user's unread notifications. Sorted descending by id with limit of 50.`, - params: [ - { - type: 'string', - name: 'max_id', - options: false, - optional: true, - description: 'Maximum \`\`\`id\`\`\` fetched. Can be used to load earlier notifications. Defaults to no limit (fetch latest notifications)', - }, - ], - return: 'response', -}; - - -const name: types = async (max_id) => { - const data = await request(`notifications`, { - method: 'GET', - params: { max_id }, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/notifications/markAsReaded.ts b/src/api/v2/routes/notifications/markAsReaded.ts deleted file mode 100644 index 55d649f6..00000000 --- a/src/api/v2/routes/notifications/markAsReaded.ts +++ /dev/null @@ -1,47 +0,0 @@ -// import { types } from "../../../../types/v2_notifications_list"; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'POST', - description: 'This endpoint allows you to mark notifications read', - params: [ - { - type: 'number array', - name: 'ids', - optional: false, - description: '\`\`\`id\`\`\` of notifications to be marked as read', - }, - ], -}; - -export interface types { - (ids: number[]): Promise; -}; - -export interface response { -} - - - -const name: types = async (ids) => { - const obj: any = {}; - - ids.forEach((r, index) => obj[`identities[${index}][object_id]`] = r); - - const data = await request(`notifications/mark-read`, { - method: 'POST', - data: JSON.stringify(obj) - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/room/details.ts b/src/api/v2/routes/room/details.ts deleted file mode 100644 index 043a22fe..00000000 --- a/src/api/v2/routes/room/details.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { types } from "../../../../types/v2_room_details"; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: '', - params: [ - { - type: 'number', - name: 'room_id', - description: 'Id of the room', - }, - ], -}; - - -const name: types = async (room_id) => { - const data = await request(`rooms/${room_id}`, { - method: 'GET', - // params: obj, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/room/leaderboard.ts b/src/api/v2/routes/room/leaderboard.ts deleted file mode 100644 index 64cbdcc4..00000000 --- a/src/api/v2/routes/room/leaderboard.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { types } from "../../../../types/v2_room_leaderboard"; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return leaderboard of room', - params: [ - { - type: 'number', - name: 'room_id', - description: 'Id of the room', - }, - ], -}; - - -const name: types = async (room_id) => { - const data = await request(`rooms/${room_id}/leaderboard`, { - method: 'GET', - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/rooms/list.ts b/src/api/v2/routes/rooms/list.ts deleted file mode 100644 index b9acfe45..00000000 --- a/src/api/v2/routes/rooms/list.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { types } from '../../../../types/v2_rooms_list'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: '', - params: [ - { - type: 'string', - name: 'mode', - optional: false, - description: '\`\`\`all\`\`\` or \`\`\`owned\`\`\` or \`\`\`participated\`\`\` or \`\`\`ended\`\`\`', - }, - { - name: 'object', - optional: true, - params: [ - { - type: 'string', - name: 'category', - optional: true, - description: '\`\`\`normal\`\`\` or \`\`\`spotlight\`\`\` or \`\`\`featured_artist\`\`\`', - }, - { - type: 'number', - name: 'limit', - optional: true, - description: 'Number of results', - }, - { - type: 'number', - name: 'season_id', - optional: true, - description: 'season_id', - }, - { - type: 'string', - name: 'type_group', - optional: true, - description: '\`\`\`playlists\`\`\` or \`\`\`realtime\`\`\`', - }, - ], - } - ], -}; - - -const name: types = async (mode, object) => { - //@ts-ignore - object.mode = mode; - const data = await request(`rooms/${mode == 'all' ? 'ended' : mode}`, { - method: 'GET', - params: object, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/scores/beatmap.ts b/src/api/v2/routes/scores/beatmap.ts deleted file mode 100644 index 3506855e..00000000 --- a/src/api/v2/routes/scores/beatmap.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { types } from '../../../../types/v2_scores_beatmap'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Returns the top scores for a beatmap', - params: [ - { - type: 'number', - name: 'beatmap', - optional: false, - description: 'id of the beatmap', - }, - { - name: 'object', - params: [ - { - type: 'string', - name: 'mode', - optional: true, - description: '\`\`\`osu\`\`\` or \`\`\`fruits\`\`\` or \`\`\`mania\`\`\` or \`\`\`taiko\`\`\`', - }, - { - type: 'string[]', - name: 'mods', - optional: true, - description: 'Array of matching mods [\'HD\', \'DT\']', - }, - { - type: 'string', - name: 'type', - optional: true, - description: '\`\`\`global\`\`\` or \`\`\`country\`\`\` or \`\`\`friend\`\`\`', - }, - ] - }, - ], -}; - - -const name: types = async (beatmap, obj) => { - const data = await request(`beatmaps/${beatmap}/scores`, { - method: 'GET', - params: obj, - }); - - if (!data.scores) return data; - return data.scores.map((v: any, i: number) => ({ position: i + 1, ...v })); -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/scores/download.ts b/src/api/v2/routes/scores/download.ts deleted file mode 100644 index 4cc5ada5..00000000 --- a/src/api/v2/routes/scores/download.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { types } from '../../../../types/v2_scores_download'; -import { Description } from '../../../../utility/types'; - - -import { download, namespace, RequestNamespace } from "../../../../utility/request"; - - -export const description: Description = { - auth: 0, - title: __filename, - method: 'GET', - description: 'Download score replay file', - params: [ - { - type: 'number', - name: 'score_id', - optional: false, - description: 'id of the score', - }, - { - type: 'string', - name: 'mode', - optional: false, - description: '\`\`\`osu\`\`\` or \`\`\`fruits\`\`\` or \`\`\`mania\`\`\` or \`\`\`taiko\`\`\`', - }, - { - type: 'string', - name: 'file_path', - optional: false, - description: 'File path with \`\`\`.osr\`\`\` at the end', - }, - ], - return: 'string', -}; - - -const name: types = async (score_id, mode, file_path) => { - const data = await download(`https://osu.ppy.sh/api/v2/scores/${mode}/${score_id}/download`, file_path); - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/scores/user/beatmap.ts b/src/api/v2/routes/scores/user/beatmap.ts deleted file mode 100644 index d12d20d3..00000000 --- a/src/api/v2/routes/scores/user/beatmap.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { types } from '../../../../../types/v2_scores_user_beatmap'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return best user score on beatmap', - params: [ - { - type: 'number', - name: 'beatmap', - optional: false, - description: 'id of the beatmap', - }, - { - type: 'string/number', - name: 'user', - optional: true, - description: 'id of the user', - }, - { - name: 'object', - optional: true, - params: [ - { - type: 'string', - name: 'mode', - optional: true, - description: '\`\`\`osu\`\`\` or \`\`\`fruits\`\`\` or \`\`\`mania\`\`\` or \`\`\`taiko\`\`\`', - }, - { - type: 'string[]', - name: 'mods', - optional: true, - description: 'Array of matching mods [\'HD\', \'DT\']', - }, - { - type: 'boolean', - name: 'best_only', - optional: true, - description: 'Return only best score from the beatmap', - } - ] - }, - ], -}; - - -const name: types = async (beatmap, user, obj) => { - let url = `beatmaps/${beatmap}/scores/users/${user}`; - if (!obj.best_only) url += '/all'; - - const data = await request(url, { - method: 'GET', - params: obj, - }); - - if (obj.best_only == true) { - data.score.position = data.position; - return [data.score]; - }; - - if (data.scores) return data.scores - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/site/news/details.ts b/src/api/v2/routes/site/news/details.ts deleted file mode 100644 index 9a438399..00000000 --- a/src/api/v2/routes/site/news/details.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { types } from '../../../../../types/v2_site_news_details'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Returns details of the specified news post', - params: [ - { - type: 'string | number', - name: 'news', - optional: false, - description: 'News post slug or ID', - }, - { - type: 'string', - name: 'key', - optional: false, - description: 'Unset to query by slug, or id to query by ID', - }, - ], - return: 'response', -}; - - -const name: types = async (news, key) => { - const data = await request(`news/${news}`, { - method: 'GET', - params: { key }, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/site/news/list.ts b/src/api/v2/routes/site/news/list.ts deleted file mode 100644 index 37bc51e2..00000000 --- a/src/api/v2/routes/site/news/list.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { types } from '../../../../../types/v2_site_news_list'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Returns a list of news posts and related metadata', - params: [ - { - name: 'object', - params: [ - { - type: 'number', - name: 'limit', - optional: true, - description: 'Maximum number of posts (12 default, 1 minimum, 21 maximum)', - }, - { - type: 'number', - name: 'year', - optional: true, - description: 'Year to return posts from', - }, - { - type: 'string', - name: 'cursorPublished', - optional: true, - description: 'Pagination cursorPublished', - }, - { - type: 'number', - name: 'cursorId', - optional: true, - description: 'Pagination cursorId', - }, - ], - } - ], - return: 'response', -}; - - -const name: types = async (obj) => { - const data = await request(`news`, { - method: 'GET', - params: obj, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/site/search.ts b/src/api/v2/routes/site/search.ts deleted file mode 100644 index 54c0d10e..00000000 --- a/src/api/v2/routes/site/search.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { types } from '../../../../types/v2_site_search'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Searches users and wiki pages.', - params: [ - { - name: 'object', - params: [ - { - type: 'string', - name: 'mode', - optional: true, - description: '\`\`\`all\`\`\` or \`\`\`user\`\`\` or \`\`\`wiki_page\`\`\`', - }, - { - type: 'string', - name: 'query', - optional: true, - description: 'Search keyword', - }, - { - type: 'number', - name: 'page', - optional: true, - description: 'Search result page. Ignored for mode all', - }, - ], - } - ], - return: 'response', -}; - - - -const name: types = async (obj) => { - const data = await request(`search`, { - method: 'GET', - params: obj, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/site/spotlights/list.ts b/src/api/v2/routes/site/spotlights/list.ts deleted file mode 100644 index 51c61fc0..00000000 --- a/src/api/v2/routes/site/spotlights/list.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { types } from '../../../../../types/v2_site_spotlights_list'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return list of spotlights', - params: [ - ], -}; - - -const name: types = async () => { - const data = await request(`spotlights`, { - method: 'GET', - }); - - if (data.spotlights) return data.spotlights; - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/site/wiki.ts b/src/api/v2/routes/site/wiki.ts deleted file mode 100644 index b6b80086..00000000 --- a/src/api/v2/routes/site/wiki.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { types } from '../../../../types/v2_site_wiki'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return data about wiki page', - params: [ - { - type: 'string', - name: 'language', - optional: false, - description: 'Language code of the wiki page', - }, - { - type: 'string', - name: 'path', - optional: false, - description: 'The path name of the wiki page', - }, - ], - return: 'response', -}; - - -const name: types = async (language, path) => { - const data = await request(`wiki/${language}/${path}`, { - method: 'GET', - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/user/activity.ts b/src/api/v2/routes/user/activity.ts deleted file mode 100644 index 29d62b8c..00000000 --- a/src/api/v2/routes/user/activity.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { types } from '../../../../types/v2_user_activity'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return list of recent user activity', - params: [ - { - type: 'number', - name: 'user', - optional: false, - description: 'id of the user', - }, - { - name: 'object', - params: [ - { - type: 'number', - name: 'limit', - optional: true, - description: 'Maximum number of results', - }, - { - type: 'string', - name: 'offset', - optional: true, - description: 'Result offset for pagination', - }, - ] - }, - ], -}; - - -const name: types = async (user, object = {}) => { - const data = await request(`users/${user}/recent_activity`, { - method: 'GET', - params: object, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/user/beatmaps/category.ts b/src/api/v2/routes/user/beatmaps/category.ts deleted file mode 100644 index 8c0a5a7a..00000000 --- a/src/api/v2/routes/user/beatmaps/category.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { types } from '../../../../../types/v2_user_beatmaps_category'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return beatmaps list of specified user', - params: [ - { - type: 'number', - name: 'user', - optional: false, - description: 'id of the user', - }, - { - type: 'string', - name: 'type', - optional: false, - description: '\`\`\`favourite\`\`\` or \`\`\`loved\`\`\` or \`\`\`ranked\`\`\` or \`\`\`pending\`\`\` or \`\`\`graveyard\`\`\`', - }, - { - name: 'object', - params: [ - { - type: 'number', - name: 'limit', - optional: true, - description: 'Maximum number of results', - }, - { - type: 'number', - name: 'offset', - optional: true, - description: 'Result offset for pagination', - }, - ] - }, - ], -}; - - -const name: types = async (user, type, obj) => { - const data = await request(`users/${user}/beatmapsets/${type}`, { - method: 'GET', - params: obj, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/user/beatmaps/kudosu.ts b/src/api/v2/routes/user/beatmaps/kudosu.ts deleted file mode 100644 index b33f1c57..00000000 --- a/src/api/v2/routes/user/beatmaps/kudosu.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { types } from '../../../../../types/v2_user_beatmaps_kudosu'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return list of kudosu actions', - params: [ - { - type: 'number', - name: 'user', - optional: false, - description: 'id of the user', - }, - { - name: 'object', - params: [ - { - type: 'number', - name: 'limit', - optional: true, - description: 'Maximum number of results', - }, - { - type: 'number', - name: 'offset', - optional: true, - description: 'Result offset for pagination', - }, - ] - }, - ], -}; - - -const name: types = async (user, obj) => { - const data = await request(`users/${user}/kudosu`, { - method: 'GET', - params: obj, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/user/beatmaps/most_played.ts b/src/api/v2/routes/user/beatmaps/most_played.ts deleted file mode 100644 index a96b7eca..00000000 --- a/src/api/v2/routes/user/beatmaps/most_played.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { types } from '../../../../../types/v2_user_beatmaps_most_played'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return list of user most played beatmaps', - params: [ - { - type: 'number', - name: 'user', - optional: false, - description: 'id of the user', - }, - { - name: 'object', - params: [ - { - type: 'number', - name: 'limit', - optional: true, - description: 'Maximum number of results', - }, - { - type: 'number', - name: 'offset', - optional: true, - description: 'Result offset for pagination', - }, - ] - }, - ], -}; - - -const name: types = async (user, obj) => { - const data = await request(`users/${user}/beatmapsets/most_played`, { - method: 'GET', - params: obj, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/user/details.ts b/src/api/v2/routes/user/details.ts deleted file mode 100644 index 6ab19caf..00000000 --- a/src/api/v2/routes/user/details.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { types } from '../../../../types/v2_user_details'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return details about user', - params: [ - { - type: 'string/number', - name: 'user', - optional: false, - description: 'id of the user', - }, - { - type: 'string/number', - name: 'mode', - optional: true, - description: '\`\`\`osu\`\`\` or \`\`\`fruits\`\`\` or \`\`\`mania\`\`\` or \`\`\`taiko\`\`\`', - }, - { - type: 'string/number', - name: 'key', - optional: true, - description: '\`\`\`id\`\`\` or \`\`\`username\`\`\`', - }, - ], - return: 'response', -}; - -const name: types = async (user, mode, key) => { - let url = `users/${user}`; - if (mode != null) url += `/${mode}`; - - const data = await request(url, { - method: 'GET', - params: { key }, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/user/me/details.ts b/src/api/v2/routes/user/me/details.ts deleted file mode 100644 index 7f38dfe6..00000000 --- a/src/api/v2/routes/user/me/details.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { types } from '../../../../../types/v2_user_me_details'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 0, - title: __filename, - method: 'GET', - description: 'Return details about your account', - params: [ - { - type: 'string', - name: 'mode', - optional: true, - description: '\`\`\`osu\`\`\` or \`\`\`fruits\`\`\` or \`\`\`mania\`\`\` or \`\`\`taiko\`\`\`', - }, - ], - return: 'response', -}; - - -const name: types = async (mode) => { - const data = await request(`me/${mode}`, { - method: 'GET', - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/user/me/download/quota.ts b/src/api/v2/routes/user/me/download/quota.ts deleted file mode 100644 index e26b7562..00000000 --- a/src/api/v2/routes/user/me/download/quota.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { types } from '../../../../../../types/v2_user_me_download_quota'; -import { Description } from '../../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: any = { - type: false, - auth: 0, - title: __filename, - method: 'GET', - description: 'Return user download quota number?', - params: [ - - ], - return: 'response', -}; - - -const name: types = async () => { - const data = await request(`me/download-quota-check`, { - method: 'GET', - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/user/me/friends.ts b/src/api/v2/routes/user/me/friends.ts deleted file mode 100644 index c95d13d0..00000000 --- a/src/api/v2/routes/user/me/friends.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { types } from '../../../../../types/v2_user_me_friends'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 0, - title: __filename, - method: 'GET', - description: 'Return list of your friedns', - params: [ - - ], -}; - - -const name: types = async () => { - const data = await request(`friends`, { - method: 'GET', - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/users/details.ts b/src/api/v2/routes/users/details.ts deleted file mode 100644 index 89aed49c..00000000 --- a/src/api/v2/routes/users/details.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { types } from '../../../../types/v2_users_details'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return list of users', - params: [ - { - type: 'number[]', - name: 'ids', - optional: false, - description: 'ids of the users (limit 50 users per request)', - } - ], -}; - - -const name: types = async (ids) => { - const data = await request(`users`, { - method: 'GET', - params: { - ids - }, - }); - - if (data.users) return data.users; - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/users/groups/list.ts b/src/api/v2/routes/users/groups/list.ts deleted file mode 100644 index b511aec2..00000000 --- a/src/api/v2/routes/users/groups/list.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { types } from '../../../../../types/v2_users_groups_list'; -import { Description } from '../../../../../utility/types'; - - -import { request, namespace, RequestNamespace } from "../../../../../utility/request"; -// const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 3, - title: __filename, - method: 'GET', - description: 'Return array of users from specified group id', - params: [ - { - type: 'number', - name: 'id', - optional: false, - description: '\`\`\`4\`\`\` or \`\`\`7\`\`\` or \`\`\`11\`\`\` or \`\`\`16\`\`\` or \`\`\`22\`\`\` or \`\`\`28\`\`\` or \`\`\`31\`\`\` or \`\`\`32\`\`\`', - }, - ], -}; - - -const name: types = async (id) => { - try { - const data = await request(`https://osu.ppy.sh/groups/${id}`, { - method: 'GET', - }); - - const parse = data.split('')[0]; - return JSON.parse(parse); - } catch (err: any) { - console.log('groups-list error', id, err.message); - - return []; - } -}; - - -export default name; \ No newline at end of file From 3bb589b76f9ba272673e8730acf5bc986ed1c90a Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 12:03:51 +0300 Subject: [PATCH 072/259] goodbye old types --- src/types/v2_assets_seasonalBackgrounds.ts | 44 --- src/types/v2_beatmap_discussions_details.ts | 223 -------------- src/types/v2_beatmap_discussions_posts.ts | 108 ------- src/types/v2_beatmap_discussions_votes.ts | 86 ------ src/types/v2_beatmap_id_attributes.ts | 45 --- src/types/v2_beatmap_id_details.ts | 111 ------- src/types/v2_beatmap_id_lookup.ts | 113 ------- src/types/v2_beatmap_set_addToFavourites.ts | 28 -- src/types/v2_beatmap_set_details.ts | 207 ------------- src/types/v2_beatmap_set_lookup.ts | 202 ------------- src/types/v2_beatmaps_details.ts | 111 ------- src/types/v2_beatmaps_events.ts | 120 -------- src/types/v2_beatmaps_search.ts | 131 --------- src/types/v2_changelogs_details.ts | 89 ------ src/types/v2_changelogs_list.ts | 94 ------ src/types/v2_changelogs_lookup.ts | 79 ----- src/types/v2_chat_channels_details.ts | 44 --- src/types/v2_chat_channels_join.ts | 42 --- src/types/v2_chat_channels_leave.ts | 27 -- src/types/v2_chat_channels_list.ts | 32 -- src/types/v2_chat_channels_messages_list.ts | 51 ---- .../v2_chat_channels_messages_markAsReaded.ts | 27 -- src/types/v2_chat_channels_messages_send.ts | 50 ---- src/types/v2_chat_new.ts | 65 ---- src/types/v2_chat_updates.ts | 51 ---- src/types/v2_comments_details.ts | 98 ------- src/types/v2_comments_edit.ts | 84 ------ src/types/v2_comments_list.ts | 105 ------- src/types/v2_comments_new.ts | 86 ------ src/types/v2_comments_remove.ts | 81 ----- src/types/v2_comments_vote.ts | 84 ------ src/types/v2_forums_post_edit.ts | 39 --- src/types/v2_forums_topic_details.ts | 88 ------ src/types/v2_forums_topic_edit.ts | 57 ---- src/types/v2_forums_topic_new.ts | 63 ---- src/types/v2_forums_topic_reply.ts | 39 --- src/types/v2_matches_details.ts | 148 ---------- src/types/v2_matches_list.ts | 39 --- src/types/v2_notifications_list.ts | 62 ---- src/types/v2_notifications_markAsReaded.ts | 26 -- src/types/v2_scores_beatmap.ts | 81 ----- src/types/v2_scores_download.ts | 28 -- src/types/v2_site_news_details.ts | 58 ---- src/types/v2_site_news_list.ts | 64 ---- src/types/v2_site_search.ts | 59 ---- src/types/v2_site_spotlights_list.ts | 31 -- src/types/v2_site_wiki.ts | 35 --- src/types/v2_user_activity.ts | 58 ---- src/types/v2_user_beatmaps_category.ts | 108 ------- src/types/v2_user_beatmaps_kudosu.ts | 41 --- src/types/v2_user_beatmaps_most_played.ts | 70 ----- src/types/v2_user_details.ts | 184 ------------ src/types/v2_user_me_details.ts | 277 ------------------ src/types/v2_user_me_friends.ts | 89 ------ src/types/v2_users_details.ts | 181 ------------ src/types/v2_users_events.ts | 66 ----- src/types/v2_users_groups_list.ts | 90 ------ 57 files changed, 4799 deletions(-) delete mode 100644 src/types/v2_assets_seasonalBackgrounds.ts delete mode 100644 src/types/v2_beatmap_discussions_details.ts delete mode 100644 src/types/v2_beatmap_discussions_posts.ts delete mode 100644 src/types/v2_beatmap_discussions_votes.ts delete mode 100644 src/types/v2_beatmap_id_attributes.ts delete mode 100644 src/types/v2_beatmap_id_details.ts delete mode 100644 src/types/v2_beatmap_id_lookup.ts delete mode 100644 src/types/v2_beatmap_set_addToFavourites.ts delete mode 100644 src/types/v2_beatmap_set_details.ts delete mode 100644 src/types/v2_beatmap_set_lookup.ts delete mode 100644 src/types/v2_beatmaps_details.ts delete mode 100644 src/types/v2_beatmaps_events.ts delete mode 100644 src/types/v2_beatmaps_search.ts delete mode 100644 src/types/v2_changelogs_details.ts delete mode 100644 src/types/v2_changelogs_list.ts delete mode 100644 src/types/v2_changelogs_lookup.ts delete mode 100644 src/types/v2_chat_channels_details.ts delete mode 100644 src/types/v2_chat_channels_join.ts delete mode 100644 src/types/v2_chat_channels_leave.ts delete mode 100644 src/types/v2_chat_channels_list.ts delete mode 100644 src/types/v2_chat_channels_messages_list.ts delete mode 100644 src/types/v2_chat_channels_messages_markAsReaded.ts delete mode 100644 src/types/v2_chat_channels_messages_send.ts delete mode 100644 src/types/v2_chat_new.ts delete mode 100644 src/types/v2_chat_updates.ts delete mode 100644 src/types/v2_comments_details.ts delete mode 100644 src/types/v2_comments_edit.ts delete mode 100644 src/types/v2_comments_list.ts delete mode 100644 src/types/v2_comments_new.ts delete mode 100644 src/types/v2_comments_remove.ts delete mode 100644 src/types/v2_comments_vote.ts delete mode 100644 src/types/v2_forums_post_edit.ts delete mode 100644 src/types/v2_forums_topic_details.ts delete mode 100644 src/types/v2_forums_topic_edit.ts delete mode 100644 src/types/v2_forums_topic_new.ts delete mode 100644 src/types/v2_forums_topic_reply.ts delete mode 100644 src/types/v2_matches_details.ts delete mode 100644 src/types/v2_matches_list.ts delete mode 100644 src/types/v2_notifications_list.ts delete mode 100644 src/types/v2_notifications_markAsReaded.ts delete mode 100644 src/types/v2_scores_beatmap.ts delete mode 100644 src/types/v2_scores_download.ts delete mode 100644 src/types/v2_site_news_details.ts delete mode 100644 src/types/v2_site_news_list.ts delete mode 100644 src/types/v2_site_search.ts delete mode 100644 src/types/v2_site_spotlights_list.ts delete mode 100644 src/types/v2_site_wiki.ts delete mode 100644 src/types/v2_user_activity.ts delete mode 100644 src/types/v2_user_beatmaps_category.ts delete mode 100644 src/types/v2_user_beatmaps_kudosu.ts delete mode 100644 src/types/v2_user_beatmaps_most_played.ts delete mode 100644 src/types/v2_user_details.ts delete mode 100644 src/types/v2_user_me_details.ts delete mode 100644 src/types/v2_user_me_friends.ts delete mode 100644 src/types/v2_users_details.ts delete mode 100644 src/types/v2_users_events.ts delete mode 100644 src/types/v2_users_groups_list.ts diff --git a/src/types/v2_assets_seasonalBackgrounds.ts b/src/types/v2_assets_seasonalBackgrounds.ts deleted file mode 100644 index c59ff798..00000000 --- a/src/types/v2_assets_seasonalBackgrounds.ts +++ /dev/null @@ -1,44 +0,0 @@ -export interface response { - ends_at: string; - backgrounds: { - url: string; - user: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour: string; - username: string; - }; - }[]; -} - - -export interface types { - /** - * Return array of seasonal backgrounds - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_assets_seasonalBackgrounds = await v2.assets.seasonalBackgrounds(); - * console.log(v2_assets_seasonalBackgrounds); - * }; - * - * main(); - * ``` - */ - (): Promise; -} diff --git a/src/types/v2_beatmap_discussions_details.ts b/src/types/v2_beatmap_discussions_details.ts deleted file mode 100644 index 94441744..00000000 --- a/src/types/v2_beatmap_discussions_details.ts +++ /dev/null @@ -1,223 +0,0 @@ -export interface response { - beatmaps: { - beatmapset_id: number; - difficulty_rating: number; - id: number; - mode: string; - status: string; - total_length: number; - user_id: number; - version: string; - accuracy: number; - ar: number; - bpm: number; - convert: boolean; - count_circles: number; - count_sliders: number; - count_spinners: number; - cs: number; - deleted_at?: string; - drain: number; - hit_length: number; - is_scoreable: boolean; - last_updated: string; - mode_int: number; - passcount: number; - playcount: number; - ranked: number; - url: string; - checksum?: string; - }[]; - beatmapsets: { - artist: string; - artist_unicode: string; - covers: { - cover: string; - 'cover@2x': string; - card: string; - 'card@2x': string; - list: string; - 'list@2x': string; - slimcover: string; - 'slimcover@2x': string; - }; - creator: string; - favourite_count: number; - hype?: string; - id: number; - nsfw: boolean; - offset: number; - play_count: number; - preview_url: string; - source: string; - spotlight: boolean; - status: string; - title: string; - title_unicode: string; - track_id?: string; - user_id: number; - video: boolean; - bpm: number; - can_be_hyped: boolean; - deleted_at?: string; - discussion_enabled: boolean; - discussion_locked: boolean; - is_scoreable: boolean; - last_updated: string; - legacy_thread_url: string; - nominations_summary: { - current: number; - required: number; - }; - ranked: number; - ranked_date: string; - storyboard: boolean; - submitted_date: string; - tags: string; - availability: { - download_disabled: boolean; - more_information: string; - }; - has_favourited: boolean; - }[]; - discussions: { - id: number; - beatmapset_id: number; - beatmap_id?: string; - user_id: number; - deleted_by_id?: string; - message_type: string; - parent_id?: string; - timestamp?: string; - resolved: boolean; - can_be_resolved: boolean; - can_grant_kudosu: boolean; - created_at: string; - updated_at: string; - deleted_at?: string; - last_post_at: string; - kudosu_denied: boolean; - current_user_attributes: { - vote_score: number; - can_moderate_kudosu: boolean; - can_resolve: boolean; - can_reopen: boolean; - can_destroy: boolean; - }; - starting_post: { - beatmapset_discussion_id: number; - created_at: string; - deleted_at: string; - deleted_by_id: string; - id: number; - last_editor_id: string; - message: string; - system: boolean; - updated_at: string; - user_id: number; - }; - }[]; - included_discussions: { - id: number; - beatmapset_id: number; - beatmap_id: string; - user_id: number; - deleted_by_id: string; - message_type: string; - parent_id: number; - timestamp: string; - resolved: boolean; - can_be_resolved: boolean; - can_grant_kudosu: boolean; - created_at: string; - updated_at: string; - deleted_at: string; - last_post_at: string; - kudosu_denied: boolean; - current_user_attributes: { - vote_score: number; - can_moderate_kudosu: boolean; - can_resolve: boolean; - can_reopen: boolean; - can_destroy: boolean; - }; - starting_post: { - beatmapset_discussion_id: number; - created_at: string; - deleted_at: string; - deleted_by_id: string; - id: number; - last_editor_id: string; - message: string; - system: boolean; - updated_at: string; - user_id: number; - }; - }[]; - reviews_config: { - max_blocks: number; - }; - users: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit?: string; - pm_friends_only: boolean; - profile_colour?: string; - username: string; - groups: { - colour: string; - has_listing: boolean; - has_playmodes: boolean; - id: number; - identifier: string; - is_probationary: boolean; - name: string; - short_name: string; - playmodes: string[]; - }[]; - }[]; - cursor: { - page: number; - limit: number; - }; - cursor_string: string; -} - - -export interface types { - /** - * Return details of beatmap discussion - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_beatmap_discussions_details = await v2.beatmap.discussions.details(object); - * console.log(v2_beatmap_discussions_details); - * }; - * - * main(); - * ``` - * @param {number} object.beatmap_id beatmap id - * @param {number} object.beatmapset_id beatmapset id - * @param {string} object.beatmapset_status ```all``` or ```ranked``` or ```qualified``` or ```disqualified``` or ```never_qualified``` or ```loved``` - * @param {number} object.limit Maximum number of results - * @param {string[]} object.message_types ```suggestion``` or ```problem``` or ```mapper_note``` or ```praise``` or ```hype``` or ```review``` or ```all``` - * @param {boolean} object.only_unresolved ```true``` or ```false``` - * @param {number} object.page Search result page - * @param {string} object.sort ```id_desc``` or ```id_asc``` - * @param {number} object.user id of the user - */ - (object: {beatmap_id?: number, beatmapset_id?: number, beatmapset_status?: 'all' | 'ranked' | 'qualified' | 'disqualified' | 'never_qualified' | 'loved' , limit?: number, message_types?: Array<'suggestion' | 'problem' | 'mapper_note' | 'praise' | 'hype' | 'review' | 'all' >, only_unresolved?: 'true' | 'false' , page?: number, sort?: 'id_desc' | 'id_asc' , user?: number, }): Promise; -} diff --git a/src/types/v2_beatmap_discussions_posts.ts b/src/types/v2_beatmap_discussions_posts.ts deleted file mode 100644 index f2c7fd35..00000000 --- a/src/types/v2_beatmap_discussions_posts.ts +++ /dev/null @@ -1,108 +0,0 @@ -export interface response { - beatmapsets: { - artist: string; - artist_unicode: string; - covers: { - cover: string; - 'cover@2x': string; - card: string; - 'card@2x': string; - list: string; - 'list@2x': string; - slimcover: string; - 'slimcover@2x': string; - }; - creator: string; - favourite_count: number; - hype?: string; - id: number; - nsfw: boolean; - offset: number; - play_count: number; - preview_url: string; - source: string; - spotlight: boolean; - status: string; - title: string; - title_unicode: string; - track_id?: string; - user_id: number; - video: boolean; - }[]; - discussions: { - id: number; - beatmapset_id: number; - beatmap_id?: number; - user_id: number; - deleted_by_id?: string; - message_type: string; - parent_id?: string; - timestamp?: number; - resolved: boolean; - can_be_resolved: boolean; - can_grant_kudosu: boolean; - created_at: string; - updated_at: string; - deleted_at?: string; - last_post_at: string; - kudosu_denied: boolean; - }[]; - posts: { - beatmapset_discussion_id: number; - created_at: string; - deleted_at?: string; - deleted_by_id?: string; - id: number; - last_editor_id?: string; - message: string; - system: boolean; - updated_at: string; - user_id: number; - }[]; - users: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit?: string; - pm_friends_only: boolean; - profile_colour?: string; - username: string; - }[]; - cursor: string; - cursor_string: string; -} - - -export interface types { - /** - * Return posts from beatmap set discussions - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_beatmap_discussions_posts = await v2.beatmap.discussions.posts(object); - * console.log(v2_beatmap_discussions_posts); - * }; - * - * main(); - * ``` - * @param {number} object.beatmapset_discussion_id id of beatmap set id - * @param {number} object.limit Maximum number of results - * @param {number} object.page Search page - * @param {string} object.sort ```id_desc``` or ```id_asc``` - * @param {string[]} object.types ```first``` or ```replay``` or ```system``` - * @param {number} object.user id of the user - */ - (object: {beatmapset_discussion_id?: number, limit?: number, page?: number, sort?: 'id_desc' | 'id_asc' , types?: Array<'first' | 'replay' | 'system' >, user?: number, }): Promise; -} diff --git a/src/types/v2_beatmap_discussions_votes.ts b/src/types/v2_beatmap_discussions_votes.ts deleted file mode 100644 index 423f117b..00000000 --- a/src/types/v2_beatmap_discussions_votes.ts +++ /dev/null @@ -1,86 +0,0 @@ -export interface response { - discussions: { - id: number; - beatmapset_id: number; - beatmap_id?: number; - user_id: number; - deleted_by_id?: string; - message_type: string; - parent_id?: string; - timestamp?: number; - resolved: boolean; - can_be_resolved: boolean; - can_grant_kudosu: boolean; - created_at: string; - updated_at: string; - deleted_at?: string; - last_post_at: string; - kudosu_denied: boolean; - }[]; - users: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit?: string; - pm_friends_only: boolean; - profile_colour?: string; - username: string; - groups: { - colour: string; - has_listing: boolean; - has_playmodes: boolean; - id: number; - identifier: string; - is_probationary: boolean; - name: string; - short_name: string; - playmodes: string[]; - }[]; - }[]; - votes: { - beatmapset_discussion_id: number; - created_at: string; - id: number; - score: number; - updated_at: string; - user_id: number; - }[]; - cursor: string; - cursor_string: string; -} - - -export interface types { - /** - * Return votes (+discussions, users) from beatmap set discussions - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_beatmap_discussions_votes = await v2.beatmap.discussions.votes(object); - * console.log(v2_beatmap_discussions_votes); - * }; - * - * main(); - * ``` - * @param {number} object.beatmapset_discussion_id id of beatmap set id - * @param {number} object.limit Maximum number of results - * @param {number} object.page Search page - * @param {number} object.receiver id of the user - * @param {number} object.score ```1``` for up vote, ```-1``` for down vote - * @param {string} object.sort ```id_desc``` or ```id_asc``` - * @param {number} object.user id of the user - */ - (object: {beatmapset_discussion_id?: number, limit?: number, page?: number, receiver?: number, score?: '1 for up vote, -1 for down vote' , sort?: 'id_desc' | 'id_asc' , user?: number, }): Promise; -} diff --git a/src/types/v2_beatmap_id_attributes.ts b/src/types/v2_beatmap_id_attributes.ts deleted file mode 100644 index 77807ea0..00000000 --- a/src/types/v2_beatmap_id_attributes.ts +++ /dev/null @@ -1,45 +0,0 @@ -export interface response { - attributes: { - star_rating: number; - max_combo: number; - aim_difficulty: number; - speed_difficulty: number; - speed_note_count: number; - flashlight_difficulty: number; - slider_factor: number; - approach_rate: number; - overall_difficulty: number; - stamina_difficulty: number; - rhythm_difficulty: number; - colour_difficulty: number; - peak_difficulty: number; - great_hit_window: number; - }; -} - - -export interface types { - /** - * Return attributes (stars, combo, stats) of beatmap - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_beatmap_id_attributes = await v2.beatmap.id.attributes(beatmap_id, body); - * console.log(v2_beatmap_id_attributes); - * }; - * - * main(); - * ``` - * @param {number} beatmap_id Beatmap id - * @param {string[] | number} body.mods Array of matching mods ['HD', 'DT'] - * @param {string} body.ruleset ```osu``` or ```fruits``` or ```mania``` or ```taiko``` - * @param {number} body.ruleset_id ```0``` or ```1``` or ```2``` or ```3``` - */ - (beatmap_id: number, body: {mods?: string[] | number, ruleset?: 'osu' | 'fruits' | 'mania' | 'taiko' , ruleset_id?: '0' | '1' | '2' | '3' , }): Promise; -} diff --git a/src/types/v2_beatmap_id_details.ts b/src/types/v2_beatmap_id_details.ts deleted file mode 100644 index 79ca9740..00000000 --- a/src/types/v2_beatmap_id_details.ts +++ /dev/null @@ -1,111 +0,0 @@ -export interface response { - beatmapset_id: number; - difficulty_rating: number; - id: number; - mode: string; - status: string; - total_length: number; - user_id: number; - version: string; - accuracy: number; - ar: number; - bpm: number; - convert: boolean; - count_circles: number; - count_sliders: number; - count_spinners: number; - cs: number; - deleted_at: string; - drain: number; - hit_length: number; - is_scoreable: boolean; - last_updated: string; - mode_int: number; - passcount: number; - playcount: number; - ranked: number; - url: string; - checksum: string; - beatmapset: { - artist: string; - artist_unicode: string; - covers: { - cover: string; - 'cover@2x': string; - card: string; - 'card@2x': string; - list: string; - 'list@2x': string; - slimcover: string; - 'slimcover@2x': string; - }; - creator: string; - favourite_count: number; - hype: string; - id: number; - nsfw: boolean; - offset: number; - play_count: number; - preview_url: string; - source: string; - spotlight: boolean; - status: string; - title: string; - title_unicode: string; - track_id: string; - user_id: number; - video: boolean; - bpm: number; - can_be_hyped: boolean; - deleted_at: string; - discussion_enabled: boolean; - discussion_locked: boolean; - is_scoreable: boolean; - last_updated: string; - legacy_thread_url: string; - nominations_summary: { - current: number; - required: number; - }; - ranked: number; - ranked_date: string; - storyboard: boolean; - submitted_date: string; - tags: string; - availability: { - download_disabled: boolean; - more_information: string; - }; - has_favourited: boolean; - ratings: number[]; - }; - failtimes: { - fail: number[]; - exit: number[]; - }; - max_combo: number; -} - - -export interface types { - /** - * Return beatmap data of specified beatmap id - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_beatmap_id_details = await v2.beatmap.id.details(beatmap); - * console.log(v2_beatmap_id_details); - * }; - * - * main(); - * ``` - * @param {number} beatmap id of the beatmap - */ - (beatmap: number): Promise; -} diff --git a/src/types/v2_beatmap_id_lookup.ts b/src/types/v2_beatmap_id_lookup.ts deleted file mode 100644 index 33783caa..00000000 --- a/src/types/v2_beatmap_id_lookup.ts +++ /dev/null @@ -1,113 +0,0 @@ -export interface response { - beatmapset_id: number; - difficulty_rating: number; - id: number; - mode: string; - status: string; - total_length: number; - user_id: number; - version: string; - accuracy: number; - ar: number; - bpm: number; - convert: boolean; - count_circles: number; - count_sliders: number; - count_spinners: number; - cs: number; - deleted_at: string; - drain: number; - hit_length: number; - is_scoreable: boolean; - last_updated: string; - mode_int: number; - passcount: number; - playcount: number; - ranked: number; - url: string; - checksum: string; - beatmapset: { - artist: string; - artist_unicode: string; - covers: { - cover: string; - 'cover@2x': string; - card: string; - 'card@2x': string; - list: string; - 'list@2x': string; - slimcover: string; - 'slimcover@2x': string; - }; - creator: string; - favourite_count: number; - hype: string; - id: number; - nsfw: boolean; - offset: number; - play_count: number; - preview_url: string; - source: string; - spotlight: boolean; - status: string; - title: string; - title_unicode: string; - track_id: string; - user_id: number; - video: boolean; - bpm: number; - can_be_hyped: boolean; - deleted_at: string; - discussion_enabled: boolean; - discussion_locked: boolean; - is_scoreable: boolean; - last_updated: string; - legacy_thread_url: string; - nominations_summary: { - current: number; - required: number; - }; - ranked: number; - ranked_date: string; - storyboard: boolean; - submitted_date: string; - tags: string; - availability: { - download_disabled: boolean; - more_information: string; - }; - has_favourited: boolean; - ratings: number[]; - }; - failtimes: { - fail: number[]; - exit: number[]; - }; - max_combo: number; -} - - -export interface types { - /** - * Return data of the specified beatmap id - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_beatmap_id_lookup = await v2.beatmap.id.lookup(object); - * console.log(v2_beatmap_id_lookup); - * }; - * - * main(); - * ``` - * @param {number} object.id id of the beatmap - * @param {string} object.checksum md5 of the beatmap file - * @param {string} object.filename file name of the beatmap - */ - (object: {id?: number, checksum?: string, filename?: string, }): Promise; -} diff --git a/src/types/v2_beatmap_set_addToFavourites.ts b/src/types/v2_beatmap_set_addToFavourites.ts deleted file mode 100644 index 03e51939..00000000 --- a/src/types/v2_beatmap_set_addToFavourites.ts +++ /dev/null @@ -1,28 +0,0 @@ -export interface response { - favourite_count: number; -} - - -export interface types { - /** - * Added specified beatmapset to favourite list - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login_lazer(USERNAME, USER_PASSWORD); - * - * const v2_beatmap_set_addToFavourites = await v2.beatmap.set.addToFavourites(beatmapset_id, action); - * console.log(v2_beatmap_set_addToFavourites); - * }; - * - * main(); - * ``` - * @param {number} beatmapset_id id of the beatmap set - * @param {boolean} action true/false - */ - (beatmapset_id: number, action: boolean): Promise; -} diff --git a/src/types/v2_beatmap_set_details.ts b/src/types/v2_beatmap_set_details.ts deleted file mode 100644 index 88f7f9f0..00000000 --- a/src/types/v2_beatmap_set_details.ts +++ /dev/null @@ -1,207 +0,0 @@ -export interface response { - artist: string; - artist_unicode: string; - covers: { - cover: string; - 'cover@2x': string; - card: string; - 'card@2x': string; - list: string; - 'list@2x': string; - slimcover: string; - 'slimcover@2x': string; - }; - creator: string; - favourite_count: number; - hype: string; - id: number; - nsfw: boolean; - offset: number; - play_count: number; - preview_url: string; - source: string; - spotlight: boolean; - status: string; - title: string; - title_unicode: string; - track_id: string; - user_id: number; - video: boolean; - bpm: number; - can_be_hyped: boolean; - deleted_at: string; - discussion_enabled: boolean; - discussion_locked: boolean; - is_scoreable: boolean; - last_updated: string; - legacy_thread_url: string; - nominations_summary: { - current: number; - required: number; - }; - ranked: number; - ranked_date: string; - storyboard: boolean; - submitted_date: string; - tags: string; - availability: { - download_disabled: boolean; - more_information: string; - }; - has_favourited: boolean; - beatmaps: { - beatmapset_id: number; - difficulty_rating: number; - id: number; - mode: string; - status: string; - total_length: number; - user_id: number; - version: string; - accuracy: number; - ar: number; - bpm: number; - convert: boolean; - count_circles: number; - count_sliders: number; - count_spinners: number; - cs: number; - deleted_at?: string; - drain: number; - hit_length: number; - is_scoreable: boolean; - last_updated: string; - mode_int: number; - passcount: number; - playcount: number; - ranked: number; - url: string; - checksum: string; - failtimes: { - fail: number[]; - exit: number[]; - }; - max_combo: number; - }[]; - converts: { - beatmapset_id: number; - difficulty_rating: number; - id: number; - mode: string; - status: string; - total_length: number; - user_id: number; - version: string; - accuracy: number; - ar: number; - bpm: number; - convert: boolean; - count_circles: number; - count_sliders: number; - count_spinners: number; - cs: number; - deleted_at?: string; - drain: number; - hit_length: number; - is_scoreable: boolean; - last_updated: string; - mode_int: number; - passcount: number; - playcount: number; - ranked: number; - url: string; - checksum: string; - failtimes: { - fail: number[]; - exit: number[]; - }; - }[]; - current_nominations: { - beatmapset_id: number; - rulesets: string[]; - reset: boolean; - user_id: number; - }[]; - description: { - description: string; - }; - genre: { - id: number; - name: string; - }; - language: { - id: number; - name: string; - }; - pack_tags: string[]; - ratings: number[]; - recent_favourites: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit?: string; - pm_friends_only: boolean; - profile_colour?: string; - username: string; - }[]; - related_users: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit?: string; - pm_friends_only: boolean; - profile_colour?: string; - username: string; - }[]; - user: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour: string; - username: string; - }; -} - - -export interface types { - /** - * Return beatmap data of specified beatmap set id - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_beatmap_set_details = await v2.beatmap.set.details(beatmapset); - * console.log(v2_beatmap_set_details); - * }; - * - * main(); - * ``` - * @param {string} beatmapset Beatmap set id - */ - (beatmapset: string): Promise; -} diff --git a/src/types/v2_beatmap_set_lookup.ts b/src/types/v2_beatmap_set_lookup.ts deleted file mode 100644 index ddca256e..00000000 --- a/src/types/v2_beatmap_set_lookup.ts +++ /dev/null @@ -1,202 +0,0 @@ -export interface response { - artist: string; - artist_unicode: string; - covers: { - cover: string; - 'cover@2x': string; - card: string; - 'card@2x': string; - list: string; - 'list@2x': string; - slimcover: string; - 'slimcover@2x': string; - }; - creator: string; - favourite_count: number; - hype: string; - id: number; - nsfw: boolean; - offset: number; - play_count: number; - preview_url: string; - source: string; - spotlight: boolean; - status: string; - title: string; - title_unicode: string; - track_id: string; - user_id: number; - video: boolean; - bpm: number; - can_be_hyped: boolean; - deleted_at: string; - discussion_enabled: boolean; - discussion_locked: boolean; - is_scoreable: boolean; - last_updated: string; - legacy_thread_url: string; - nominations_summary: { - current: number; - required: number; - }; - ranked: number; - ranked_date: string; - storyboard: boolean; - submitted_date: string; - tags: string; - availability: { - download_disabled: boolean; - more_information: string; - }; - has_favourited: boolean; - beatmaps: { - beatmapset_id: number; - difficulty_rating: number; - id: number; - mode: string; - status: string; - total_length: number; - user_id: number; - version: string; - accuracy: number; - ar: number; - bpm: number; - convert: boolean; - count_circles: number; - count_sliders: number; - count_spinners: number; - cs: number; - deleted_at?: string; - drain: number; - hit_length: number; - is_scoreable: boolean; - last_updated: string; - mode_int: number; - passcount: number; - playcount: number; - ranked: number; - url: string; - checksum: string; - failtimes: { - fail: number[]; - exit: number[]; - }; - max_combo: number; - }[]; - converts: { - beatmapset_id: number; - difficulty_rating: number; - id: number; - mode: string; - status: string; - total_length: number; - user_id: number; - version: string; - accuracy: number; - ar: number; - bpm: number; - convert: boolean; - count_circles: number; - count_sliders: number; - count_spinners: number; - cs: number; - deleted_at?: string; - drain: number; - hit_length: number; - is_scoreable: boolean; - last_updated: string; - mode_int: number; - passcount: number; - playcount: number; - ranked: number; - url: string; - checksum: string; - failtimes: { - fail: number[]; - exit: number[]; - }; - }[]; - current_nominations: []; - description: { - description: string; - }; - genre: { - id: number; - name: string; - }; - language: { - id: number; - name: string; - }; - pack_tags: []; - ratings: number[]; - recent_favourites: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour?: string; - username: string; - }; - related_users: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit?: string; - pm_friends_only: boolean; - profile_colour?: string; - username: string; - }; - user: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour: string; - username: string; - }; -} - - -export interface types { - /** - * Return details about beatmapset for specified beatmap id - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_beatmap_set_lookup = await v2.beatmap.set.lookup(beatmap_id); - * console.log(v2_beatmap_set_lookup); - * }; - * - * main(); - * ``` - * @param {number} beatmap_id id of the beatmap - */ - (beatmap_id: number): Promise; -} diff --git a/src/types/v2_beatmaps_details.ts b/src/types/v2_beatmaps_details.ts deleted file mode 100644 index 6618c7e6..00000000 --- a/src/types/v2_beatmaps_details.ts +++ /dev/null @@ -1,111 +0,0 @@ -export interface response { - beatmapset_id: number; - difficulty_rating: number; - id: number; - mode: string; - status: string; - total_length: number; - user_id: number; - version: string; - accuracy: number; - ar: number; - bpm: number; - convert: boolean; - count_circles: number; - count_sliders: number; - count_spinners: number; - cs: number; - deleted_at: string; - drain: number; - hit_length: number; - is_scoreable: boolean; - last_updated: string; - mode_int: number; - passcount: number; - playcount: number; - ranked: number; - url: string; - checksum: string; - beatmapset: { - artist: string; - artist_unicode: string; - covers: { - cover: string; - 'cover@2x': string; - card: string; - 'card@2x': string; - list: string; - 'list@2x': string; - slimcover: string; - 'slimcover@2x': string; - }; - creator: string; - favourite_count: number; - hype: string; - id: number; - nsfw: boolean; - offset: number; - play_count: number; - preview_url: string; - source: string; - spotlight: boolean; - status: string; - title: string; - title_unicode: string; - track_id: string; - user_id: number; - video: boolean; - bpm: number; - can_be_hyped: boolean; - deleted_at: string; - discussion_enabled: boolean; - discussion_locked: boolean; - is_scoreable: boolean; - last_updated: string; - legacy_thread_url: string; - nominations_summary: { - current: number; - required: number; - }; - ranked: number; - ranked_date: string; - storyboard: boolean; - submitted_date: string; - tags: string; - availability: { - download_disabled: boolean; - more_information: string; - }; - has_favourited: boolean; - ratings: number[]; - }; - failtimes: { - fail: number[]; - exit: number[]; - }; - max_combo: number; -} - - -export interface types { - /** - * Return array of specified beatmaps (limit 50 beatmaps) - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_beatmaps_details = await v2.beatmaps.details(ids); - * console.log(v2_beatmaps_details); - * }; - * - * main(); - * ``` - * @param {number[]} ids Array of beatmap ids - */ - (ids: number[]): Promise; -} diff --git a/src/types/v2_beatmaps_events.ts b/src/types/v2_beatmaps_events.ts deleted file mode 100644 index b4778703..00000000 --- a/src/types/v2_beatmaps_events.ts +++ /dev/null @@ -1,120 +0,0 @@ -export interface response { - events: { - id: number; - type: string; - comment: { - beatmap_discussion_id: string; - beatmap_discussion_post_id: string; - beatmap_id: number; - beatmap_version: string; - new_user_id: number; - new_user_username: string; - }; - created_at: string; - user_id: number; - beatmapset: { - artist: string; - artist_unicode: string; - covers: { - cover: string; - 'cover@2x': string; - card: string; - 'card@2x': string; - list: string; - 'list@2x': string; - slimcover: string; - 'slimcover@2x': string; - }; - creator: string; - favourite_count: number; - hype: { - current: number; - required: number; - }; - id: number; - nsfw: boolean; - offset: number; - play_count: number; - preview_url: string; - source: string; - spotlight: boolean; - status: string; - title: string; - title_unicode: string; - track_id: string; - user_id: number; - video: boolean; - user: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour: string; - username: string; - }; - }; - }[]; - reviewsConfig: { - max_blocks: number; - }; - users: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit?: string; - pm_friends_only: boolean; - profile_colour?: string; - username: string; - groups: { - colour: string; - has_listing: boolean; - has_playmodes: boolean; - id: number; - identifier: string; - is_probationary: boolean; - name: string; - short_name: string; - playmodes: string[]; - }[]; - }[]; -} - - -export interface types { - /** - * Return list of beatmaps events (Nominations, bubbles and etc) - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_beatmaps_events = await v2.beatmaps.events(object); - * console.log(v2_beatmaps_events); - * }; - * - * main(); - * ``` - * @param {string|number} object.user id of the user - * @param {string[]} object.types ```nominate``` or ```qualify``` or ```rank``` or ```love``` or ```nomination_reset``` or ```nomination_reset_received``` or ```disqualify``` or ```remove_from_loved``` or ```kudosu_gain``` or ```kudosu_lost``` or ```genre_edit``` or ```language_edit``` or ```nsfw_toggle``` or ```offset_edit``` or ```issue_resolve``` or ```issue_reopen``` or ```beatmap_owner_change``` or ```kudosu_allow``` or ```kudosu_deny``` or ```approve``` or ```kudosu_recalculate``` or ```discussion_delete``` or ```discussion_restore``` or ```discussion_post_delete``` or ```discussion_post_restore``` - * @param {string} object.min_date Date from - * @param {string} object.max_date Date to - */ - (object: {user?: string | number, types?: Array<'nominate' | 'qualify' | 'rank' | 'love' | 'nomination_reset' | 'nomination_reset_received' | 'disqualify' | 'remove_from_loved' | 'kudosu_gain' | 'kudosu_lost' | 'genre_edit' | 'language_edit' | 'nsfw_toggle' | 'offset_edit' | 'issue_resolve' | 'issue_reopen' | 'beatmap_owner_change' | 'kudosu_allow' | 'kudosu_deny' | 'approve' | 'kudosu_recalculate' | 'discussion_delete' | 'discussion_restore' | 'discussion_post_delete' | 'discussion_post_restore' >, min_date?: string, max_date?: string, }): Promise; -} diff --git a/src/types/v2_beatmaps_search.ts b/src/types/v2_beatmaps_search.ts deleted file mode 100644 index ac4e3b1b..00000000 --- a/src/types/v2_beatmaps_search.ts +++ /dev/null @@ -1,131 +0,0 @@ -export interface response { - beatmapsets: { - artist: string; - artist_unicode: string; - covers: { - cover: string; - 'cover@2x': string; - card: string; - 'card@2x': string; - list: string; - 'list@2x': string; - slimcover: string; - 'slimcover@2x': string; - }; - creator: string; - favourite_count: number; - hype?: string; - id: number; - nsfw: boolean; - offset: number; - play_count: number; - preview_url: string; - source: string; - spotlight: boolean; - status: string; - title: string; - title_unicode: string; - track_id?: number; - user_id: number; - video: boolean; - bpm: number; - can_be_hyped: boolean; - deleted_at?: string; - discussion_enabled: boolean; - discussion_locked: boolean; - is_scoreable: boolean; - last_updated: string; - legacy_thread_url: string; - nominations_summary: { - current: number; - required: number; - }; - ranked: number; - ranked_date: string; - storyboard: boolean; - submitted_date: string; - tags: string; - availability: { - download_disabled: boolean; - more_information: string; - }; - has_favourited: boolean; - beatmaps: { - beatmapset_id: number; - difficulty_rating: number; - id: number; - mode: string; - status: string; - total_length: number; - user_id: number; - version: string; - accuracy: number; - ar: number; - bpm: number; - convert: boolean; - count_circles: number; - count_sliders: number; - count_spinners: number; - cs: number; - deleted_at?: string; - drain: number; - hit_length: number; - is_scoreable: boolean; - last_updated: string; - mode_int: number; - passcount: number; - playcount: number; - ranked: number; - url: string; - checksum: string; - max_combo: number; - }[]; - pack_tags: string[]; - }[]; - search: { - sort: string; - }; - recommended_difficulty: number; - error: string; - total: number; - cursor: { - approved_date: number; - id: number; - }; - cursor_string: string; -} - - -export interface types { - /** - * Return list of beatmaps - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_beatmaps_search = await v2.beatmaps.search(object); - * console.log(v2_beatmaps_search); - * }; - * - * main(); - * ``` - * @param {string} object.query search query, song ``title`` / ``artist``, ``stars``, ``bpm``, ``date`` and etc. - * @param {string} object.sort ```title_desc``` or ```title_asc``` or ```artist_desc``` or ```artist_asc``` or ```difficulty_desc``` or ```difficulty_asc``` or ```updated_desc``` or ```updated_asc``` or ```ranked_desc``` or ```ranked_asc``` or ```rating_desc``` or ```rating_asc``` or ```plays_desc``` or ```plays_asc``` or ```favourites_desc``` or ```favourites_asc``` - * @param {string[]} object.general ```converts``` or ```follows``` or ```recommended``` or ````featured_artists```` or ````spotlights```` - * @param {string} object.mode ```osu``` or ```fruits``` or ```mania``` or ```taiko``` - * @param {string} object.section ```ranked``` or ```qualified``` or ```loved``` or ```favourites``` or ```pending``` or ```wip``` or ```graveyard``` or ```mine``` - * @param {string} object.genre ```Unspecified``` or ```Video Game``` or ```Anime``` or ```Rock``` or ```Pop``` or ```Other``` or ```Novelty``` or ```Hip Hop``` or ```Electronic``` or ```Metal``` or ```Classical``` or ```Folk``` or ```Jazz``` - * @param {string} object.language ```English``` or ```Chinese``` or ```French``` or ```German``` or ```Italian``` or ```Japanese``` or ```Korean``` or ```Spanish``` or ```Swedish``` or ```Russian``` or ```Polish``` or ```Instrumental``` or ```Unspecified``` or ```Other``` - * @param {string} object.include ```video``` or ```storyboard``` - * @param {string[]} object.rank ```XH``` or ```X``` or ```SH``` or ```S``` or ```A``` or ```B``` or ```C``` or ```D``` - * @param {boolean} object.nfsw ```true``` or ```false``` - * @param {string} object.played ```played``` or ```unplayed``` - * @param {string} object.cursor_string Pagination cursor - */ - (object: { query?: string, sort?: 'title_desc' | 'title_asc' | 'artist_desc' | 'artist_asc' | 'difficulty_desc' | 'difficulty_asc' | 'updated_desc' | 'updated_asc' | 'ranked_desc' | 'ranked_asc' | 'rating_desc' | 'rating_asc' | 'plays_desc' | 'plays_asc' | 'favourites_desc' | 'favourites_asc', general?: Array<'converts' | 'follows' | 'recommended' | 'featured_artists' | 'spotlights'>, mode?: 'osu' | 'fruits' | 'mania' | 'taiko', section?: 'ranked' | 'qualified' | 'loved' | 'favourites' | 'pending' | 'wip' | 'graveyard' | 'mine', genre?: 'Unspecified' | 'Video Game' | 'Anime' | 'Rock' | 'Pop' | 'Other' | 'Novelty' | 'Hip Hop' | 'Electronic' | 'Metal' | 'Classical' | 'Folk' | 'Jazz', language?: 'English' | 'Chinese' | 'French' | 'German' | 'Italian' | 'Japanese' | 'Korean' | 'Spanish' | 'Swedish' | 'Russian' | 'Polish' | 'Instrumental' | 'Unspecified' | 'Other', include?: 'video' | 'storyboard', rank?: Array<'XH' | 'X' | 'SH' | 'S' | 'A' | 'B' | 'C' | 'D'>, nfsw?: 'true' | 'false', played?: 'played' | 'unplayed', cursor_string?: string, }): Promise; -} diff --git a/src/types/v2_changelogs_details.ts b/src/types/v2_changelogs_details.ts deleted file mode 100644 index 351d9830..00000000 --- a/src/types/v2_changelogs_details.ts +++ /dev/null @@ -1,89 +0,0 @@ -export interface response { - id: number; - version: number; - display_version: number; - users: number; - created_at: string; - update_stream: { - id: number; - name: string; - display_name: string; - is_featured: boolean; - }; - changelog_entries: { - id?: string; - repository?: string; - github_pull_request_id?: string; - github_url?: string; - url?: string; - type: string; - category: string; - title: string; - major: boolean; - created_at: string; - github_user: { - id: string; - display_name: string; - github_url: string; - osu_username: string; - user_id: number; - user_url: string; - }; - message?: string; - message_html?: string; - }[]; - versions: { - next: { - id: number; - version: number; - display_version: number; - users: number; - created_at: string; - update_stream: { - id: number; - name: string; - display_name: string; - is_featured: boolean; - }; - }; - previous: { - id: number; - version: number; - display_version: number; - users: number; - created_at: string; - update_stream: { - id: number; - name: string; - display_name: string; - is_featured: boolean; - }; - }; - }; - error: string; -} - - -export interface types { - /** - * Returns details of the specified build - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_changelogs_details = await v2.changelogs.details(stream, build); - * console.log(v2_changelogs_details); - * }; - * - * main(); - * ``` - * @param {string} stream ```stable40``` or ```stable``` or ```beta40``` or ```cuttingedge``` or ```lazer``` or ```web``` - * @param {string} build ```id``` or ```name``` of the build - */ - (stream: 'stable40' | 'stable' | 'beta40' | 'cuttingedge' | 'lazer' | 'web' , build: string): Promise; -} diff --git a/src/types/v2_changelogs_list.ts b/src/types/v2_changelogs_list.ts deleted file mode 100644 index 171d5a7a..00000000 --- a/src/types/v2_changelogs_list.ts +++ /dev/null @@ -1,94 +0,0 @@ -export interface response { - streams: { - id: number; - name: string; - display_name: string; - is_featured: boolean; - latest_build: { - created_at: string; - display_version: number; - id: number; - users: number; - version: number; - youtube_id: string; - update_stream: { - id: number; - name: string; - display_name: string; - is_featured: boolean; - }; - }; - user_count: number; - }[]; - builds: { - created_at: string; - display_version: number; - id: number; - users: number; - version: number; - youtube_id?: string; - update_stream: { - id: number; - name: string; - display_name: string; - is_featured: boolean; - }; - changelog_entries: { - id?: string; - repository?: string; - github_pull_request_id?: string; - github_url?: string; - url?: string; - type: string; - category: string; - title: string; - major: boolean; - created_at: string; - github_user: { - id: string; - display_name: string; - github_url: string; - osu_username: string; - user_id: number; - user_url: string; - }; - message?: string; - message_html?: string; - }[]; - }[]; - search: { - stream: string; - from: string; - to: string; - max_id: string; - limit: number; - }; -} - - -export interface types { - /** - * Returns a listing of update streams, builds, and changelog entries - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_changelogs_list = await v2.changelogs.list(object); - * console.log(v2_changelogs_list); - * }; - * - * main(); - * ``` - * @param {string} object.from Minimum build version - * @param {string} object.to Maximum build version - * @param {number} object.max_id Maximum build ID - * @param {string} object.stream ```stable40``` or ```stable``` or ```beta40``` or ```cuttingedge``` or ```lazer``` or ```web``` - * @param {string[]} object.message_formats ```html``` or ```markdown``` - */ - (object: {from?: string, to?: string, max_id?: number, stream?: 'stable40' | 'stable' | 'beta40' | 'cuttingedge' | 'lazer' | 'web' , message_formats?: Array<'html' | 'markdown' >, }): Promise; -} diff --git a/src/types/v2_changelogs_lookup.ts b/src/types/v2_changelogs_lookup.ts deleted file mode 100644 index efeba8b0..00000000 --- a/src/types/v2_changelogs_lookup.ts +++ /dev/null @@ -1,79 +0,0 @@ -export interface response { - created_at: string; - display_version: number; - id: number; - users: number; - version: number; - youtube_id: string; - update_stream: { - id: number; - name: string; - display_name: string; - is_featured: boolean; - }; - changelog_entries: { - id?: string; - repository?: string; - github_pull_request_id?: string; - github_url?: string; - url?: string; - type: string; - category: string; - title: string; - major: boolean; - created_at: string; - github_user: { - id: string; - display_name: string; - github_url: string; - osu_username: string; - user_id: number; - user_url: string; - }; - message?: string; - message_html?: string; - }[]; - versions: { - previous: { - created_at: string; - display_version: number; - id: number; - users: number; - version: number; - youtube_id: string; - update_stream: { - id: number; - name: string; - display_name: string; - is_featured: boolean; - }; - }; - }; - error: string; -} - - -export interface types { - /** - * Returns details of the specified build - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_changelogs_lookup = await v2.changelogs.lookup(changelog, object); - * console.log(v2_changelogs_lookup); - * }; - * - * main(); - * ``` - * @param {string|number} changelog Build version, update stream name, or build ID - * @param {string} object.key Unset to query by build version or stream name, or ```id``` to query by build ID. - * @param {string[]} object.message_formats ```html``` or ```markdown``` - */ - (changelog: string | number, object: {key: string, message_formats: Array<'html' | 'markdown' >, }): Promise; -} diff --git a/src/types/v2_chat_channels_details.ts b/src/types/v2_chat_channels_details.ts deleted file mode 100644 index 23a48872..00000000 --- a/src/types/v2_chat_channels_details.ts +++ /dev/null @@ -1,44 +0,0 @@ -export interface response { - channel: { - channel_id: number; - description: string; - icon: string; - moderated: boolean; - name: string; - type: string; - uuid: string; - current_user_attributes: { - can_message: boolean; - can_message_error: string; - last_read_id: number; - }; - last_message_id: number; - last_read_id: number; - users: []; - }; - users: []; -} - - -export interface types { - /** - * Return details about specified channel (only channel that you joined to) - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login_lazer(USERNAME, USER_PASSWORD); - * - * const v2_chat_channels_details = await v2.chat.channels.details(channel); - * console.log(v2_chat_channels_details); - * }; - * - * main(); - * ``` - * @param {number} channel id of the channel - */ - (channel?: number): Promise; -} diff --git a/src/types/v2_chat_channels_join.ts b/src/types/v2_chat_channels_join.ts deleted file mode 100644 index a9a74a4b..00000000 --- a/src/types/v2_chat_channels_join.ts +++ /dev/null @@ -1,42 +0,0 @@ -export interface response { - channel_id: number; - description: string; - icon: string; - moderated: boolean; - name: string; - type: string; - uuid: string; - current_user_attributes: { - can_message: boolean; - can_message_error: string; - last_read_id: string; - }; - last_message_id: number; - last_read_id: string; - users: []; -} - - -export interface types { - /** - * Join channel by id - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login_lazer(USERNAME, USER_PASSWORD); - * - * const v2_chat_channels_join = await v2.chat.channels.join(channel_id, user_id); - * console.log(v2_chat_channels_join); - * }; - * - * main(); - * ``` - * @param {number} channel_id Channel id - * @param {number} user_id User id - */ - (channel_id: number, user_id: number): Promise; -} diff --git a/src/types/v2_chat_channels_leave.ts b/src/types/v2_chat_channels_leave.ts deleted file mode 100644 index 0826b1e5..00000000 --- a/src/types/v2_chat_channels_leave.ts +++ /dev/null @@ -1,27 +0,0 @@ -export interface response { -} - - -export interface types { - /** - * Remove channel by id - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login_lazer(USERNAME, USER_PASSWORD); - * - * const v2_chat_channels_leave = await v2.chat.channels.leave(channel_id, user_id); - * console.log(v2_chat_channels_leave); - * }; - * - * main(); - * ``` - * @param {number} channel_id Channel id - * @param {number} user_id User id - */ - (channel_id: number, user_id: number): Promise; -} diff --git a/src/types/v2_chat_channels_list.ts b/src/types/v2_chat_channels_list.ts deleted file mode 100644 index e785b2e8..00000000 --- a/src/types/v2_chat_channels_list.ts +++ /dev/null @@ -1,32 +0,0 @@ -export interface response { - channel_id: number; - description: string; - icon: string; - moderated: boolean; - name: string; - type: string; - uuid: string; -} - - -export interface types { - /** - * Return list of channels - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login_lazer(USERNAME, USER_PASSWORD); - * - * const v2_chat_channels_list = await v2.chat.channels.list(); - * console.log(v2_chat_channels_list); - * }; - * - * main(); - * ``` - */ - (): Promise; -} diff --git a/src/types/v2_chat_channels_messages_list.ts b/src/types/v2_chat_channels_messages_list.ts deleted file mode 100644 index e7a3f47a..00000000 --- a/src/types/v2_chat_channels_messages_list.ts +++ /dev/null @@ -1,51 +0,0 @@ -export interface response { - channel_id: number; - content: number; - is_action: boolean; - message_id: number; - sender_id: number; - timestamp: string; - type: string; - sender: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour: string; - username: string; - }; -} - - -export interface types { - /** - * Return chat messages for a specific channel - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login_lazer(USERNAME, USER_PASSWORD); - * - * const v2_chat_channels_messages_list = await v2.chat.channels.messages.list(channel_id, object); - * console.log(v2_chat_channels_messages_list); - * }; - * - * main(); - * ``` - * @param {number} channel_id id of the channel - * @param {number} object.limit Maximum number of results (Max 50) - * @param {number} object.since Messages after the specified message id will be returned - * @param {number} object.until Messages up to but not including the specified message id will be returned - */ - (channel_id: number, object: {limit?: number, since?: number, until?: number, }): Promise; -} diff --git a/src/types/v2_chat_channels_messages_markAsReaded.ts b/src/types/v2_chat_channels_messages_markAsReaded.ts deleted file mode 100644 index dcc1b1b3..00000000 --- a/src/types/v2_chat_channels_messages_markAsReaded.ts +++ /dev/null @@ -1,27 +0,0 @@ -export interface response { -} - - -export interface types { - /** - * This endpoint marks the channel as having being read up to the given ```message_id``` - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login_lazer(USERNAME, USER_PASSWORD); - * - * const v2_chat_channels_messages_markAsReaded = await v2.chat.channels.messages.markAsReaded(channel_id, message_id); - * console.log(v2_chat_channels_messages_markAsReaded); - * }; - * - * main(); - * ``` - * @param {number} channel_id The ```channel_id``` of the channel to mark as read - * @param {number} message_id The ```message_id``` of the message to mark as read up to - */ - (channel_id?: number, message_id?: number): Promise; -} diff --git a/src/types/v2_chat_channels_messages_send.ts b/src/types/v2_chat_channels_messages_send.ts deleted file mode 100644 index 33152145..00000000 --- a/src/types/v2_chat_channels_messages_send.ts +++ /dev/null @@ -1,50 +0,0 @@ -export interface response { - channel_id: number; - content: number; - is_action: boolean; - message_id: number; - sender_id: number; - timestamp: string; - type: string; - sender: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour: string; - username: string; - }; -} - - -export interface types { - /** - * Send message to chat channel - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login_lazer(USERNAME, USER_PASSWORD); - * - * const v2_chat_channels_messages_send = await v2.chat.channels.messages.send(channel_id, message, is_action); - * console.log(v2_chat_channels_messages_send); - * }; - * - * main(); - * ``` - * @param {number} channel_id The channel_id of the channel to send message to - * @param {number} message Message to send - * @param {number} is_action Whether the message is an action - */ - (channel_id: number, message: number, is_action: number): Promise; -} diff --git a/src/types/v2_chat_new.ts b/src/types/v2_chat_new.ts deleted file mode 100644 index f14414b3..00000000 --- a/src/types/v2_chat_new.ts +++ /dev/null @@ -1,65 +0,0 @@ -export interface response { - channel: { - channel_id: number; - description: string; - icon: string; - moderated: boolean; - name: string; - type: string; - uuid: string; - last_message_id: number; - users: number[]; - }; - message: { - channel_id: number; - content: string; - is_action: boolean; - message_id: number; - sender_id: number; - timestamp: string; - type: string; - sender: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour: string; - username: string; - }; - }; - new_channel_id: number; -} - - -export interface types { - /** - * Send new message to user - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * - * - * const v2_chat_new = await v2.chat.new(target_id, message, is_action, uuid); - * console.log(v2_chat_new); - * }; - * - * main(); - * ``` - * @param {string} target_id User id to start PM with - * @param {string} message message to send - * @param {boolean} is_action whether the message is an action - * @param {string} uuid client-side message identifier which will be sent back in response and websocket json - */ - (target_id: string, message: string, is_action?: boolean, uuid?: string): Promise; -} diff --git a/src/types/v2_chat_updates.ts b/src/types/v2_chat_updates.ts deleted file mode 100644 index 236e21e8..00000000 --- a/src/types/v2_chat_updates.ts +++ /dev/null @@ -1,51 +0,0 @@ -export interface response { - presence: { - channel_id: number; - description: string; - icon: string; - message_length_limit: number; - moderated: boolean; - name: string; - type: string; - uuid?: string; - current_user_attributes: { - can_message: boolean; - can_message_error: string; - last_read_id: number; - }; - last_message_id: number; - last_read_id?: number; - users: number[]; - }[]; - silences: { - id: number; - user_id: number; - }[]; - messages: []; -} - - -export interface types { - /** - * This endpoint returns new messages since the given message_id along with updated channel 'presence' data. - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login_lazer(USERNAME, USER_PASSWORD); - * - * const v2_chat_updates = await v2.chat.updates(object); - * console.log(v2_chat_updates); - * }; - * - * main(); - * ``` - * @param {number} object.history_since UserSilence after the specified id to return - * @param {string[]} object.includes ```presence```, ```messages```, ```silences``` - * @param {number} object.since Messages after the specified message_id to return - */ - (object: {history_since?: number, includes?: Array<'presence, messages, silences' >, since: number, }): Promise; -} diff --git a/src/types/v2_comments_details.ts b/src/types/v2_comments_details.ts deleted file mode 100644 index 947ee8a4..00000000 --- a/src/types/v2_comments_details.ts +++ /dev/null @@ -1,98 +0,0 @@ -export interface response { - comments: { - id: number; - parent_id: string; - user_id: number; - pinned: boolean; - replies_count: number; - votes_count: number; - commentable_type: string; - commentable_id: number; - legacy_name: string; - created_at: string; - updated_at: string; - deleted_at: string; - edited_at: string; - edited_by_id: string; - message: string; - message_html: string; - }[]; - has_more: boolean; - has_more_id: number; - included_comments: { - id: number; - parent_id: number; - user_id: number; - pinned: boolean; - replies_count: number; - votes_count: number; - commentable_type: string; - commentable_id: number; - legacy_name?: string; - created_at: string; - updated_at: string; - deleted_at?: string; - edited_at?: string; - edited_by_id?: string; - message?: string; - message_html?: string; - }[]; - pinned_comments: []; - user_votes: []; - user_follow: boolean; - users: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour: string; - username: string; - }[]; - sort: string; - cursor: { - created_at: string; - id: number; - }; - commentable_meta: { - current_user_attributes: { - can_new_comment_reason: string; - }; - id?: number; - type?: string; - title: string; - url?: string; - owner_id?: number; - owner_title?: string; - }[]; -} - - -export interface types { - /** - * Gets a comment and its replies up to 2 levels deep - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_comments_details = await v2.comments.details(comment); - * console.log(v2_comments_details); - * }; - * - * main(); - * ``` - * @param {number} comment id of the comment - */ - (comment: number): Promise; -} diff --git a/src/types/v2_comments_edit.ts b/src/types/v2_comments_edit.ts deleted file mode 100644 index fe11c5d5..00000000 --- a/src/types/v2_comments_edit.ts +++ /dev/null @@ -1,84 +0,0 @@ -export interface response { - comments: { - id: number; - parent_id: string; - user_id: number; - pinned: boolean; - replies_count: number; - votes_count: number; - commentable_type: string; - commentable_id: number; - legacy_name: string; - created_at: string; - updated_at: string; - deleted_at: string; - edited_at: string; - edited_by_id: number; - message: string; - message_html: string; - }[]; - has_more: boolean; - has_more_id: string; - included_comments: []; - pinned_comments: []; - user_votes: []; - user_follow: boolean; - users: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour: string; - username: string; - }[]; - sort: string; - cursor: { - created_at: string; - id: number; - }; - top_level_count: number; - total: number; - commentable_meta: { - current_user_attributes: { - can_new_comment_reason: string; - }; - id?: number; - type?: string; - title: string; - url?: string; - owner_id?: number; - owner_title?: string; - }[]; -} - - -export interface types { - /** - * Edit your comment by id - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_comments_edit = await v2.comments.edit(comment_id, message); - * console.log(v2_comments_edit); - * }; - * - * main(); - * ``` - * @param {number} comment_id Comment id - * @param {string} message Text of the message - */ - (comment_id: number, message: string): Promise; -} diff --git a/src/types/v2_comments_list.ts b/src/types/v2_comments_list.ts deleted file mode 100644 index bb0bca88..00000000 --- a/src/types/v2_comments_list.ts +++ /dev/null @@ -1,105 +0,0 @@ -export interface response { - comments: { - id: number; - parent_id?: number; - user_id: number; - pinned: boolean; - replies_count: number; - votes_count: number; - commentable_type: string; - commentable_id: number; - legacy_name?: string; - created_at: string; - updated_at: string; - deleted_at?: string; - edited_at?: string; - edited_by_id?: string; - message: string; - message_html: string; - }[]; - has_more: boolean; - has_more_id: string; - included_comments: { - id: number; - parent_id?: string; - user_id: number; - pinned: boolean; - replies_count: number; - votes_count: number; - commentable_type: string; - commentable_id: number; - legacy_name?: string; - created_at: string; - updated_at: string; - deleted_at?: string; - edited_at?: string; - edited_by_id?: string; - message: string; - message_html: string; - }[]; - pinned_comments: []; - user_votes: []; - user_follow: boolean; - users: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit?: string; - pm_friends_only: boolean; - profile_colour?: string; - username: string; - }[]; - sort: string; - cursor: { - created_at: string; - id: number; - }; - top_level_count: number; - total: number; - commentable_meta: { - current_user_attributes: { - can_new_comment_reason: string; - }; - id?: number; - type?: string; - title: string; - url?: string; - owner_id?: number; - owner_title?: string; - }[]; -} - - -export interface types { - /** - * Returns a list comments and their replies up to 2 levels deep - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_comments_list = await v2.comments.list(object); - * console.log(v2_comments_list); - * }; - * - * main(); - * ``` - * @param {string} object.commentable_type ```news_post``` or ```beatmapset``` - * @param {string} object.commentable_id id of the resource to get comments for - * @param {number} object.cursor.id - * @param {string} object.cursor.created_at - * @param {string} object.parent_id id of the comment parent - * @param {string} object.sort ```new``` or ```old``` or ```top``` - */ - (object: {commentable_type?: 'news_post' | 'beatmapset' , commentable_id?: string, cursor: {id?: number, created_at?: string, }, parent_id?: string, sort?: 'new' | 'old' | 'top' , }): Promise; -} diff --git a/src/types/v2_comments_new.ts b/src/types/v2_comments_new.ts deleted file mode 100644 index 79126903..00000000 --- a/src/types/v2_comments_new.ts +++ /dev/null @@ -1,86 +0,0 @@ -export interface response { - comments: { - id: number; - parent_id: string; - user_id: number; - pinned: boolean; - replies_count: number; - votes_count: number; - commentable_type: string; - commentable_id: number; - legacy_name: string; - created_at: string; - updated_at: string; - deleted_at: string; - edited_at: string; - edited_by_id: string; - message: string; - message_html: string; - }[]; - has_more: boolean; - has_more_id: string; - included_comments: []; - pinned_comments: []; - user_votes: []; - user_follow: boolean; - users: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour: string; - username: string; - }[]; - sort: string; - cursor: { - created_at: string; - id: number; - }; - top_level_count: number; - total: number; - commentable_meta: { - current_user_attributes: { - can_new_comment_reason: string; - }; - id?: number; - type?: string; - title: string; - url?: string; - owner_id?: number; - owner_title?: string; - }[]; -} - - -export interface types { - /** - * Posts a new comment to a comment thread - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_comments_new = await v2.comments.new(comment); - * console.log(v2_comments_new); - * }; - * - * main(); - * ``` - * @param {string} comment.commentable_id Resource ID the comment thread is attached to - * @param {string} comment.commentable_type ```news_post``` or ```beatmapset``` - * @param {string} comment.message Text of the comment - * @param {string} comment.parent_id The id of the comment to reply to, null if not a reply - */ - (comment: {commentable_id?: string, commentable_type?: 'news_post' | 'beatmapset' , message?: string, parent_id?: string, }): Promise; -} diff --git a/src/types/v2_comments_remove.ts b/src/types/v2_comments_remove.ts deleted file mode 100644 index e9271a8b..00000000 --- a/src/types/v2_comments_remove.ts +++ /dev/null @@ -1,81 +0,0 @@ -export interface response { - comments: { - id: number; - parent_id: string; - user_id: number; - pinned: boolean; - replies_count: number; - votes_count: number; - commentable_type: string; - commentable_id: number; - legacy_name: string; - created_at: string; - updated_at: string; - deleted_at: string; - edited_at: string; - edited_by_id: number; - }[]; - has_more: boolean; - has_more_id: string; - included_comments: []; - pinned_comments: []; - user_votes: []; - user_follow: boolean; - users: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour: string; - username: string; - }[]; - sort: string; - cursor: { - created_at: string; - id: number; - }; - top_level_count: number; - total: number; - commentable_meta: { - current_user_attributes: { - can_new_comment_reason: string; - }; - id?: number; - type?: string; - title: string; - url?: string; - owner_id?: number; - owner_title?: string; - }[]; -} - - -export interface types { - /** - * Delete your comment by id - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_comments_remove = await v2.comments.remove(comment_id); - * console.log(v2_comments_remove); - * }; - * - * main(); - * ``` - * @param {number} comment_id Comment id - */ - (comment_id: number): Promise; -} diff --git a/src/types/v2_comments_vote.ts b/src/types/v2_comments_vote.ts deleted file mode 100644 index 28dceafe..00000000 --- a/src/types/v2_comments_vote.ts +++ /dev/null @@ -1,84 +0,0 @@ -export interface response { - comments: { - id: number; - parent_id: string; - user_id: number; - pinned: boolean; - replies_count: number; - votes_count: number; - commentable_type: string; - commentable_id: number; - legacy_name: string; - created_at: string; - updated_at: string; - deleted_at: string; - edited_at: string; - edited_by_id: string; - message: string; - message_html: string; - }[]; - has_more: boolean; - has_more_id: string; - included_comments: []; - pinned_comments: []; - user_votes: number[]; - user_follow: boolean; - users: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour: string; - username: string; - }[]; - sort: string; - cursor: { - created_at: string; - id: number; - }; - top_level_count: number; - total: number; - commentable_meta: { - current_user_attributes: { - can_new_comment_reason: string; - }; - id?: number; - type?: string; - title: string; - url?: string; - owner_id?: number; - owner_title?: string; - }[]; -} - - -export interface types { - /** - * Delete your comment by id - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_comments_vote = await v2.comments.vote(comment_id, type); - * console.log(v2_comments_vote); - * }; - * - * main(); - * ``` - * @param {number} comment_id Comment id - * @param {boolean} type ```true``` (Upvote) or ```false``` (Downvote) - */ - (comment_id: number, type: boolean): Promise; -} diff --git a/src/types/v2_forums_post_edit.ts b/src/types/v2_forums_post_edit.ts deleted file mode 100644 index b8e714c2..00000000 --- a/src/types/v2_forums_post_edit.ts +++ /dev/null @@ -1,39 +0,0 @@ -export interface response { - created_at: string; - deleted_at: string; - edited_at: string; - edited_by_id: number; - forum_id: number; - id: number; - topic_id: number; - user_id: number; - body: { - html: string; - raw: string; - }; -} - - -export interface types { - /** - * - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login_lazer(USERNAME, USER_PASSWORD); - * - * const v2_forums_post_edit = await v2.forums.post.edit(post_id, body); - * console.log(v2_forums_post_edit); - * }; - * - * main(); - * ``` - * @param {number} post_id Post id - * @param {number} body Body of the post - */ - (post_id: number, body: number): Promise; -} diff --git a/src/types/v2_forums_topic_details.ts b/src/types/v2_forums_topic_details.ts deleted file mode 100644 index 87eba14a..00000000 --- a/src/types/v2_forums_topic_details.ts +++ /dev/null @@ -1,88 +0,0 @@ -export interface response { - posts: { - created_at: string; - deleted_at?: string; - edited_at?: string; - edited_by_id?: string; - forum_id: number; - id: number; - topic_id: number; - user_id: number; - body: { - html: string; - raw: string; - }; - }[]; - search: { - limit: number; - sort: string; - }; - topic: { - created_at: string; - deleted_at: string; - first_post_id: number; - forum_id: number; - id: number; - is_locked: boolean; - last_post_id: number; - post_count: number; - title: string; - type: string; - updated_at: string; - user_id: number; - poll: { - allow_vote_change: boolean; - ended_at: string; - hide_incomplete_results: boolean; - last_vote_at: string; - max_votes: number; - started_at: string; - title: { - bbcode: string; - html: string; - }; - total_vote_count: number; - options: { - id: number; - text: { - bbcode: string; - html: string; - }; - vote_count: number; - }[]; - }; - }; - cursor: { - id: number; - }; - cursor_string: string; -} - - -export interface types { - /** - * Return topic data and posts list - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_forums_topic_details = await v2.forums.topic.details(topic, object); - * console.log(v2_forums_topic_details); - * }; - * - * main(); - * ``` - * @param {number} topic Topic id - * @param {string} object.cursor_string Parameter for pagination - * @param {string} object.sort ```id_asc``` or ```id_desc``` - * @param {number} object.limit Maximum number of posts to be returned (20 default, 50 at most) - * @param {string} object.start First post id to be returned with sort set to id_asc. This parameter is ignored if cursor_string is specified - * @param {string} object.end Last post id to be returned with sort set to id_desc. This parameter is ignored if cursor_string is specified. - */ - (topic: number, object: {cursor_string?: string, sort?: 'id_asc' | 'id_desc' , limit?: number, start?: string, end?: string, }): Promise; -} diff --git a/src/types/v2_forums_topic_edit.ts b/src/types/v2_forums_topic_edit.ts deleted file mode 100644 index 5da07774..00000000 --- a/src/types/v2_forums_topic_edit.ts +++ /dev/null @@ -1,57 +0,0 @@ -export interface response { - title: { - created_at: string; - deleted_at: string; - first_post_id: number; - forum_id: number; - id: number; - is_locked: boolean; - last_post_id: number; - post_count: number; - title: string; - type: string; - updated_at: string; - user_id: number; - poll: string; - }; - body: { - created_at: string; - deleted_at: string; - edited_at: string; - edited_by_id: number; - forum_id: number; - id: number; - topic_id: number; - user_id: number; - body: { - html: string; - raw: string; - }; - }; -} - - -export interface types { - /** - * Edit your topic and post from the forum - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login_lazer(USERNAME, USER_PASSWORD); - * - * const v2_forums_topic_edit = await v2.forums.topic.edit(topic_id, object); - * console.log(v2_forums_topic_edit); - * }; - * - * main(); - * ``` - * @param {number} topic_id Topic id - * @param {string} object.title New title - * @param {string} object.body New body - */ - (topic_id: number, object: {title?: string, body?: string, }): Promise; -} diff --git a/src/types/v2_forums_topic_new.ts b/src/types/v2_forums_topic_new.ts deleted file mode 100644 index 5f6d8279..00000000 --- a/src/types/v2_forums_topic_new.ts +++ /dev/null @@ -1,63 +0,0 @@ -export interface response { - topic: { - created_at: string; - deleted_at: string; - first_post_id: number; - forum_id: number; - id: number; - is_locked: boolean; - last_post_id: number; - post_count: number; - title: string; - type: string; - updated_at: string; - user_id: number; - poll: string; - }; - post: { - created_at: string; - deleted_at: string; - edited_at: string; - edited_by_id: string; - forum_id: number; - id: number; - topic_id: number; - user_id: number; - body: { - html: string; - raw: string; - }; - }; -} - - -export interface types { - /** - * Edit your topic and post from the forum - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login_lazer(USERNAME, USER_PASSWORD); - * - * const v2_forums_topic_new = await v2.forums.topic.new(forum_id, object, poll); - * console.log(v2_forums_topic_new); - * }; - * - * main(); - * ``` - * @param {number} forum_id Forum id - * @param {string} object.title Title of the topic - * @param {string} object.body Body of the topic - * @param {string} poll.title Title of the poll. - * @param {string[]} poll.options Newline-separated list of voting options. BBCode is supported. - * @param {boolean} poll.hide_results Hide results of the poll until voting period ends - * @param {number} poll.length_days Number of days for voting period. 0 means the voting will never ends (default: 0). This parameter is required if hide_results option is enabled. - * @param {number} poll.max_options This is the number of options each user may select when voting. - * @param {boolean} poll.vote_change Enable this to allow user to change their votes (default: false). - */ - (forum_id: number, object: {title: string, body: string, }, poll: {title: string, options: string[], hide_results?: boolean, length_days?: number, max_options?: number, vote_change?: boolean, }): Promise; -} diff --git a/src/types/v2_forums_topic_reply.ts b/src/types/v2_forums_topic_reply.ts deleted file mode 100644 index 1b579011..00000000 --- a/src/types/v2_forums_topic_reply.ts +++ /dev/null @@ -1,39 +0,0 @@ -export interface response { - created_at: string; - deleted_at: string; - edited_at: string; - edited_by_id: string; - forum_id: number; - id: number; - topic_id: number; - user_id: number; - body: { - html: string; - raw: string; - }; -} - - -export interface types { - /** - * Edit your topic and post from the forum - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login_lazer(USERNAME, USER_PASSWORD); - * - * const v2_forums_topic_reply = await v2.forums.topic.reply(topic_id, body); - * console.log(v2_forums_topic_reply); - * }; - * - * main(); - * ``` - * @param {number} topic_id Topic id - * @param {number} body Message body - */ - (topic_id: number, body: number): Promise; -} diff --git a/src/types/v2_matches_details.ts b/src/types/v2_matches_details.ts deleted file mode 100644 index 4cda3271..00000000 --- a/src/types/v2_matches_details.ts +++ /dev/null @@ -1,148 +0,0 @@ -export interface response { - match: { - id: number; - start_time: string; - end_time: string; - name: string; - }; - events: { - id: number; - detail: { - type: string; - text: string; - }; - timestamp: string; - user_id?: number; - game: { - beatmap_id: number; - id: number; - start_time: string; - end_time: string; - mode: string; - mode_int: number; - scoring_type: string; - team_type: string; - mods: string[]; - beatmap: { - beatmapset_id: number; - difficulty_rating: number; - id: number; - mode: string; - status: string; - total_length: number; - user_id: number; - version: string; - beatmapset: { - artist: string; - artist_unicode: string; - covers: { - cover: string; - 'cover@2x': string; - card: string; - 'card@2x': string; - list: string; - 'list@2x': string; - slimcover: string; - 'slimcover@2x': string; - }; - creator: string; - favourite_count: number; - hype: string; - id: number; - nsfw: boolean; - offset: number; - play_count: number; - preview_url: string; - source: string; - spotlight: boolean; - status: string; - title: string; - title_unicode: string; - track_id: string; - user_id: number; - video: boolean; - }; - }; - scores: { - accuracy: number; - best_id?: string; - created_at: string; - id?: string; - max_combo: number; - mode: string; - mode_int: number; - mods: string[]; - passed: boolean; - perfect: number; - pp?: string; - rank: string; - replay: boolean; - score: number; - statistics: { - count_100: number; - count_300: number; - count_50: number; - count_geki: number; - count_katu: number; - count_miss: number; - }; - type: string; - user_id: number; - current_user_attributes: { - pin: string; - }; - match: { - slot: number; - team: string; - pass: boolean; - }; - }[]; - }; - }[]; - users: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit?: string; - pm_friends_only: boolean; - profile_colour?: string; - username: string; - country: { - code: string; - name: string; - }; - }[]; - first_event_id: number; - latest_event_id: number; - current_game_id: string; -} - - -export interface types { - /** - * Return match data for specified id - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_matches_details = await v2.matches.details(match); - * console.log(v2_matches_details); - * }; - * - * main(); - * ``` - * @param {number} match id of the match - */ - (match: number): Promise; -} diff --git a/src/types/v2_matches_list.ts b/src/types/v2_matches_list.ts deleted file mode 100644 index 2d66c22e..00000000 --- a/src/types/v2_matches_list.ts +++ /dev/null @@ -1,39 +0,0 @@ -export interface response { - matches: { - id: number; - start_time: string; - end_time?: string; - name: string; - }[]; - params: { - limit: number; - sort: string; - }; - cursor: { - match_id: number; - }; - cursor_string: string; -} - - -export interface types { - /** - * Return array of the matches - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_matches_list = await v2.matches.list(); - * console.log(v2_matches_list); - * }; - * - * main(); - * ``` - */ - (): Promise; -} diff --git a/src/types/v2_notifications_list.ts b/src/types/v2_notifications_list.ts deleted file mode 100644 index e75b98cd..00000000 --- a/src/types/v2_notifications_list.ts +++ /dev/null @@ -1,62 +0,0 @@ -export interface response { - notifications: { - id: number; - name: string; - created_at: string; - object_type: string; - object_id: number; - source_user_id: number; - is_read: boolean; - details: { - title: string; - username: string; - cover_url: string; - beatmapset_id: number; - title_unicode: string; - type: string; - post_id: number; - }; - }[]; - stacks: { - category: string; - cursor?: string; - name: string; - object_type: string; - object_id: number; - total: number; - }[]; - timestamp: string; - types: { - cursor: { - id: number; - type: string; - }; - name: string; - total: number; - }[]; - notification_endpoint: string; -} - - -export interface types { - /** - * This endpoint returns a list of the user's unread notifications. Sorted descending by id with limit of 50. - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login_lazer(USERNAME, USER_PASSWORD); - * - * const v2_notifications_list = await v2.notifications.list(max_id); - * console.log(v2_notifications_list); - * }; - * - * main(); - * ``` - * @param {string} max_id Maximum ```id``` fetched. Can be used to load earlier notifications. Defaults to no limit (fetch latest notifications) - */ - (max_id?: string): Promise; -} diff --git a/src/types/v2_notifications_markAsReaded.ts b/src/types/v2_notifications_markAsReaded.ts deleted file mode 100644 index 71b22fa5..00000000 --- a/src/types/v2_notifications_markAsReaded.ts +++ /dev/null @@ -1,26 +0,0 @@ -export interface response { -} - - -export interface types { - /** - * This endpoint allows you to mark notifications read - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_notifications_markAsReaded = await v2.notifications.markAsReaded(ids); - * console.log(v2_notifications_markAsReaded); - * }; - * - * main(); - * ``` - * @param {number array} ids ```id``` of notifications to be marked as read - */ - (ids: 'id of notifications to be marked as read' ): Promise; -} diff --git a/src/types/v2_scores_beatmap.ts b/src/types/v2_scores_beatmap.ts deleted file mode 100644 index ec1bcf0a..00000000 --- a/src/types/v2_scores_beatmap.ts +++ /dev/null @@ -1,81 +0,0 @@ -export interface response { - position: number; - accuracy: number; - best_id: number; - created_at: string; - id: number; - max_combo: number; - mode: string; - mode_int: number; - mods: string[]; - passed: boolean; - perfect: boolean; - pp: number; - rank: string; - replay: boolean; - score: number; - statistics: { - count_100: number; - count_300: number; - count_50: number; - count_geki: number; - count_katu: number; - count_miss: number; - }; - type: string; - user_id: number; - current_user_attributes: { - pin: string; - }; - user: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour: string; - username: string; - country: { - code: string; - name: string; - }; - cover: { - custom_url: string; - url: string; - id: string; - }; - }; -} - - -export interface types { - /** - * Returns the top scores for a beatmap - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_scores_beatmap = await v2.scores.beatmap(beatmap, object); - * console.log(v2_scores_beatmap); - * }; - * - * main(); - * ``` - * @param {number} beatmap id of the beatmap - * @param {string} object.mode ```osu``` or ```fruits``` or ```mania``` or ```taiko``` - * @param {string[]} object.mods Array of matching mods ['HD', 'DT'] - * @param {string} object.type ```global``` or ```country``` or ```friend``` - */ - (beatmap: number, object: {mode?: 'osu' | 'fruits' | 'mania' | 'taiko' , mods?: string[], type?: 'global' | 'country' | 'friend' , }): Promise; -} diff --git a/src/types/v2_scores_download.ts b/src/types/v2_scores_download.ts deleted file mode 100644 index ade55d5e..00000000 --- a/src/types/v2_scores_download.ts +++ /dev/null @@ -1,28 +0,0 @@ -export interface response { -} - - -export interface types { - /** - * Download score replay file - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login_lazer(USERNAME, USER_PASSWORD); - * - * const v2_scores_download = await v2.scores.download(score_id, mode, file_path); - * console.log(v2_scores_download); - * }; - * - * main(); - * ``` - * @param {number} score_id id of the score - * @param {string} mode ```osu``` or ```fruits``` or ```mania``` or ```taiko``` - * @param {string} file_path File path with ```.osr``` at the end - */ - (score_id: number, mode: 'osu' | 'fruits' | 'mania' | 'taiko' , file_path: 'File path with .osr at the end' ): Promise; -} diff --git a/src/types/v2_site_news_details.ts b/src/types/v2_site_news_details.ts deleted file mode 100644 index 37ff5efb..00000000 --- a/src/types/v2_site_news_details.ts +++ /dev/null @@ -1,58 +0,0 @@ -export interface response { - id: number; - author: string; - edit_url: string; - first_image: string; - published_at: string; - updated_at: string; - slug: string; - title: string; - content: string; - navigation: { - newer: { - id: number; - author: string; - edit_url: string; - first_image: string; - published_at: string; - updated_at: string; - slug: string; - title: string; - }; - older: { - id: number; - author: string; - edit_url: string; - first_image: string; - published_at: string; - updated_at: string; - slug: string; - title: string; - }; - }; -} - - -export interface types { - /** - * Returns details of the specified news post - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_site_news_details = await v2.site.news.details(news, key); - * console.log(v2_site_news_details); - * }; - * - * main(); - * ``` - * @param {string | number} news News post slug or ID - * @param {string} key Unset to query by slug, or id to query by ID - */ - (news: string | number, key: string): Promise; -} diff --git a/src/types/v2_site_news_list.ts b/src/types/v2_site_news_list.ts deleted file mode 100644 index 6c967b49..00000000 --- a/src/types/v2_site_news_list.ts +++ /dev/null @@ -1,64 +0,0 @@ -export interface response { - news_posts: { - id: number; - author: string; - edit_url: string; - first_image: string; - published_at: string; - updated_at: string; - slug: string; - title: string; - preview: string; - }[]; - news_sidebar: { - current_year: number; - news_posts: { - id: number; - author: string; - edit_url: string; - first_image: string; - published_at: string; - updated_at: string; - slug: string; - title: string; - }[]; - years: number[]; - }; - search: { - limit: number; - sort: string; - year: string; - }; - cursor: { - published_at: string; - id: number; - }; - cursor_string: string; -} - - -export interface types { - /** - * Returns a list of news posts and related metadata - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_site_news_list = await v2.site.news.list(object); - * console.log(v2_site_news_list); - * }; - * - * main(); - * ``` - * @param {number} object.limit Maximum number of posts (12 default, 1 minimum, 21 maximum) - * @param {number} object.year Year to return posts from - * @param {string} object.cursorPublished Pagination cursorPublished - * @param {number} object.cursorId Pagination cursorId - */ - (object: {limit?: number, year?: number, cursorPublished?: string, cursorId?: number, }): Promise; -} diff --git a/src/types/v2_site_search.ts b/src/types/v2_site_search.ts deleted file mode 100644 index 134af71d..00000000 --- a/src/types/v2_site_search.ts +++ /dev/null @@ -1,59 +0,0 @@ -export interface response { - user: { - data: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit?: string; - pm_friends_only: boolean; - profile_colour?: string; - username: string; - }[]; - total: number; - }; - wiki_page: { - data: { - available_locales: string[]; - layout: string; - locale: string; - markdown: string; - path: string; - subtitle: string; - tags: []; - title: string; - }[]; - total: number; - }; -} - - -export interface types { - /** - * Searches users and wiki pages. - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_site_search = await v2.site.search(object); - * console.log(v2_site_search); - * }; - * - * main(); - * ``` - * @param {string} object.mode ```all``` or ```user``` or ```wiki_page``` - * @param {string} object.query Search keyword - * @param {number} object.page Search result page. Ignored for mode all - */ - (object: {mode?: 'all' | 'user' | 'wiki_page' , query?: string, page?: number, }): Promise; -} diff --git a/src/types/v2_site_spotlights_list.ts b/src/types/v2_site_spotlights_list.ts deleted file mode 100644 index 1f0b97a0..00000000 --- a/src/types/v2_site_spotlights_list.ts +++ /dev/null @@ -1,31 +0,0 @@ -export interface response { - end_date: string; - id: number; - mode_specific: boolean; - name: string; - start_date: string; - type: string; -} - - -export interface types { - /** - * Return list of spotlights - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_site_spotlights_list = await v2.site.spotlights.list(); - * console.log(v2_site_spotlights_list); - * }; - * - * main(); - * ``` - */ - (): Promise; -} diff --git a/src/types/v2_site_wiki.ts b/src/types/v2_site_wiki.ts deleted file mode 100644 index 4b98cbf1..00000000 --- a/src/types/v2_site_wiki.ts +++ /dev/null @@ -1,35 +0,0 @@ -export interface response { - available_locales: string[]; - layout: string; - locale: string; - markdown: string; - path: string; - subtitle: string; - tags: []; - title: string; -} - - -export interface types { - /** - * Return data about wiki page - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_site_wiki = await v2.site.wiki(language, path); - * console.log(v2_site_wiki); - * }; - * - * main(); - * ``` - * @param {string} language Language code of the wiki page - * @param {string} path The path name of the wiki page - */ - (language: string, path: string): Promise; -} diff --git a/src/types/v2_user_activity.ts b/src/types/v2_user_activity.ts deleted file mode 100644 index 1ac6c487..00000000 --- a/src/types/v2_user_activity.ts +++ /dev/null @@ -1,58 +0,0 @@ -export interface response { - created_at: string; - createdAt: string; - id: number; - type: string; - scoreRank: string; - rank: number; - mode: string; - beatmap: { - title: string; - url: string; - }; - user: { - username: string; - url: string; - }; - beatmapset: { - title: string; - url: string; - }; - achievement: { - icon_url: string; - id: number; - name: string; - grouping: string; - ordering: number; - slug: string; - description: string; - mode: string; - instructions: string; - }; -} - - -export interface types { - /** - * Return list of recent user activity - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_user_activity = await v2.user.activity(user, object); - * console.log(v2_user_activity); - * }; - * - * main(); - * ``` - * @param {number} user id of the user - * @param {number} object.limit Maximum number of results - * @param {string} object.offset Result offset for pagination - */ - (user: number, object: {limit?: number, offset?: string, }): Promise; -} diff --git a/src/types/v2_user_beatmaps_category.ts b/src/types/v2_user_beatmaps_category.ts deleted file mode 100644 index 9a629982..00000000 --- a/src/types/v2_user_beatmaps_category.ts +++ /dev/null @@ -1,108 +0,0 @@ -export interface response { - artist: string; - artist_unicode: string; - covers: { - cover: string; - 'cover@2x': string; - card: string; - 'card@2x': string; - list: string; - 'list@2x': string; - slimcover: string; - 'slimcover@2x': string; - }; - creator: string; - favourite_count: number; - hype: string; - id: number; - nsfw: boolean; - offset: number; - play_count: number; - preview_url: string; - source: string; - spotlight: boolean; - status: string; - title: string; - title_unicode: string; - track_id: string; - user_id: number; - video: boolean; - bpm: number; - can_be_hyped: boolean; - deleted_at: string; - discussion_enabled: boolean; - discussion_locked: boolean; - is_scoreable: boolean; - last_updated: string; - legacy_thread_url: string; - nominations_summary: { - current: number; - required: number; - }; - ranked: number; - ranked_date: string; - storyboard: boolean; - submitted_date: string; - tags: string; - availability: { - download_disabled: boolean; - more_information: string; - }; - has_favourited: boolean; - beatmaps: { - beatmapset_id: number; - difficulty_rating: number; - id: number; - mode: string; - status: string; - total_length: number; - user_id: number; - version: string; - accuracy: number; - ar: number; - bpm: number; - convert: boolean; - count_circles: number; - count_sliders: number; - count_spinners: number; - cs: number; - deleted_at?: string; - drain: number; - hit_length: number; - is_scoreable: boolean; - last_updated: string; - mode_int: number; - passcount: number; - playcount: number; - ranked: number; - url: string; - checksum: string; - }[]; -} - - -export interface types { - /** - * Return beatmaps list of specified user - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_user_beatmaps_category = await v2.user.beatmaps.category(user, type, object); - * console.log(v2_user_beatmaps_category); - * }; - * - * main(); - * ``` - * @param {number} user id of the user - * @param {string} type ```favourite``` or ```loved``` or ```ranked``` or ```pending``` or ```graveyard``` - * @param {number} object.limit Maximum number of results - * @param {number} object.offset Result offset for pagination - */ - (user: number, type: 'favourite' | 'loved' | 'ranked' | 'pending' | 'graveyard' , object: {limit?: number, offset?: number, }): Promise; -} diff --git a/src/types/v2_user_beatmaps_kudosu.ts b/src/types/v2_user_beatmaps_kudosu.ts deleted file mode 100644 index 700d5598..00000000 --- a/src/types/v2_user_beatmaps_kudosu.ts +++ /dev/null @@ -1,41 +0,0 @@ -export interface response { - id: number; - action: string; - amount: number; - model: string; - created_at: string; - giver: string; - post: { - url: string; - title: string; - }; - details: { - event: string; - }; -} - - -export interface types { - /** - * Return list of kudosu actions - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_user_beatmaps_kudosu = await v2.user.beatmaps.kudosu(user, object); - * console.log(v2_user_beatmaps_kudosu); - * }; - * - * main(); - * ``` - * @param {number} user id of the user - * @param {number} object.limit Maximum number of results - * @param {number} object.offset Result offset for pagination - */ - (user: number, object: {limit?: number, offset?: number, }): Promise; -} diff --git a/src/types/v2_user_beatmaps_most_played.ts b/src/types/v2_user_beatmaps_most_played.ts deleted file mode 100644 index 72eac356..00000000 --- a/src/types/v2_user_beatmaps_most_played.ts +++ /dev/null @@ -1,70 +0,0 @@ -export interface response { - beatmap_id: number; - count: number; - beatmap: { - beatmapset_id: number; - difficulty_rating: number; - id: number; - mode: string; - status: string; - total_length: number; - user_id: number; - version: string; - }; - beatmapset: { - artist: string; - artist_unicode: string; - covers: { - cover: string; - 'cover@2x': string; - card: string; - 'card@2x': string; - list: string; - 'list@2x': string; - slimcover: string; - 'slimcover@2x': string; - }; - creator: string; - favourite_count: number; - hype: string; - id: number; - nsfw: boolean; - offset: number; - play_count: number; - preview_url: string; - source: string; - spotlight: boolean; - status: string; - title: string; - title_unicode: string; - track_id: string; - user_id: number; - video: boolean; - }; -} - - -export interface types { - /** - * Return list of user most played beatmaps - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_user_beatmaps_most_played = await v2.user.beatmaps.most_played(user, object); - * console.log(v2_user_beatmaps_most_played); - * }; - * - * main(); - * ``` - * @param {number} user id of the user - * @param {number} object.limit Maximum number of results - * @param {number} object.offset Result offset for pagination - */ - (user: number, object: {limit?: number, offset?: number, }): Promise; -} diff --git a/src/types/v2_user_details.ts b/src/types/v2_user_details.ts deleted file mode 100644 index 2bfa86cb..00000000 --- a/src/types/v2_user_details.ts +++ /dev/null @@ -1,184 +0,0 @@ -export interface response { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour: string; - profile_hue?: number; - username: string; - cover_url: string; - discord: string; - has_supported: boolean; - interests: string; - join_date: string; - kudosu: { - total: number; - available: number; - }; - location: string; - max_blocks: number; - max_friends: number; - occupation: string; - playmode: string; - playstyle: string; - post_count: number; - profile_order: string[]; - title: string; - title_url: string; - twitter: string; - website: string; - country: { - code: string; - name: string; - }; - cover: { - custom_url: string; - url: string; - id: number; - }; - account_history: []; - active_tournament_banner: string; - badges: { - awarded_at: string; - description: string; - image_url: string; - url: string; - }[]; - beatmap_playcounts_count: number; - comments_count: number; - daily_challenge_user_stats: { - daily_streak_best: number - daily_streak_current: number - last_update?: string - last_weekly_streak?: string - playcount: number - top_10p_placements: number - top_50p_placements: number - user_id: number - weekly_streak_best: number - weekly_streak_current: number - } - favourite_beatmapset_count: number; - follower_count: number; - graveyard_beatmapset_count: number; - groups: { - colour: string; - has_listing: boolean; - has_playmodes: boolean; - id: number; - identifier: string; - is_probationary: boolean; - name: string; - short_name: string; - playmodes: string[]; - }; - guest_beatmapset_count: number; - loved_beatmapset_count: number; - mapping_follower_count: number; - monthly_playcounts: { - start_date: string; - count: number; - }[]; - nominated_beatmapset_count: number; - page: { - html: string; - raw: string; - }; - pending_beatmapset_count: number; - previous_usernames: string[]; - rank_highest: { - rank: number; - updated_at: string; - }; - ranked_beatmapset_count: number; - replays_watched_counts: { - start_date: string; - count: number; - }[]; - scores_best_count: number; - scores_first_count: number; - scores_pinned_count: number; - scores_recent_count: number; - statistics: { - count_100: number; - count_300: number; - count_50: number; - count_miss: number; - level: { - current: number; - progress: number; - }; - global_rank: number; - global_rank_exp: number; - pp: number; - pp_exp: number; - ranked_score: number; - hit_accuracy: number; - play_count: number; - play_time: number; - total_score: number; - total_hits: number; - maximum_combo: number; - replays_watched_by_others: number; - is_ranked: boolean; - grade_counts: { - ss: number; - ssh: number; - s: number; - sh: number; - a: number; - }; - country_rank: number; - rank: { - country: number; - }; - }; - support_level: number; - user_achievements: { - achieved_at: string; - achievement_id: number; - }[]; - rank_history: { - mode: string; - data: number[]; - }; - rankHistory: { - mode: string; - data: number[]; - }; - ranked_and_approved_beatmapset_count: number; - unranked_beatmapset_count: number; -} - - -export interface types { - /** - * Return details about user - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_user_details = await v2.user.details(user, mode, key); - * console.log(v2_user_details); - * }; - * - * main(); - * ``` - * @param {string|number} user id of the user - * @param {string|number} mode ```osu``` or ```fruits``` or ```mania``` or ```taiko``` - * @param {string|number} key ```id``` or ```username``` - */ - (user: string | number, mode?: 'osu' | 'fruits' | 'mania' | 'taiko', key?: 'id' | 'username'): Promise; -} diff --git a/src/types/v2_user_me_details.ts b/src/types/v2_user_me_details.ts deleted file mode 100644 index 717b2bbc..00000000 --- a/src/types/v2_user_me_details.ts +++ /dev/null @@ -1,277 +0,0 @@ -export interface response { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour: string; - username: string; - cover_url: string; - discord: string; - has_supported: boolean; - interests: string; - join_date: string; - kudosu: { - total: number; - available: number; - }; - location: string; - max_blocks: number; - max_friends: number; - occupation: string; - playmode: string; - playstyle: string[]; - post_count: number; - profile_order: string[]; - title: string; - title_url: string; - twitter: string; - website: string; - country: { - code: string; - name: string; - }; - cover: { - custom_url: string; - url: string; - id: string; - }; - is_restricted: boolean; - account_history: []; - active_tournament_banner: string; - badges: []; - beatmap_playcounts_count: number; - comments_count: number; - favourite_beatmapset_count: number; - follower_count: number; - graveyard_beatmapset_count: number; - groups: []; - guest_beatmapset_count: number; - loved_beatmapset_count: number; - mapping_follower_count: number; - monthly_playcounts: { - start_date: string; - count: number; - }[]; - nominated_beatmapset_count: number; - page: { - html: string; - raw: string; - }; - pending_beatmapset_count: number; - previous_usernames: []; - rank_highest: { - rank: number; - updated_at: string; - }; - ranked_beatmapset_count: number; - replays_watched_counts: { - start_date: string; - count: number; - }[]; - scores_best_count: number; - scores_first_count: number; - scores_pinned_count: number; - scores_recent_count: number; - statistics: { - count_100: number; - count_300: number; - count_50: number; - count_miss: number; - level: { - current: number; - progress: number; - }; - global_rank: number; - global_rank_exp: number; - pp: number; - pp_exp: number; - ranked_score: number; - hit_accuracy: number; - play_count: number; - play_time: number; - total_score: number; - total_hits: number; - maximum_combo: number; - replays_watched_by_others: number; - is_ranked: boolean; - grade_counts: { - ss: number; - ssh: number; - s: number; - sh: number; - a: number; - }; - country_rank: number; - rank: { - country: number; - }; - }; - statistics_rulesets: { - osu: { - count_100: number; - count_300: number; - count_50: number; - count_miss: number; - level: { - current: number; - progress: number; - }; - global_rank: number; - global_rank_exp: number; - pp: number; - pp_exp: number; - ranked_score: number; - hit_accuracy: number; - play_count: number; - play_time: number; - total_score: number; - total_hits: number; - maximum_combo: number; - replays_watched_by_others: number; - is_ranked: boolean; - grade_counts: { - ss: number; - ssh: number; - s: number; - sh: number; - a: number; - }; - }; - taiko: { - count_100: number; - count_300: number; - count_50: number; - count_miss: number; - level: { - current: number; - progress: number; - }; - global_rank: string; - global_rank_exp: string; - pp: number; - pp_exp: number; - ranked_score: number; - hit_accuracy: number; - play_count: number; - play_time: number; - total_score: number; - total_hits: number; - maximum_combo: number; - replays_watched_by_others: number; - is_ranked: boolean; - grade_counts: { - ss: number; - ssh: number; - s: number; - sh: number; - a: number; - }; - }; - fruits: { - count_100: number; - count_300: number; - count_50: number; - count_miss: number; - level: { - current: number; - progress: number; - }; - global_rank: string; - global_rank_exp: string; - pp: number; - pp_exp: number; - ranked_score: number; - hit_accuracy: number; - play_count: number; - play_time: number; - total_score: number; - total_hits: number; - maximum_combo: number; - replays_watched_by_others: number; - is_ranked: boolean; - grade_counts: { - ss: number; - ssh: number; - s: number; - sh: number; - a: number; - }; - }; - mania: { - count_100: number; - count_300: number; - count_50: number; - count_miss: number; - level: { - current: number; - progress: number; - }; - global_rank: string; - global_rank_exp: string; - pp: number; - pp_exp: number; - ranked_score: number; - hit_accuracy: number; - play_count: number; - play_time: number; - total_score: number; - total_hits: number; - maximum_combo: number; - replays_watched_by_others: number; - is_ranked: boolean; - grade_counts: { - ss: number; - ssh: number; - s: number; - sh: number; - a: number; - }; - }; - }; - support_level: number; - user_achievements: { - achieved_at: string; - achievement_id: number; - }[]; - rank_history: { - mode: string; - data: number[]; - }; - rankHistory: { - mode: string; - data: number[]; - }; - ranked_and_approved_beatmapset_count: number; - unranked_beatmapset_count: number; -} - - -export interface types { - /** - * Return details about your account - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login_lazer(USERNAME, USER_PASSWORD); - * - * const v2_user_me_details = await v2.user.me.details(mode); - * console.log(v2_user_me_details); - * }; - * - * main(); - * ``` - * @param {string} mode ```osu``` or ```fruits``` or ```mania``` or ```taiko``` - */ - (mode?: 'osu' | 'fruits' | 'mania' | 'taiko' ): Promise; -} diff --git a/src/types/v2_user_me_friends.ts b/src/types/v2_user_me_friends.ts deleted file mode 100644 index 3e34a372..00000000 --- a/src/types/v2_user_me_friends.ts +++ /dev/null @@ -1,89 +0,0 @@ -export interface response { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour: string; - username: string; - country: { - code: string; - name: string; - }; - cover: { - custom_url: string; - url: string; - id: string; - }; - groups: { - colour?: string; - has_listing: boolean; - has_playmodes: boolean; - id: number; - identifier: string; - is_probationary: boolean; - name: string; - short_name: string; - playmodes?: string; - }[]; - statistics: { - count_100: number; - count_300: number; - count_50: number; - count_miss: number; - level: { - current: number; - progress: number; - }; - global_rank: number; - global_rank_exp: string; - pp: number; - pp_exp: number; - ranked_score: number; - hit_accuracy: number; - play_count: number; - play_time: number; - total_score: number; - total_hits: number; - maximum_combo: number; - replays_watched_by_others: number; - is_ranked: boolean; - grade_counts: { - ss: number; - ssh: number; - s: number; - sh: number; - a: number; - }; - }; - support_level: number; -} - - -export interface types { - /** - * Return list of your friedns - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login_lazer(USERNAME, USER_PASSWORD); - * - * const v2_user_me_friends = await v2.user.me.friends(); - * console.log(v2_user_me_friends); - * }; - * - * main(); - * ``` - */ - (): Promise; -} diff --git a/src/types/v2_users_details.ts b/src/types/v2_users_details.ts deleted file mode 100644 index ac7fb4b6..00000000 --- a/src/types/v2_users_details.ts +++ /dev/null @@ -1,181 +0,0 @@ -export interface response { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour: string; - username: string; - country: { - code: string; - name: string; - }; - cover: { - custom_url: string; - url: string; - id: string; - }; - groups: { - colour: string; - has_listing: boolean; - has_playmodes: boolean; - id: number; - identifier: string; - is_probationary: boolean; - name: string; - short_name: string; - playmodes?: string; - }[]; - statistics_rulesets: { - osu: { - count_100: number; - count_300: number; - count_50: number; - count_miss: number; - level: { - current: number; - progress: number; - }; - global_rank: string; - global_rank_exp: number; - pp: number; - pp_exp: number; - ranked_score: number; - hit_accuracy: number; - play_count: number; - play_time: number; - total_score: number; - total_hits: number; - maximum_combo: number; - replays_watched_by_others: number; - is_ranked: boolean; - grade_counts: { - ss: number; - ssh: number; - s: number; - sh: number; - a: number; - }; - }; - taiko: { - count_100: number; - count_300: number; - count_50: number; - count_miss: number; - level: { - current: number; - progress: number; - }; - global_rank: string; - global_rank_exp: string; - pp: number; - pp_exp: number; - ranked_score: number; - hit_accuracy: number; - play_count: number; - play_time: number; - total_score: number; - total_hits: number; - maximum_combo: number; - replays_watched_by_others: number; - is_ranked: boolean; - grade_counts: { - ss: number; - ssh: number; - s: number; - sh: number; - a: number; - }; - }; - fruits: { - count_100: number; - count_300: number; - count_50: number; - count_miss: number; - level: { - current: number; - progress: number; - }; - global_rank: string; - global_rank_exp: string; - pp: number; - pp_exp: number; - ranked_score: number; - hit_accuracy: number; - play_count: number; - play_time: number; - total_score: number; - total_hits: number; - maximum_combo: number; - replays_watched_by_others: number; - is_ranked: boolean; - grade_counts: { - ss: number; - ssh: number; - s: number; - sh: number; - a: number; - }; - }; - mania: { - count_100: number; - count_300: number; - count_50: number; - count_miss: number; - level: { - current: number; - progress: number; - }; - global_rank: string; - global_rank_exp: number; - pp: number; - pp_exp: number; - ranked_score: number; - hit_accuracy: number; - play_count: number; - play_time: number; - total_score: number; - total_hits: number; - maximum_combo: number; - replays_watched_by_others: number; - is_ranked: boolean; - grade_counts: { - ss: number; - ssh: number; - s: number; - sh: number; - a: number; - }; - }; - }; -} - - -export interface types { - /** - * Return list of users - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_users_details = await v2.users.details(ids); - * console.log(v2_users_details); - * }; - * - * main(); - * ``` - * @param {number[]} ids ids of the users (limit 50 users per request) - */ - (ids: number[]): Promise; -} diff --git a/src/types/v2_users_events.ts b/src/types/v2_users_events.ts deleted file mode 100644 index cac7a57b..00000000 --- a/src/types/v2_users_events.ts +++ /dev/null @@ -1,66 +0,0 @@ -export interface response { - events: { - created_at: string; - createdAt: string; - id: number; - type: string; - scoreRank?: string; - rank?: number; - mode?: string; - beatmap: { - title: string; - url: string; - }; - user: { - username: string; - url: string; - previousUsername: string; - }; - achievement: { - icon_url: string; - id: number; - name: string; - grouping: string; - ordering: number; - slug: string; - description: string; - mode: string; - instructions: string; - }; - beatmapset: { - title: string; - url: string; - }; - approval?: string; - }[]; - cursor: { - event_id: number; - }; - cursor_string: string; -} - - -export interface types { - /** - * Return list of events in order of creation time - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_users_events = await v2.users.events(object); - * console.log(v2_users_events); - * }; - * - * main(); - * ``` - * @param {string} object.sort ```id_desc``` or ```id_asc``` - * @param {string} object.cursor_string Parameter for pagination - * @param {string[]} object.type ```achievement``` or ```beatmapPlaycount``` or ```beatmapsetApprove``` or ```beatmapsetDelete``` or ```beatmapsetRevive``` or ```beatmapsetUpdate``` or ```beatmapsetUpload``` or ```rank``` or ```userSupportAgain``` or ```userSupportFirst``` or ```userSupportGift``` or ```usernameChange``` - */ - (object?: {sort?: 'id_desc' | 'id_asc' , cursor_string?: string, type?: Array<'achievement' | 'beatmapPlaycount' | 'beatmapsetApprove' | 'beatmapsetDelete' | 'beatmapsetRevive' | 'beatmapsetUpdate' | 'beatmapsetUpload' | 'rank' | 'userSupportAgain' | 'userSupportFirst' | 'userSupportGift' | 'usernameChange' >, }): Promise; -} diff --git a/src/types/v2_users_groups_list.ts b/src/types/v2_users_groups_list.ts deleted file mode 100644 index b015bd81..00000000 --- a/src/types/v2_users_groups_list.ts +++ /dev/null @@ -1,90 +0,0 @@ -export interface response { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour: string; - username: string; - country: { - code: string; - name: string; - }; - cover: { - custom_url: string; - url: string; - id: string; - }; - groups: { - colour?: string; - has_listing: boolean; - has_playmodes: boolean; - id: number; - identifier: string; - is_probationary: boolean; - name: string; - short_name: string; - playmodes?: string; - }[]; - statistics: { - count_100: number; - count_300: number; - count_50: number; - count_miss: number; - level: { - current: number; - progress: number; - }; - global_rank: number; - global_rank_exp: number; - pp: number; - pp_exp: number; - ranked_score: number; - hit_accuracy: number; - play_count: number; - play_time: number; - total_score: number; - total_hits: number; - maximum_combo: number; - replays_watched_by_others: number; - is_ranked: boolean; - grade_counts: { - ss: number; - ssh: number; - s: number; - sh: number; - a: number; - }; - }; - support_level: number; -} - - -export interface types { - /** - * Return array of users from specified group id - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * - * - * const v2_users_groups_list = await v2.users.groups.list(id); - * console.log(v2_users_groups_list); - * }; - * - * main(); - * ``` - * @param {number} id ```4``` or ```7``` or ```11``` or ```16``` or ```22``` or ```28``` or ```31``` or ```32``` - */ - (id: '4' | '7' | '11' | '16' | '22' | '28' | '31' | '32' ): Promise; -} From 4fafacec0b63bca2e4271ac6205edd28bd69fc6c Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 12:05:00 +0300 Subject: [PATCH 073/259] allow to use different timeout, save ratelimit in cache, so you can access it from anywhere --- package.json | 2 +- types/index.ts | 5 ++++- utility/auth.ts | 22 +++++++++++++++------- utility/request.ts | 33 +++++++++++++++++++++++---------- 4 files changed, 43 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index 0b02d649..64193f09 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.26", + "version": "3.0.0-beta.27", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/types/index.ts b/types/index.ts index e2d2a01c..77ca5205 100644 --- a/types/index.ts +++ b/types/index.ts @@ -5,6 +5,7 @@ export type IDefaultParams = { * Only use it if you want to use user authKey to perform requests on their behave */ authKey?: string; + timeout_ms?: number; }; @@ -38,7 +39,9 @@ export type auth_scopes = ( )[]; -export type auth_params = ({ +export type auth_params = { + timeout?: number, +} & ({ method: 'v2'; client_id: number | string; diff --git a/utility/auth.ts b/utility/auth.ts index 6a69eb5e..8ed0fa46 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -7,6 +7,11 @@ import { auth_params, auth_response, auth_scopes, Modes_names } from '../types/i import { UserAuth } from '../types/user_details'; +export const settings = { + timeout: 60000, +}; + + export const credentials: { method: any; @@ -39,9 +44,12 @@ export const credentials: { scopes: ['public'], }; -export const cache_tokens = { +export const cache = { v1: '', v2: '', + + 'ratelimit-remaining': 0, + 'ratelimit-limit': 0, }; @@ -53,8 +61,8 @@ export const login = async (params: auth_params) => { if (params.method == 'v1') { credentials.api_key = params.api_key; - cache_tokens.v1 = params.api_key; - return cache_tokens.v1; + cache.v1 = params.api_key; + return cache.v1; }; @@ -94,7 +102,7 @@ export const login = async (params: auth_params) => { }; -export const set_v2 = (token: string) => cache_tokens.v2 = token; +export const set_v2 = (token: string) => cache.v2 = token; export const refresh_token = async () => { const refresh = await login(credentials); @@ -120,7 +128,7 @@ const client_login = async (client_id: number | string, client_secret: string, s }); - cache_tokens.v2 = access_token; + cache.v2 = access_token; return { access_token, expires_in }; }; @@ -143,7 +151,7 @@ const lazer_login = async (login: string, password: string) => { }); - cache_tokens.v2 = access_token; + cache.v2 = access_token; return { access_token, expires_in }; }; @@ -175,7 +183,7 @@ const authorize_cli = async (client_id: number | string, client_secret: string, }); - cache_tokens.v2 = access_token; + cache.v2 = access_token; return { access_token, expires_in }; }; diff --git a/utility/request.ts b/utility/request.ts index b75ce867..dc18f35a 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -22,7 +22,6 @@ export interface RequestType { // VALUES -const TIMEOUT_MS = 60000; let total_retries = 0; @@ -38,13 +37,13 @@ export const request: RequestType = (url, { method, headers, data, params = {}, // V1 add credentials if (url.includes('https://osu.ppy.sh/api/') && !url.includes('https://osu.ppy.sh/api/v2')) - params.k = params.v1 || auth.cache_tokens.v1; + params.k = params.v1 || auth.cache.v1; // V2 add credentials if (url.includes('https://osu.ppy.sh/api/v2')) { if (!headers) headers = {}; - headers.Authorization = `Bearer ${addons.authKey || auth.cache_tokens.v2}`; + headers.Authorization = `Bearer ${addons.authKey || auth.cache.v2}`; if (!headers.Accept) headers.Accept = `application/json`; if (!headers['Content-Type']) headers['Content-Type'] = `application/json`; headers['x-api-version'] = addons.apiVersion == '' ? null : addons.apiVersion || '20240130'; @@ -61,6 +60,13 @@ export const request: RequestType = (url, { method, headers, data, params = {}, // console.log({ url: build_url, method, headers, data, generate_query, params }); // debug const req = https.request(build_url, { method, headers }, (response) => { const { location } = response.headers; + + if (response.headers['x-ratelimit-limit']) + auth.cache['ratelimit-limit'] = parseInt(response.headers['x-ratelimit-limit'].toString() || '60'); + if (response.headers['x-ratelimit-remaining']) + auth.cache['ratelimit-remaining'] = parseInt(response.headers['x-ratelimit-remaining'].toString() || '60'); + + if (location) { request(location, { method, headers, data, params, addons }) .then(resolve) @@ -68,7 +74,13 @@ export const request: RequestType = (url, { method, headers, data, params = {}, return; }; - // console.log(response.statusCode, response.statusMessage, response.headers.accept); // debug + // console.log(response.statusCode, response.statusMessage, response.headers.accept, { + // 'ratelimit-limit': auth.cache['ratelimit-limit'], + // 'ratelimit-remaining': auth.cache['ratelimit-remaining'], + // }, { + // url: build_url, method, headers, data, generate_query, params, + // }); // debug + const chunks: any[] = []; // handle response events @@ -107,9 +119,9 @@ export const request: RequestType = (url, { method, headers, data, params = {}, req.on('error', reject); // timeout - req.setTimeout(TIMEOUT_MS, () => { + req.setTimeout(addons.timeout_ms || auth.settings.timeout, () => { req.destroy(); - reject(new Error(`Request to ${build_url} time out after ${TIMEOUT_MS}ms`)); + reject(new Error(`Request to ${build_url} time out after ${addons.timeout_ms || auth.settings.timeout}ms`)); }); @@ -125,15 +137,16 @@ export const request: RequestType = (url, { method, headers, data, params = {}, * @param {string} dest The file destination * @returns {Promise} The response */ -export const download = (url: string, dest: string, { _callback, headers = {}, data, params, callback }: { +export const download = (url: string, dest: string, { _callback, headers = {}, data, params, callback, addons = {} }: { _callback: boolean; headers?: { [key: string]: string }, data?: string; params?: any; + addons?: IDefaultParams; callback?: Function; }): Promise => { return new Promise((resolve, reject) => { - if (url.includes('https://osu.ppy.sh/api/v2')) headers['Authorization'] = `Bearer ${params?.v2 || auth.cache_tokens.v2}`; + if (url.includes('https://osu.ppy.sh/api/v2')) headers['Authorization'] = `Bearer ${params?.v2 || auth.cache.v2}`; if (!headers['accept']) headers['accept'] = `application/octet-stream`; @@ -185,9 +198,9 @@ export const download = (url: string, dest: string, { _callback, headers = {}, d response.pipe(file); }); - req.setTimeout(TIMEOUT_MS, () => { + req.setTimeout(addons.timeout_ms || auth.settings.timeout, () => { req.destroy(); - reject(new Error(`Request to ${url} time out after ${TIMEOUT_MS}ms`)); + reject(new Error(`Request to ${url} time out after ${addons.timeout_ms || auth.settings.timeout}ms`)); }); if (data) { From 0fb0da447db80eb2e9afc51b1fb338ad9d26ea98 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 13:21:12 +0300 Subject: [PATCH 074/259] request switch from throw to { error: new Error } 1/? --- types/index.ts | 10 ++++++- utility/auth.ts | 10 +++++-- utility/request.ts | 70 +++++++++++++++++++++++++++++++--------------- 3 files changed, 65 insertions(+), 25 deletions(-) diff --git a/types/index.ts b/types/index.ts index 77ca5205..876f0b8f 100644 --- a/types/index.ts +++ b/types/index.ts @@ -6,6 +6,11 @@ export type IDefaultParams = { */ authKey?: string; timeout_ms?: number; + + /** + * If request returns `authentication: 'basic', it wont try to refresh session + */ + ignoreSessionRefresh?: boolean }; @@ -75,4 +80,7 @@ export type auth_response = { expires_in: number; }; -export type IBeatmapPackType = 'standard' | 'featured' | 'tournament' | 'loved' | 'chart' | 'theme' | 'artist'; \ No newline at end of file +export type IBeatmapPackType = 'standard' | 'featured' | 'tournament' | 'loved' | 'chart' | 'theme' | 'artist'; + + +export type IError = { error: Error }; \ No newline at end of file diff --git a/utility/auth.ts b/utility/auth.ts index 8ed0fa46..31d9de19 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -234,7 +234,10 @@ export const authorize = async ({ code, mode, client_id, client_secret, redirect }); - const user = await request(`https://osu.ppy.sh/api/v2/me/${mode}`, { method: 'GET', params: { v2: access_token, nor: true } }); + const user = await request(`https://osu.ppy.sh/api/v2/me/${mode}`, { + method: 'GET', + addons: { authKey: access_token, ignoreSessionRefresh: true } + }); user.access_token = access_token; user.refresh_token = refresh_token; user.expires_in = expires_in; @@ -268,7 +271,10 @@ export const refresh_session = async ({ refresh_token, mode, client_id, client_s }); - const user = await request(`https://osu.ppy.sh/api/v2/me/${mode}`, { method: 'GET', params: { v2: access_token, nor: true } }); + const user = await request(`https://osu.ppy.sh/api/v2/me/${mode}`, { + method: 'GET', + addons: { authKey: access_token, ignoreSessionRefresh: true } + }); user.access_token = access_token; user.refresh_token = refresh_token_new; user.expires_in = expires_in; diff --git a/utility/request.ts b/utility/request.ts index dc18f35a..e364e4df 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -6,7 +6,7 @@ import fs from 'fs'; // CREDENTIALS import * as auth from "./auth"; -import { IDefaultParams } from '../types'; +import { IDefaultParams, IError } from '../types'; // TYPES @@ -26,18 +26,20 @@ let total_retries = 0; -export const request: RequestType = (url, { method, headers, data, params = {}, addons = {} }): Promise => new Promise((resolve, reject) => { +export const request: RequestType = (url, { method, headers, data, params = {}, addons = {} }): Promise => new Promise((resolve, reject) => { // check required args - if (url == null) - throw new Error('URL not specified'); + if (url == null) { + return resolve({ error: new Error('URL not specified'), }); + }; - if (method == null) - throw new Error('Method not specified'); + if (method == null) { + return resolve({ error: new Error('Method not specified'), }); + }; // V1 add credentials if (url.includes('https://osu.ppy.sh/api/') && !url.includes('https://osu.ppy.sh/api/v2')) - params.k = params.v1 || auth.cache.v1; + params.k = addons.authKey || auth.cache.v1; // V2 add credentials if (url.includes('https://osu.ppy.sh/api/v2')) { @@ -91,21 +93,40 @@ export const request: RequestType = (url, { method, headers, data, params = {}, if (/^application\/json/.test(response.headers['content-type'])) { try { const parse = JSON.parse(data); - if (parse.authentication === 'basic' && total_retries < 3 && params.nor != true) { - const refresh = await auth.refresh_token(); - if (refresh == null) return resolve({ authentication: 'basic' }); + if (parse.authentication === 'basic' && total_retries < 3 && addons.ignoreSessionRefresh != true) { total_retries++; + const refresh = await auth.refresh_token(); + if (refresh == null) { + return resolve({ error: 'Cannot refresh session, double check your credentials (or report to package author)' }); + }; + + const retry_request = await request(url, { method, headers, data, params }); return resolve(retry_request); }; + if ('error' in parse) { + if (parse.error === null) { + return resolve({ error: new Error(`osu returned empty error, double check your parameters`) }); + }; + + + return resolve({ error: new Error(parse.error) }); + }; + + + if (parse.authentication === 'basic') { + return resolve({ error: new Error('Unauthorized (double check credentials)') }); + }; + + total_retries = 0; return resolve(parse); } catch (error) { - reject(error); + return resolve({ error: error }); }; }; @@ -115,13 +136,15 @@ export const request: RequestType = (url, { method, headers, data, params = {}, }); - // throw error - req.on('error', reject); + // send error + req.on('error', (error) => { + resolve({ error: error }); + }); // timeout req.setTimeout(addons.timeout_ms || auth.settings.timeout, () => { req.destroy(); - reject(new Error(`Request to ${build_url} time out after ${addons.timeout_ms || auth.settings.timeout}ms`)); + resolve({ error: new Error(`Request to ${build_url} time out after ${addons.timeout_ms || auth.settings.timeout}ms`) }); }); @@ -144,7 +167,7 @@ export const download = (url: string, dest: string, { _callback, headers = {}, d params?: any; addons?: IDefaultParams; callback?: Function; -}): Promise => { +}): Promise => { return new Promise((resolve, reject) => { if (url.includes('https://osu.ppy.sh/api/v2')) headers['Authorization'] = `Bearer ${params?.v2 || auth.cache.v2}`; @@ -161,15 +184,16 @@ export const download = (url: string, dest: string, { _callback, headers = {}, d if (location) { download(location, dest, { _callback, headers, data, params, callback }) .then(resolve) - .catch(reject); + .catch(error => ({ error: error })); return; - } + }; + const file = fs.createWriteStream(dest, { encoding: 'utf8' }); - file.on('error', err => { + file.on('error', error => { fs.unlinkSync(dest); - reject(err); + resolve({ error: error }); }); file.on('finish', () => { @@ -177,10 +201,12 @@ export const download = (url: string, dest: string, { _callback, headers = {}, d resolve(dest); }); + if (response.statusCode === 404) { - resolve('file unavailable'); + resolve({ error: new Error('file unavailable') }); return; - } + }; + if (_callback == true && callback !== undefined) { const totalLength = parseInt(response.headers['content-length']); @@ -200,7 +226,7 @@ export const download = (url: string, dest: string, { _callback, headers = {}, d req.setTimeout(addons.timeout_ms || auth.settings.timeout, () => { req.destroy(); - reject(new Error(`Request to ${url} time out after ${addons.timeout_ms || auth.settings.timeout}ms`)); + resolve({ error: new Error(`Request to ${build_url} time out after ${addons.timeout_ms || auth.settings.timeout}ms`) }); }); if (data) { From 39b709f536c88f73e13cec074d41a7699dfc6b46 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 13:23:05 +0300 Subject: [PATCH 075/259] add types to `assets_backgrounds` --- api/v2/assets_backgrounds.ts | 59 ++++++++++++++++++++++------------ types/v2/assets_backgrounds.ts | 39 ++++++++++++++++++++++ 2 files changed, 77 insertions(+), 21 deletions(-) create mode 100644 types/v2/assets_backgrounds.ts diff --git a/api/v2/assets_backgrounds.ts b/api/v2/assets_backgrounds.ts index 7bcb2a33..c6eb8753 100644 --- a/api/v2/assets_backgrounds.ts +++ b/api/v2/assets_backgrounds.ts @@ -1,37 +1,54 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { BeatmapsetBackground, SeasonalBackgrounds } from "../../types/v2/assets_backgrounds"; import { request } from "../../utility/request"; type params = ({ type: 'seasonal'; +} | { + type: 'beatmapset', + set_id: number; }); type Response = - T extends 'site' - ? any - : T extends 'beatmaps' - ? any - : never; - - -const name = async (params: T, addons?: IDefaultParams): Promise> => { - let url = 'https://osu.ppy.sh/api/v2'; - - switch (params.type) { - case 'seasonal': - url += `/seasonal-backgrounds`; - - break; + T extends 'seasonal' + ? Promise + : T extends 'beatmapset' + ? BeatmapsetBackground & IError + : IError; + + +const name = (params: T, addons?: IDefaultParams): Response => { + if (params.type == 'seasonal') { + return request(`https://osu.ppy.sh/api/v2/seasonal-backgrounds`, { + method: 'GET', + addons, + }) as Response; }; - const data = await request(url, { - method: 'GET', - addons, - }); + if (params.type == 'beatmapset') { + if (params.set_id == null) { + return { error: new Error('Specify beatmapset id') } as any; + }; + + + return { + cover: `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/cover.jpg?1707077934`, + "cover@2x": `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/cover@2x.jpg?1707077934`, + card: `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/card.jpg?1707077934`, + "card@2x": `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/card@2x.jpg?1707077934`, + list: `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/list.jpg?1707077934`, + "list@2x": `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/list@2x.jpg?1707077934`, + slimcover: `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/slimcover.jpg?1707077934`, + "slimcover@2x": `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/slimcover@2x.jpg?1707077934`, + raw: `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/raw.jpg`, + fullsize: `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/fullsize.jpg`, + } as Response; + }; - return data; + return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; }; diff --git a/types/v2/assets_backgrounds.ts b/types/v2/assets_backgrounds.ts new file mode 100644 index 00000000..3e089f2d --- /dev/null +++ b/types/v2/assets_backgrounds.ts @@ -0,0 +1,39 @@ +export interface SeasonalBackgrounds { + ends_at: string + backgrounds: Background[] +} + +export interface BeatmapsetBackground { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string + raw: string + fullsize: string +} + + +export interface Background { + url: string + user: User +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour: any + username: string +} From 931c1175012b8d2cc72da663a88502ec66d55712 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 13:34:41 +0300 Subject: [PATCH 076/259] assets_dataFiles - errors handling & types --- api/v2/assets_backgrounds.ts | 7 ++----- api/v2/assets_dataFiles.ts | 14 ++++++++------ routes/v2.ts | 4 ++-- utility/request.ts | 4 ++-- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/api/v2/assets_backgrounds.ts b/api/v2/assets_backgrounds.ts index c6eb8753..54cad813 100644 --- a/api/v2/assets_backgrounds.ts +++ b/api/v2/assets_backgrounds.ts @@ -18,7 +18,7 @@ type Response = : IError; -const name = (params: T, addons?: IDefaultParams): Response => { +export const assets_backgrounds = (params: T, addons?: IDefaultParams): Response => { if (params.type == 'seasonal') { return request(`https://osu.ppy.sh/api/v2/seasonal-backgrounds`, { method: 'GET', @@ -49,7 +49,4 @@ const name = (params: T, addons?: IDefaultParams): Response; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/api/v2/assets_dataFiles.ts b/api/v2/assets_dataFiles.ts index 9c6b6f30..e620dfd3 100644 --- a/api/v2/assets_dataFiles.ts +++ b/api/v2/assets_dataFiles.ts @@ -1,12 +1,17 @@ +import { IError } from "../../types"; import { request } from "../../utility/request"; +type Response = { files: string[] } | IError; -const name = async () => { + +export const assets_dataFiles = async (): Promise => { const data = await request(`https://data.ppy.sh/`, { method: 'GET', }); + if (data.error) return data.error; + const array = data.split('\n') .filter((r: string) => r.includes(` Date: Fri, 26 Apr 2024 13:41:56 +0300 Subject: [PATCH 077/259] beatmaps_events_list - errors handling & types --- ...eatmap_events_list.ts => beatmaps_events_list.ts} | 7 ++----- routes/v2.ts | 4 ++-- types/v2/beatmaps_events.ts | 8 ++++---- utility/request.ts | 12 ++++++------ 4 files changed, 14 insertions(+), 17 deletions(-) rename api/v2/{beatmap_events_list.ts => beatmaps_events_list.ts} (90%) diff --git a/api/v2/beatmap_events_list.ts b/api/v2/beatmaps_events_list.ts similarity index 90% rename from api/v2/beatmap_events_list.ts rename to api/v2/beatmaps_events_list.ts index b4b911ad..5619914e 100644 --- a/api/v2/beatmap_events_list.ts +++ b/api/v2/beatmaps_events_list.ts @@ -4,7 +4,7 @@ import { request } from "../../utility/request"; -const name = async (obj: { +export const beatmaps_events_list = async (obj: { user: string | number, types: (beatmap_events_types)[]; min_date: string; @@ -20,7 +20,4 @@ const name = async (obj: { }); return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 3030bf91..1c1f0f2f 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -1,4 +1,4 @@ -import beatmap_events_list from "../api/v2/beatmap_events_list"; +import { beatmaps_events_list } from "../api/v2/beatmaps_events_list"; import beatmaps_lookup from "../api/v2/beatmaps_lookup"; import beatmaps_details from "../api/v2/beatmaps_details"; import beatmaps_download from "../api/v2/beatmaps_download"; @@ -19,7 +19,7 @@ export const beatmaps = { lookup: beatmaps_lookup, details: beatmaps_details, events: { - list: beatmap_events_list, + list: beatmaps_events_list, }, download: beatmaps_download, discussions: { diff --git a/types/v2/beatmaps_events.ts b/types/v2/beatmaps_events.ts index 57e57c5f..ed94d6c8 100644 --- a/types/v2/beatmaps_events.ts +++ b/types/v2/beatmaps_events.ts @@ -50,7 +50,7 @@ export interface Beatmapset { status: string title: string title_unicode: string - track_id: any + track_id?: number user_id: number video: boolean user: User @@ -91,11 +91,11 @@ export interface User { export interface Discussion { id: number beatmapset_id: number - beatmap_id: number + beatmap_id?: number user_id: number deleted_by_id: any message_type: string - parent_id?: number + parent_id?: any timestamp?: number resolved: boolean can_be_resolved: boolean @@ -151,5 +151,5 @@ export interface Group { is_probationary: boolean name: string short_name: string - playmodes: string[] + playmodes?: string[] } diff --git a/utility/request.ts b/utility/request.ts index 6f528f62..1c213e37 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -76,12 +76,12 @@ export const request: RequestType = (url, { method, headers, data, params = {}, return; }; - // console.log(response.statusCode, response.statusMessage, response.headers.accept, { - // 'ratelimit-limit': auth.cache['ratelimit-limit'], - // 'ratelimit-remaining': auth.cache['ratelimit-remaining'], - // }, { - // url: build_url, method, headers, data, generate_query, params, - // }); // debug + console.log(response.statusCode, response.statusMessage, response.headers.accept, { + 'ratelimit-limit': auth.cache['ratelimit-limit'], + 'ratelimit-remaining': auth.cache['ratelimit-remaining'], + }, { + url: build_url, method, headers, data, generate_query, params, + }); // debug const chunks: any[] = []; From 721bab3c0ce72ecc107a0e86c80c7507b5b39c4d Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 13:45:50 +0300 Subject: [PATCH 078/259] beatmap_packs_details - errors handling & types --- api/v2/assets_backgrounds.ts | 16 ++++++++-------- api/v2/beatmap_packs_details.ts | 15 +++++++++------ api/v2/beatmaps_events_list.ts | 4 ++-- routes/v2.ts | 2 +- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/api/v2/assets_backgrounds.ts b/api/v2/assets_backgrounds.ts index 54cad813..cadd7e4e 100644 --- a/api/v2/assets_backgrounds.ts +++ b/api/v2/assets_backgrounds.ts @@ -34,14 +34,14 @@ export const assets_backgrounds = (params: T, addons?: IDefaul return { - cover: `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/cover.jpg?1707077934`, - "cover@2x": `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/cover@2x.jpg?1707077934`, - card: `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/card.jpg?1707077934`, - "card@2x": `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/card@2x.jpg?1707077934`, - list: `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/list.jpg?1707077934`, - "list@2x": `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/list@2x.jpg?1707077934`, - slimcover: `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/slimcover.jpg?1707077934`, - "slimcover@2x": `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/slimcover@2x.jpg?1707077934`, + cover: `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/cover.jpg`, + "cover@2x": `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/cover@2x.jpg`, + card: `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/card.jpg`, + "card@2x": `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/card@2x.jpg`, + list: `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/list.jpg`, + "list@2x": `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/list@2x.jpg`, + slimcover: `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/slimcover.jpg`, + "slimcover@2x": `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/slimcover@2x.jpg`, raw: `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/raw.jpg`, fullsize: `https://assets.ppy.sh/beatmaps/${params.set_id}/covers/fullsize.jpg`, } as Response; diff --git a/api/v2/beatmap_packs_details.ts b/api/v2/beatmap_packs_details.ts index 0e6ea26d..3d1d0762 100644 --- a/api/v2/beatmap_packs_details.ts +++ b/api/v2/beatmap_packs_details.ts @@ -1,17 +1,20 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; import { BeatmapsPacksDetailsResponse } from "../../types/v2/beatmaps_packs_details"; import { request } from "../../utility/request"; -const name = async (pack_tag: string, addons?: IDefaultParams): Promise => { +export const beatmap_packs_details = async (pack_tag: string, addons?: IDefaultParams): Promise => { + if (pack_tag == null) { + return { error: new Error('Specify beatmap pack tag') }; + }; + + const data = await request(`https://osu.ppy.sh/api/v2/beatmaps/packs/${pack_tag}`, { method: 'GET', addons, }); - return data; -}; - -export default name; \ No newline at end of file + return data; +}; \ No newline at end of file diff --git a/api/v2/beatmaps_events_list.ts b/api/v2/beatmaps_events_list.ts index 5619914e..62ba558b 100644 --- a/api/v2/beatmaps_events_list.ts +++ b/api/v2/beatmaps_events_list.ts @@ -1,5 +1,5 @@ import { BeatmapsEvents } from "../../types/v2/beatmaps_events"; -import { IDefaultParams, beatmap_events_types } from "../../types"; +import { IDefaultParams, IError, beatmap_events_types } from "../../types"; import { request } from "../../utility/request"; @@ -9,7 +9,7 @@ export const beatmaps_events_list = async (obj: { types: (beatmap_events_types)[]; min_date: string; max_date: string; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { let url = 'https://osu.ppy.sh/api/v2/beatmapsets/events'; diff --git a/routes/v2.ts b/routes/v2.ts index 1c1f0f2f..a015462a 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -3,7 +3,7 @@ import beatmaps_lookup from "../api/v2/beatmaps_lookup"; import beatmaps_details from "../api/v2/beatmaps_details"; import beatmaps_download from "../api/v2/beatmaps_download"; import beatmap_packs_list from "../api/v2/beatmap_packs_list"; -import beatmap_packs_details from "../api/v2/beatmap_packs_details"; +import { beatmap_packs_details } from "../api/v2/beatmap_packs_details"; import beatmaps_discussions_list from "../api/v2/beatmaps_discussions_list"; import beatmaps_discussions_posts from "../api/v2/beatmaps_discussions_posts"; import beatmaps_discussions_votes from "../api/v2/beatmaps_discussions_votes"; From ca2a370ee2bef7666dd2f3ebd5b8a1c2831424c7 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 13:49:39 +0300 Subject: [PATCH 079/259] beatmaps_packs_list - errors handling & types --- ...ap_packs_details.ts => beatmaps_packs_details.ts} | 0 ...{beatmap_packs_list.ts => beatmaps_packs_list.ts} | 12 +++++------- routes/v2.ts | 6 +++--- types/v2/beatmaps_packs_list.ts | 4 ++-- 4 files changed, 10 insertions(+), 12 deletions(-) rename api/v2/{beatmap_packs_details.ts => beatmaps_packs_details.ts} (100%) rename api/v2/{beatmap_packs_list.ts => beatmaps_packs_list.ts} (61%) diff --git a/api/v2/beatmap_packs_details.ts b/api/v2/beatmaps_packs_details.ts similarity index 100% rename from api/v2/beatmap_packs_details.ts rename to api/v2/beatmaps_packs_details.ts diff --git a/api/v2/beatmap_packs_list.ts b/api/v2/beatmaps_packs_list.ts similarity index 61% rename from api/v2/beatmap_packs_list.ts rename to api/v2/beatmaps_packs_list.ts index 5564c8cc..454363e2 100644 --- a/api/v2/beatmap_packs_list.ts +++ b/api/v2/beatmaps_packs_list.ts @@ -1,21 +1,19 @@ -import { IBeatmapPackType, IDefaultParams } from "../../types"; +import { IBeatmapPackType, IDefaultParams, IError } from "../../types"; import { BeatmapsPacksListResponse } from "../../types/v2/beatmaps_packs_list"; import { request } from "../../utility/request"; -const name = async (params: { +export const beatmaps_packs_list = async (params: { type: IBeatmapPackType; cursor_string?: string; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/beatmaps/packs`, { method: 'GET', params, addons, }); - return data; -}; - -export default name; \ No newline at end of file + return data; +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index a015462a..30025795 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -2,8 +2,8 @@ import { beatmaps_events_list } from "../api/v2/beatmaps_events_list"; import beatmaps_lookup from "../api/v2/beatmaps_lookup"; import beatmaps_details from "../api/v2/beatmaps_details"; import beatmaps_download from "../api/v2/beatmaps_download"; -import beatmap_packs_list from "../api/v2/beatmap_packs_list"; -import { beatmap_packs_details } from "../api/v2/beatmap_packs_details"; +import { beatmaps_packs_list } from "../api/v2/beatmaps_packs_list"; +import { beatmap_packs_details } from "../api/v2/beatmaps_packs_details"; import beatmaps_discussions_list from "../api/v2/beatmaps_discussions_list"; import beatmaps_discussions_posts from "../api/v2/beatmaps_discussions_posts"; import beatmaps_discussions_votes from "../api/v2/beatmaps_discussions_votes"; @@ -13,7 +13,7 @@ import beatmaps_actions from "../api/v2/beatmaps_actions"; export const beatmaps = { packs: { - list: beatmap_packs_list, + list: beatmaps_packs_list, details: beatmap_packs_details, }, lookup: beatmaps_lookup, diff --git a/types/v2/beatmaps_packs_list.ts b/types/v2/beatmaps_packs_list.ts index 5b33c6f9..0b324421 100644 --- a/types/v2/beatmaps_packs_list.ts +++ b/types/v2/beatmaps_packs_list.ts @@ -9,11 +9,11 @@ export interface BeatmapPack { date: string name: string no_diff_reduction: boolean - ruleset_id: any + ruleset_id?: number tag: string url: string } export interface Cursor { pack_id: number -} +} \ No newline at end of file From d8781d65e0759d54f01d2312964bc5cd25bc658b Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 13:58:29 +0300 Subject: [PATCH 080/259] beatmaps_details - errors handling & types --- api/v2/assets_backgrounds.ts | 4 ++-- api/v2/beatmaps_actions.ts | 2 +- api/v2/beatmaps_details.ts | 22 ++++++++++++++-------- routes/v2.ts | 2 +- types/v2/beamaps_details_set.ts | 2 +- 5 files changed, 19 insertions(+), 13 deletions(-) diff --git a/api/v2/assets_backgrounds.ts b/api/v2/assets_backgrounds.ts index cadd7e4e..bb3dc2a6 100644 --- a/api/v2/assets_backgrounds.ts +++ b/api/v2/assets_backgrounds.ts @@ -12,9 +12,9 @@ type params = ({ type Response = T extends 'seasonal' - ? Promise + ? Promise : T extends 'beatmapset' - ? BeatmapsetBackground & IError + ? BeatmapsetBackground | IError : IError; diff --git a/api/v2/beatmaps_actions.ts b/api/v2/beatmaps_actions.ts index 607e164c..7b36ccc5 100644 --- a/api/v2/beatmaps_actions.ts +++ b/api/v2/beatmaps_actions.ts @@ -18,7 +18,7 @@ type Response = ? any : never; - +// FIX const name = async (params: T, addons?: IDefaultParams): Promise | { error: string }> => { return { error: 'TEMPORARY NOT WORKING, have no clue why', diff --git a/api/v2/beatmaps_details.ts b/api/v2/beatmaps_details.ts index 86a1bd2e..3fb57084 100644 --- a/api/v2/beatmaps_details.ts +++ b/api/v2/beatmaps_details.ts @@ -1,4 +1,4 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; import { BeamapsDetailsDifficulty } from "../../types/v2/beamaps_details_difficulty"; import { BeamapsDetailsSet } from "../../types/v2/beamaps_details_set"; import { request } from "../../utility/request"; @@ -15,12 +15,17 @@ type params = ({ type Response = T extends 'difficulty' - ? BeamapsDetailsDifficulty + ? BeamapsDetailsDifficulty | IError : T extends 'set' - ? BeamapsDetailsSet : never; + ? BeamapsDetailsSet | IError : IError; + + +export const beatmaps_details = async (params: T, addons?: IDefaultParams): Promise> => { + if (params.id == null) { + return { error: new Error(`Specify ${params.type} id`) } as Response; + }; -const name = async (params: T, addons?: IDefaultParams): Promise> => { const object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; let method = 'GET'; @@ -34,6 +39,9 @@ const name = async (params: T, addons?: IDefaultParams): Promi case 'set': url += `/beatmapsets/${params.id}`; break; + + default: + return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; }; @@ -43,8 +51,6 @@ const name = async (params: T, addons?: IDefaultParams): Promi addons }); - return data as Response; -}; - -export default name; \ No newline at end of file + return data as Response; +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 30025795..44f853ba 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -1,6 +1,6 @@ import { beatmaps_events_list } from "../api/v2/beatmaps_events_list"; import beatmaps_lookup from "../api/v2/beatmaps_lookup"; -import beatmaps_details from "../api/v2/beatmaps_details"; +import { beatmaps_details } from "../api/v2/beatmaps_details"; import beatmaps_download from "../api/v2/beatmaps_download"; import { beatmaps_packs_list } from "../api/v2/beatmaps_packs_list"; import { beatmap_packs_details } from "../api/v2/beatmaps_packs_details"; diff --git a/types/v2/beamaps_details_set.ts b/types/v2/beamaps_details_set.ts index 312d7446..ecf909fb 100644 --- a/types/v2/beamaps_details_set.ts +++ b/types/v2/beamaps_details_set.ts @@ -173,7 +173,7 @@ export interface RecentFavourite { is_supporter: boolean last_visit?: string pm_friends_only: boolean - profile_colour: any + profile_colour?: string username: string } From db3056611d4f5b8194aacc27e91bfe81f6a056a1 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 14:06:43 +0300 Subject: [PATCH 081/259] beatmaps_discussions_list - errors handling & types --- api/v2/beatmaps_discussions_list.ts | 11 +++---- routes/v2.ts | 2 +- types/v2/beatmaps_discussions_list.ts | 43 +++++++++++++++++++++++---- 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/api/v2/beatmaps_discussions_list.ts b/api/v2/beatmaps_discussions_list.ts index f1894d66..da8c0bda 100644 --- a/api/v2/beatmaps_discussions_list.ts +++ b/api/v2/beatmaps_discussions_list.ts @@ -1,10 +1,10 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; import { BeatmapsDiscussionsListResponse } from "../../types/v2/beatmaps_discussions_list"; import { request } from "../../utility/request"; -const name = async (params: { +export const beatmaps_discussions_list = async (params: { only_unresolved?: boolean; user?: number; beatmap_id?: number; @@ -14,7 +14,7 @@ const name = async (params: { limit?: number; sort?: 'id_desc' | 'id_asc'; cursor_string?: string; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/beatmapsets/discussions`, { method: 'GET', params, @@ -22,7 +22,4 @@ const name = async (params: { }); return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 44f853ba..0e93f576 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -4,7 +4,7 @@ import { beatmaps_details } from "../api/v2/beatmaps_details"; import beatmaps_download from "../api/v2/beatmaps_download"; import { beatmaps_packs_list } from "../api/v2/beatmaps_packs_list"; import { beatmap_packs_details } from "../api/v2/beatmaps_packs_details"; -import beatmaps_discussions_list from "../api/v2/beatmaps_discussions_list"; +import { beatmaps_discussions_list } from "../api/v2/beatmaps_discussions_list"; import beatmaps_discussions_posts from "../api/v2/beatmaps_discussions_posts"; import beatmaps_discussions_votes from "../api/v2/beatmaps_discussions_votes"; diff --git a/types/v2/beatmaps_discussions_list.ts b/types/v2/beatmaps_discussions_list.ts index 0e4b075e..427d6903 100644 --- a/types/v2/beatmaps_discussions_list.ts +++ b/types/v2/beatmaps_discussions_list.ts @@ -2,11 +2,11 @@ export interface BeatmapsDiscussionsListResponse { beatmaps: Beatmap[] beatmapsets: Beatmapset[] discussions: Discussion[] - included_discussions: any[] + included_discussions: IncludedDiscussion[] reviews_config: ReviewsConfig users: User[] - cursor?: Cursor - cursor_string?: string + cursor: Cursor + cursor_string: string } export interface Beatmap { @@ -56,7 +56,7 @@ export interface Beatmapset { status: string title: string title_unicode: string - track_id: any + track_id?: number user_id: number video: boolean bpm: number @@ -69,7 +69,7 @@ export interface Beatmapset { legacy_thread_url: string nominations_summary: NominationsSummary ranked: number - ranked_date?: string + ranked_date: any storyboard: boolean submitted_date: string tags: string @@ -135,6 +135,39 @@ export interface StartingPost { user_id: number } +export interface IncludedDiscussion { + id: number + beatmapset_id: number + beatmap_id?: number + user_id: number + deleted_by_id: any + message_type: string + parent_id: number + timestamp?: number + resolved: boolean + can_be_resolved: boolean + can_grant_kudosu: boolean + created_at: string + updated_at: string + deleted_at: any + last_post_at: string + kudosu_denied: boolean + starting_post: StartingPost2 +} + +export interface StartingPost2 { + beatmapset_discussion_id: number + created_at: string + deleted_at: any + deleted_by_id: any + id: number + last_editor_id: any + message: string + system: boolean + updated_at: string + user_id: number +} + export interface ReviewsConfig { max_blocks: number } From b289356524bf41d816f213c011b695014fca6872 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 14:08:46 +0300 Subject: [PATCH 082/259] beatmaps_discussions_posts - errors handling & types --- api/v2/beatmaps_discussions_posts.ts | 11 ++++------- routes/v2.ts | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/api/v2/beatmaps_discussions_posts.ts b/api/v2/beatmaps_discussions_posts.ts index a1e0fefe..72be60a3 100644 --- a/api/v2/beatmaps_discussions_posts.ts +++ b/api/v2/beatmaps_discussions_posts.ts @@ -1,10 +1,10 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; import { BeatmapsDiscussionsListResponse } from "../../types/v2/beatmaps_discussions_list"; import { request } from "../../utility/request"; -const name = async (params: { +export const beatmaps_discussions_posts = async (params: { discussion_id?: number; sort?: 'id_desc' | 'id_asc'; types?: ('first' | 'reply' | 'system')[]; @@ -12,7 +12,7 @@ const name = async (params: { limit?: number; cursor_string?: string; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { if (params.discussion_id) { // @ts-ignore params.beatmapset_discussion_id = params.discussion_id; @@ -33,7 +33,4 @@ const name = async (params: { }); return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 0e93f576..9f61c2ce 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -5,7 +5,7 @@ import beatmaps_download from "../api/v2/beatmaps_download"; import { beatmaps_packs_list } from "../api/v2/beatmaps_packs_list"; import { beatmap_packs_details } from "../api/v2/beatmaps_packs_details"; import { beatmaps_discussions_list } from "../api/v2/beatmaps_discussions_list"; -import beatmaps_discussions_posts from "../api/v2/beatmaps_discussions_posts"; +import { beatmaps_discussions_posts } from "../api/v2/beatmaps_discussions_posts"; import beatmaps_discussions_votes from "../api/v2/beatmaps_discussions_votes"; import beatmaps_actions from "../api/v2/beatmaps_actions"; From b3a1d7a080935efd82dcdef7b7b3a2849ab6fbf6 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 14:48:04 +0300 Subject: [PATCH 083/259] beatmaps_discussions_votes - errors handling & types --- api/v2/beatmaps_discussions_votes.ts | 11 +- routes/v2.ts | 2 +- types/v2/beatmaps_discussions_list.ts | 166 +++----------------------- 3 files changed, 19 insertions(+), 160 deletions(-) diff --git a/api/v2/beatmaps_discussions_votes.ts b/api/v2/beatmaps_discussions_votes.ts index c8ed1f9c..560d2cac 100644 --- a/api/v2/beatmaps_discussions_votes.ts +++ b/api/v2/beatmaps_discussions_votes.ts @@ -1,10 +1,10 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; import { BeatmapsDiscussionsListResponse } from "../../types/v2/beatmaps_discussions_list"; import { request } from "../../utility/request"; -const name = async (params: { +export const beatmaps_discussions_votes = async (params: { discussion_id?: number; sort?: 'id_desc' | 'id_asc'; score?: '1' | '-1'; @@ -14,7 +14,7 @@ const name = async (params: { limit?: number; cursor_string?: string; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { if (params.discussion_id) { // @ts-ignore params.beatmapset_discussion_id = params.discussion_id; @@ -29,7 +29,4 @@ const name = async (params: { }); return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 9f61c2ce..0e1e09bf 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -6,7 +6,7 @@ import { beatmaps_packs_list } from "../api/v2/beatmaps_packs_list"; import { beatmap_packs_details } from "../api/v2/beatmaps_packs_details"; import { beatmaps_discussions_list } from "../api/v2/beatmaps_discussions_list"; import { beatmaps_discussions_posts } from "../api/v2/beatmaps_discussions_posts"; -import beatmaps_discussions_votes from "../api/v2/beatmaps_discussions_votes"; +import { beatmaps_discussions_votes } from "../api/v2/beatmaps_discussions_votes"; import beatmaps_actions from "../api/v2/beatmaps_actions"; diff --git a/types/v2/beatmaps_discussions_list.ts b/types/v2/beatmaps_discussions_list.ts index 427d6903..b71ba45c 100644 --- a/types/v2/beatmaps_discussions_list.ts +++ b/types/v2/beatmaps_discussions_list.ts @@ -1,105 +1,9 @@ export interface BeatmapsDiscussionsListResponse { - beatmaps: Beatmap[] - beatmapsets: Beatmapset[] discussions: Discussion[] - included_discussions: IncludedDiscussion[] - reviews_config: ReviewsConfig users: User[] - cursor: Cursor - cursor_string: string -} - -export interface Beatmap { - beatmapset_id: number - difficulty_rating: number - id: number - mode: string - status: string - total_length: number - user_id: number - version: string - accuracy: number - ar: number - bpm: number - convert: boolean - count_circles: number - count_sliders: number - count_spinners: number - cs: number - deleted_at?: string - drain: number - hit_length: number - is_scoreable: boolean - last_updated: string - mode_int: number - passcount: number - playcount: number - ranked: number - url: string - checksum?: string -} - -export interface Beatmapset { - artist: string - artist_unicode: string - covers: Covers - creator: string - favourite_count: number - hype?: Hype - id: number - nsfw: boolean - offset: number - play_count: number - preview_url: string - source: string - spotlight: boolean - status: string - title: string - title_unicode: string - track_id?: number - user_id: number - video: boolean - bpm: number - can_be_hyped: boolean - deleted_at: any - discussion_enabled: boolean - discussion_locked: boolean - is_scoreable: boolean - last_updated: string - legacy_thread_url: string - nominations_summary: NominationsSummary - ranked: number - ranked_date: any - storyboard: boolean - submitted_date: string - tags: string - availability: Availability -} - -export interface Covers { - cover: string - "cover@2x": string - card: string - "card@2x": string - list: string - "list@2x": string - slimcover: string - "slimcover@2x": string -} - -export interface Hype { - current: number - required: number -} - -export interface NominationsSummary { - current: number - required: number -} - -export interface Availability { - download_disabled: boolean - more_information: any + votes: Vote[] + cursor?: Cursor + cursor_string?: string } export interface Discussion { @@ -109,40 +13,7 @@ export interface Discussion { user_id: number deleted_by_id: any message_type: string - parent_id: any - timestamp?: number - resolved: boolean - can_be_resolved: boolean - can_grant_kudosu: boolean - created_at: string - updated_at: string - deleted_at: any - last_post_at: string - kudosu_denied: boolean - starting_post: StartingPost -} - -export interface StartingPost { - beatmapset_discussion_id: number - created_at: string - deleted_at: any - deleted_by_id: any - id: number - last_editor_id?: number - message: string - system: boolean - updated_at: string - user_id: number -} - -export interface IncludedDiscussion { - id: number - beatmapset_id: number - beatmap_id?: number - user_id: number - deleted_by_id: any - message_type: string - parent_id: number + parent_id?: number timestamp?: number resolved: boolean can_be_resolved: boolean @@ -152,24 +23,6 @@ export interface IncludedDiscussion { deleted_at: any last_post_at: string kudosu_denied: boolean - starting_post: StartingPost2 -} - -export interface StartingPost2 { - beatmapset_discussion_id: number - created_at: string - deleted_at: any - deleted_by_id: any - id: number - last_editor_id: any - message: string - system: boolean - updated_at: string - user_id: number -} - -export interface ReviewsConfig { - max_blocks: number } export interface User { @@ -190,7 +43,7 @@ export interface User { } export interface Group { - colour?: string + colour: string has_listing: boolean has_playmodes: boolean id: number @@ -201,6 +54,15 @@ export interface Group { playmodes?: string[] } +export interface Vote { + beatmapset_discussion_id: number + created_at: string + id: number + score: number + updated_at: string + user_id: number +} + export interface Cursor { page: number limit: number From 0f202636e44a271b2863261ce8d25d43f28b2e2d Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 15:18:49 +0300 Subject: [PATCH 084/259] beatmaps_download - errors handling & types --- api/v2/beatmaps_download.ts | 42 ++++++++++++++++--------- routes/v2.ts | 2 +- utility/request.ts | 62 +++++++++++++++++++++++++++++++------ 3 files changed, 81 insertions(+), 25 deletions(-) diff --git a/api/v2/beatmaps_download.ts b/api/v2/beatmaps_download.ts index cf47540d..b5834bd0 100644 --- a/api/v2/beatmaps_download.ts +++ b/api/v2/beatmaps_download.ts @@ -1,5 +1,5 @@ -import { IDefaultParams } from "../../types"; -import { download, request } from "../../utility/request"; +import { IDefaultParams, IError } from "../../types"; +import { download } from "../../utility/request"; import path from "path"; import fs from "fs"; @@ -19,7 +19,7 @@ type params = ({ type: 'set'; id: number; - host: 'osu' | 'beatconnect' | 'chimu' | 'nerinyan' | 'osu_direct_mirror' | 'sayobot' | 'gatari' | 'ripple' | 'akatsuki' | 'catboy', + host: 'osu' | 'beatconnect' | 'chimu' | 'nerinyan' | 'osu_direct_mirror' | 'sayobot' | 'gatari' | 'ripple' | 'catboy', file_path: string; no_video?: boolean; @@ -29,13 +29,23 @@ type params = ({ }); -const name = async (params: T, addons?: IDefaultParams): Promise => { +type Response = { + status: string, + destination?: string, + /** + * Time in milliseconds + */ + elapsed_time?: number +} | IError; + + +export const beatmaps_download = async (params: T, addons?: IDefaultParams): Promise => { const { dir } = path.parse(params.file_path); if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); if (fs.existsSync(params.file_path) && params.overwrite != true) { - return 'exists'; + return { status: 'exists' }; }; @@ -86,10 +96,10 @@ const name = async (params: T, addons?: IDefaultParams): Promi headers['Referer'] = 'https://ripple.moe/'; break; - case 'akatsuki': - url = `https://akatsuki.gg/d/${params.id}`; - headers['Referer'] = 'https://akatsuki.gg/'; - break; + // case 'akatsuki': + // url = `https://akatsuki.gg/d/${params.id}`; + // headers['Referer'] = 'https://akatsuki.gg/'; + // break; case 'catboy': url = `https://catboy.best/d/${params.id}`; @@ -107,12 +117,16 @@ const name = async (params: T, addons?: IDefaultParams): Promi const data = await download(url, params.file_path, { _callback: params.progress_track_fn != null, headers, + addons: addons, callback: progress_track, }); return data; - } else if (params.type == 'difficulty') { + }; + + + if (params.type == 'difficulty') { switch (params.host) { case 'osu_direct_mirror': url = `https://api.osu.direct/osu/${params.id}?raw=true` @@ -132,6 +146,7 @@ const name = async (params: T, addons?: IDefaultParams): Promi const data = await download(url, params.file_path, { _callback: params.progress_track_fn != null, headers, + addons: addons, callback: progress_track, }); @@ -140,8 +155,5 @@ const name = async (params: T, addons?: IDefaultParams): Promi }; - return `Unknown type: ${(params as any).type}`; -}; - - -export default name; \ No newline at end of file + return { error: new Error(`Unsupported type: ${(params as any).type}`) }; +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 0e1e09bf..db13e3d6 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -1,7 +1,7 @@ import { beatmaps_events_list } from "../api/v2/beatmaps_events_list"; import beatmaps_lookup from "../api/v2/beatmaps_lookup"; import { beatmaps_details } from "../api/v2/beatmaps_details"; -import beatmaps_download from "../api/v2/beatmaps_download"; +import { beatmaps_download } from "../api/v2/beatmaps_download"; import { beatmaps_packs_list } from "../api/v2/beatmaps_packs_list"; import { beatmap_packs_details } from "../api/v2/beatmaps_packs_details"; import { beatmaps_discussions_list } from "../api/v2/beatmaps_discussions_list"; diff --git a/utility/request.ts b/utility/request.ts index 1c213e37..2d51ed48 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -110,7 +110,7 @@ export const request: RequestType = (url, { method, headers, data, params = {}, if ('error' in parse) { if (parse.error === null) { - return resolve({ error: new Error(`osu returned empty error, double check your parameters`) }); + return resolve({ error: new Error(`osu returned empty error, double check your parameters (request)`) }); }; @@ -169,6 +169,7 @@ export const download = (url: string, dest: string, { _callback, headers = {}, d callback?: Function; }): Promise => { return new Promise((resolve, reject) => { + const start_time = performance.now(); if (url.includes('https://osu.ppy.sh/api/v2')) headers['Authorization'] = `Bearer ${params?.v2 || auth.cache.v2}`; if (!headers['accept']) headers['accept'] = `application/octet-stream`; @@ -177,9 +178,10 @@ export const download = (url: string, dest: string, { _callback, headers = {}, d const generate_query = querystring.encode(params); const build_url = url + (generate_query ? `?${generate_query}` : ''); - // console.log({ url: build_url, method, headers, data }); + // console.log({ url: build_url, headers, data }); // debug const req = https.request(build_url, { method: 'GET', headers }, response => { const { location } = response.headers; + // console.log(url, response.headers['content-type'], response.headers); // debug too if (location) { download(location, dest, { _callback, headers, data, params, callback }) @@ -189,6 +191,44 @@ export const download = (url: string, dest: string, { _callback, headers = {}, d }; + if (response.statusCode === 404) { + return resolve({ error: new Error('file unavailable') }); + }; + + + if (response.headers['content-type'] == 'application/json') { + const chunks: any[] = []; + + + response.on('data', (chunk: any) => chunks.push(chunk)); + response.on('end', async () => { + try { + const data = Buffer.concat(chunks).toString(); + const json = JSON.parse(data); + + + if ('error' in json && json.error == null) { + return resolve({ error: new Error('osu returned empty error (download)') }); + }; + + + return resolve(json); + } catch (error) { + return resolve({ error: error }); + }; + }); + + + return; + }; + + + if (response.headers['content-type'] == null && +(response.headers['content-length'] || 0) < 100) { + + return resolve({ error: new Error(`Unnable to download from: ${url}`) }); + }; + + const file = fs.createWriteStream(dest, { encoding: 'utf8' }); file.on('error', error => { @@ -198,16 +238,12 @@ export const download = (url: string, dest: string, { _callback, headers = {}, d file.on('finish', () => { file.close(); - resolve(dest); + + const finish_time = performance.now(); + resolve({ status: 'finished', destination: dest, elapsed_time: finish_time - start_time }); }); - if (response.statusCode === 404) { - resolve({ error: new Error('file unavailable') }); - return; - }; - - if (_callback == true && callback !== undefined) { const totalLength = parseInt(response.headers['content-length']); @@ -224,6 +260,14 @@ export const download = (url: string, dest: string, { _callback, headers = {}, d response.pipe(file); }); + + // send error + req.on('error', (error) => { + resolve({ error: error }); + }); + + + // timeout req.setTimeout(addons.timeout_ms || auth.settings.timeout, () => { req.destroy(); resolve({ error: new Error(`Request to ${build_url} time out after ${addons.timeout_ms || auth.settings.timeout}ms`) }); From 3959c7fde1d899ee8ab803cdc0d133443e44de4c Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 15:33:26 +0300 Subject: [PATCH 085/259] beatmaps_lookups - errors handling & types --- api/v2/beatmaps_actions.ts | 46 +++++++++++++------------- api/v2/beatmaps_lookup.ts | 34 +++++++++++++------ routes/v2.ts | 2 +- types/v2/beatmaps_lookup_difficulty.ts | 5 +-- types/v2/beatmaps_lookup_set.ts | 1 - 5 files changed, 48 insertions(+), 40 deletions(-) diff --git a/api/v2/beatmaps_actions.ts b/api/v2/beatmaps_actions.ts index 7b36ccc5..9ac7cd97 100644 --- a/api/v2/beatmaps_actions.ts +++ b/api/v2/beatmaps_actions.ts @@ -1,5 +1,5 @@ import { request } from "../../utility/request"; -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; import { postDataObject } from "../../tools"; @@ -19,38 +19,38 @@ type Response = : never; // FIX -const name = async (params: T, addons?: IDefaultParams): Promise | { error: string }> => { +const name = async (params: T, addons?: IDefaultParams): Promise | IError> => { return { - error: 'TEMPORARY NOT WORKING, have no clue why', + error: new Error('TEMPORARY NOT WORKING, have no clue why'), }; - if (params.type == null) - return { - error: 'Type not specified', - }; + // if (params.type == null) + // return { + // error: 'Type not specified', + // }; - const object: any = {}; - let url = 'https://osu.ppy.sh/api/v2'; - let method = 'POST'; + // const object: any = {}; + // let url = 'https://osu.ppy.sh/api/v2'; + // let method = 'POST'; - switch (params.type) { - case 'favourite': - url += `/beatmapsets/${params.beatmapset_id}/favourites`; + // switch (params.type) { + // case 'favourite': + // url += `/beatmapsets/${params.beatmapset_id}/favourites`; - object['action'] = params.add == true ? 'favourite' : 'unfavourite'; - break; - }; + // object['action'] = params.add == true ? 'favourite' : 'unfavourite'; + // break; + // }; - const data = await request(url, { - method: method, - // params: object, - data: postDataObject('', object), - addons, - }); + // const data = await request(url, { + // method: method, + // // params: object, + // data: postDataObject('', object), + // addons, + // }); - return data as Response; + // return data as Response; }; diff --git a/api/v2/beatmaps_lookup.ts b/api/v2/beatmaps_lookup.ts index cd149424..ca8359a7 100644 --- a/api/v2/beatmaps_lookup.ts +++ b/api/v2/beatmaps_lookup.ts @@ -3,7 +3,7 @@ import { BeatmapsLookupDifficulty } from "../../types/v2/beatmaps_lookup_difficu import { BeatmapsLookupSet } from "../../types/v2/beatmaps_lookup_set"; import { Modes_enums } from "../../types/enums"; import { request } from "../../utility/request"; -import { IDefaultParams, Modes_names } from "../../types"; +import { IDefaultParams, IError, Modes_names } from "../../types"; import { BeatmapsLookupDifficultiesResponse } from "../../types/v2/beatmaps_lookup_difficulties"; @@ -28,17 +28,17 @@ type params = ({ type Response = T extends 'difficulty' - ? BeatmapsLookupDifficulty + ? BeatmapsLookupDifficulty | IError : T extends 'set' - ? BeatmapsLookupSet + ? BeatmapsLookupSet | IError : T extends 'attributes' - ? BeatmapsLookupAttributes + ? BeatmapsLookupAttributes | IError : T extends 'difficulties' - ? BeatmapsLookupDifficultiesResponse[] - : never; + ? BeatmapsLookupDifficultiesResponse[] | IError + : IError; -const name = async (params: T, addons?: IDefaultParams): Promise> => { +export const beatmaps_lookup = async (params: T, addons?: IDefaultParams): Promise> => { const object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; let method = 'GET'; @@ -48,6 +48,10 @@ const name = async (params: T, addons?: IDefaultParams): Promi case 'difficulty': url += '/beatmaps/lookup'; + if (params.id == null && params.checksum && params.filename) { + return { error: new Error(`Specify at least one parameter`) } as Response; + }; + if (params.id) object.id = params.id; if (params.checksum) object.checksum = params.checksum; if (params.filename) object.filename = params.filename; @@ -57,6 +61,10 @@ const name = async (params: T, addons?: IDefaultParams): Promi case 'set': url += '/beatmapsets/lookup'; + if (params.id == null) { + return { error: new Error(`Specify beatmap set id`) } as Response; + }; + if (params.id) object.beatmap_id = params.id; break; @@ -65,6 +73,10 @@ const name = async (params: T, addons?: IDefaultParams): Promi url += `/beatmaps/${params.id}/attributes`; method = 'POST'; + if (params.id == null) { + return { error: new Error(`Specify beatmap id`) } as Response; + }; + if (params.mods) object.mods = params.mods; if (typeof params.mode == 'string') object.ruleset = params.mode; @@ -76,6 +88,9 @@ const name = async (params: T, addons?: IDefaultParams): Promi url += `/beatmaps`; if (Array.isArray(params.ids)) object['ids[]'] = params.ids; + else { + return { error: new Error(`Specify at least one beatmap id`) } as Response; + }; break; }; @@ -91,7 +106,4 @@ const name = async (params: T, addons?: IDefaultParams): Promi if (params.type == 'attributes') return data.attributes as Response; if (params.type == 'difficulties') return data.beatmaps as Response; return data as Response; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index db13e3d6..99ad669e 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -1,5 +1,5 @@ import { beatmaps_events_list } from "../api/v2/beatmaps_events_list"; -import beatmaps_lookup from "../api/v2/beatmaps_lookup"; +import { beatmaps_lookup } from "../api/v2/beatmaps_lookup"; import { beatmaps_details } from "../api/v2/beatmaps_details"; import { beatmaps_download } from "../api/v2/beatmaps_download"; import { beatmaps_packs_list } from "../api/v2/beatmaps_packs_list"; diff --git a/types/v2/beatmaps_lookup_difficulty.ts b/types/v2/beatmaps_lookup_difficulty.ts index 4917f5a1..b1b91435 100644 --- a/types/v2/beatmaps_lookup_difficulty.ts +++ b/types/v2/beatmaps_lookup_difficulty.ts @@ -93,7 +93,4 @@ export interface Availability { export interface Failtimes { fail: number[] exit: number[] -} - - - +} \ No newline at end of file diff --git a/types/v2/beatmaps_lookup_set.ts b/types/v2/beatmaps_lookup_set.ts index 86b5ad43..1c15f406 100644 --- a/types/v2/beatmaps_lookup_set.ts +++ b/types/v2/beatmaps_lookup_set.ts @@ -1,5 +1,4 @@ export interface BeatmapsLookupSet { - error: any artist?: string artist_unicode?: string covers?: Covers From 388fe46381c6dd33fdfa893c1086196023aa0d85 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 15:38:15 +0300 Subject: [PATCH 086/259] changelogs_details - errors handling & types --- api/v2/changelogs_details.ts | 21 ++++++--- routes/v2.ts | 2 +- types/v2/changelogs_details.ts | 83 ++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 8 deletions(-) create mode 100644 types/v2/changelogs_details.ts diff --git a/api/v2/changelogs_details.ts b/api/v2/changelogs_details.ts index 652b1899..697888ca 100644 --- a/api/v2/changelogs_details.ts +++ b/api/v2/changelogs_details.ts @@ -1,12 +1,22 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { changelogsDetailsResponse } from "../../types/v2/changelogs_details"; import { request } from "../../utility/request"; -const name = async (params: { +export const changelogs_details = async (params: { stream_name: string; build_version: string; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { + if (params.stream_name == null) { + return { error: new Error(`Specify stream name`) }; + }; + + if (params.build_version == null) { + return { error: new Error(`Specify build version`) }; + }; + + const data = await request(`https://osu.ppy.sh/api/v2/changelog/${params.stream_name}/${params.build_version}`, { method: 'GET', addons, @@ -14,7 +24,4 @@ const name = async (params: { return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 99ad669e..534f0a2e 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -34,7 +34,7 @@ export const beatmaps = { import changelogs_list from '../api/v2/changelogs_list'; -import changelogs_details from '../api/v2/changelogs_details'; +import { changelogs_details } from '../api/v2/changelogs_details'; export const changelogs = { diff --git a/types/v2/changelogs_details.ts b/types/v2/changelogs_details.ts new file mode 100644 index 00000000..022e8170 --- /dev/null +++ b/types/v2/changelogs_details.ts @@ -0,0 +1,83 @@ +export interface changelogsDetailsResponse { + created_at: string + display_version: string + id: number + users: number + version: string + youtube_id: any + update_stream: UpdateStream + changelog_entries: ChangelogEntry[] + versions: Versions +} + +export interface UpdateStream { + id: number + name: string + display_name: string + is_featured: boolean +} + +export interface ChangelogEntry { + id: number + repository: string + github_pull_request_id: number + github_url: string + url: any + type: string + category: string + title: string + major: boolean + created_at: string + github_user: GithubUser + message: any + message_html: any +} + +export interface GithubUser { + display_name: string + github_url: string + github_username: string + id: number + osu_username?: string + user_id?: number + user_url?: string +} + +export interface Versions { + next: Next + previous: Previous +} + +export interface Next { + created_at: string + display_version: string + id: number + users: number + version: string + youtube_id: any + update_stream: UpdateStream2 +} + +export interface UpdateStream2 { + id: number + name: string + display_name: string + is_featured: boolean +} + +export interface Previous { + created_at: string + display_version: string + id: number + users: number + version: string + youtube_id: any + update_stream: UpdateStream3 +} + +export interface UpdateStream3 { + id: number + name: string + display_name: string + is_featured: boolean +} From c24eb663982d535271b2bca166e77c0283a15266 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 15:47:57 +0300 Subject: [PATCH 087/259] changelogs_list - errors handling & types --- api/v2/beatmaps_lookup.ts | 3 ++ api/v2/changelogs_list.ts | 43 +++++++++------- routes/v2.ts | 2 +- types/v2/changelogs_list_all.ts | 83 ++++++++++++++++++++++++++++++ types/v2/changelogs_list_lookup.ts | 65 +++++++++++++++++++++++ 5 files changed, 175 insertions(+), 21 deletions(-) create mode 100644 types/v2/changelogs_list_all.ts create mode 100644 types/v2/changelogs_list_lookup.ts diff --git a/api/v2/beatmaps_lookup.ts b/api/v2/beatmaps_lookup.ts index ca8359a7..5243a519 100644 --- a/api/v2/beatmaps_lookup.ts +++ b/api/v2/beatmaps_lookup.ts @@ -93,6 +93,9 @@ export const beatmaps_lookup = async (params: T, addons?: IDef }; break; + + default: + return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; }; diff --git a/api/v2/changelogs_list.ts b/api/v2/changelogs_list.ts index 123b63d7..168e0483 100644 --- a/api/v2/changelogs_list.ts +++ b/api/v2/changelogs_list.ts @@ -1,4 +1,6 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { ChangelogsListAllResponse } from "../../types/v2/changelogs_list_all"; +import { ChangelogsListLookupResponse } from "../../types/v2/changelogs_list_lookup"; import { request } from "../../utility/request"; @@ -22,15 +24,13 @@ type params = ({ type Response = T extends 'all' - ? any + ? ChangelogsListAllResponse | IError : T extends 'lookup' - ? any - : never; + ? ChangelogsListLookupResponse | IError + : IError; -const name = async (params: T, addons?: IDefaultParams) => { - if (params.type == null) return null; - +export const changelogs_list = async (params: T, addons?: IDefaultParams) => { let object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; let method = 'GET'; @@ -39,23 +39,29 @@ const name = async (params: T, addons?: IDefaultParams) => { switch (params.type) { case 'all': url += '/changelog'; - - object = { - from: params.from_build, - to: params.to_build, - - stream: params.stream_name, - max_id: params.max_id, - 'message_formats[]': params.message_formats, - }; + + object.from = params.from_build; + object.to = params.to_build; + + object.stream = params.stream_name; + object.max_id = params.max_id; + object['message_formats[]'] = params.message_formats; break; case 'lookup': url += `/changelog/${params.changelog}`; + if (params.changelog == null) { + return { error: new Error(`Specify changelog stream`) } as Response; + }; + + object['message_formats[]'] = params.message_formats; object['key'] = params.key; break; + + default: + return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; }; @@ -67,7 +73,4 @@ const name = async (params: T, addons?: IDefaultParams) => { return data as Response; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 534f0a2e..e1411e7e 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -33,7 +33,7 @@ export const beatmaps = { -import changelogs_list from '../api/v2/changelogs_list'; +import { changelogs_list } from '../api/v2/changelogs_list'; import { changelogs_details } from '../api/v2/changelogs_details'; diff --git a/types/v2/changelogs_list_all.ts b/types/v2/changelogs_list_all.ts new file mode 100644 index 00000000..eb01ccb3 --- /dev/null +++ b/types/v2/changelogs_list_all.ts @@ -0,0 +1,83 @@ +export interface ChangelogsListAllResponse { + streams: Stream[] + builds: Build[] + search: Search +} + +export interface Stream { + id: number + name: string + display_name: string + is_featured: boolean + latest_build: LatestBuild + user_count: number +} + +export interface LatestBuild { + created_at: string + display_version: string + id: number + users: number + version: string + youtube_id?: string + update_stream: UpdateStream +} + +export interface UpdateStream { + id: number + name: string + display_name: string + is_featured: boolean +} + +export interface Build { + created_at: string + display_version: string + id: number + users: number + version: string + youtube_id?: string + update_stream: UpdateStream2 + changelog_entries: ChangelogEntry[] +} + +export interface UpdateStream2 { + id: number + name: string + display_name: string + is_featured: boolean +} + +export interface ChangelogEntry { + id?: number + repository?: string + github_pull_request_id?: number + github_url?: string + url: any + type: string + category: string + title: string + major: boolean + created_at: string + github_user: GithubUser + message?: string + message_html?: string +} + +export interface GithubUser { + display_name: string + github_url?: string + github_username?: string + id?: number + osu_username?: string + user_id?: number + user_url?: string +} + +export interface Search { + stream: any + from: any + to: any + max_id: any + limit: number +} diff --git a/types/v2/changelogs_list_lookup.ts b/types/v2/changelogs_list_lookup.ts new file mode 100644 index 00000000..0e11874d --- /dev/null +++ b/types/v2/changelogs_list_lookup.ts @@ -0,0 +1,65 @@ +export interface ChangelogsListLookupResponse { + created_at: string + display_version: string + id: number + users: number + version: string + youtube_id: any + update_stream: UpdateStream + changelog_entries: ChangelogEntry[] + versions: Versions +} + +export interface UpdateStream { + id: number + name: string + display_name: string + is_featured: boolean +} + +export interface ChangelogEntry { + id: number + repository: string + github_pull_request_id: number + github_url: string + url: any + type: string + category: string + title: string + major: boolean + created_at: string + github_user: GithubUser + message: any + message_html: any +} + +export interface GithubUser { + display_name: string + github_url: string + github_username: string + id: number + osu_username?: string + user_id?: number + user_url?: string +} + +export interface Versions { + previous: Previous +} + +export interface Previous { + created_at: string + display_version: string + id: number + users: number + version: string + youtube_id: any + update_stream: UpdateStream2 +} + +export interface UpdateStream2 { + id: number + name: string + display_name: string + is_featured: boolean +} From f7de4e98dababe053b107d5b63abc77e99d30eee Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 15:56:13 +0300 Subject: [PATCH 088/259] chat_actions - errors handling & types --- api/v2/chat_actions.ts | 31 ++++++++++++-------- routes/v2.ts | 2 +- types/v2/chat_actions_keepalive.ts | 8 ++++++ types/v2/chat_actions_new.ts | 45 ++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 13 deletions(-) create mode 100644 types/v2/chat_actions_keepalive.ts create mode 100644 types/v2/chat_actions_new.ts diff --git a/api/v2/chat_actions.ts b/api/v2/chat_actions.ts index bd531598..de906f3b 100644 --- a/api/v2/chat_actions.ts +++ b/api/v2/chat_actions.ts @@ -1,5 +1,7 @@ import { request } from "../../utility/request"; -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { ChatActionsNewResponse } from "../../types/v2/chat_actions_new"; +import { ChatActionsKeepaliveResponse } from "../../types/v2/chat_actions_keepalive"; type params = ({ @@ -20,14 +22,14 @@ type params = ({ type Response = - T extends 'difficulty' - ? any - : T extends 'difficulties' - ? any - : never; + T extends 'new' + ? ChatActionsNewResponse | IError + : T extends 'keepalive' + ? ChatActionsKeepaliveResponse | IError + : IError; -const name = async (params: T, addons?: IDefaultParams): Promise> => { +export const chat_actions = async (params: T, addons?: IDefaultParams): Promise> => { const object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; let method = 'POST'; @@ -38,10 +40,15 @@ const name = async (params: T, addons?: IDefaultParams): Promi url += `/chat/new`; method = 'POST'; + if (params.is_action == null || params.user_id == null || params.message == null) { + return { error: new Error('Missing required parameters') } as Response; + }; + + object['is_action'] = params.is_action; object['target_id'] = params.user_id; object['message'] = params.message; - object['uuid'] = params.uuid; + if (params.uuid) object['uuid'] = params.uuid; break; case 'keepalive': @@ -51,6 +58,9 @@ const name = async (params: T, addons?: IDefaultParams): Promi object['history_since'] = params.history_since; object['since'] = params.since; break; + + default: + return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; }; @@ -62,7 +72,4 @@ const name = async (params: T, addons?: IDefaultParams): Promi return data as Response; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index e1411e7e..48bff720 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -202,7 +202,7 @@ import chat_list from "../api/v2/chat_list"; import chat_messages from "../api/v2/chat_messages"; import chat_updates from "../api/v2/chat_updates"; import chat_details from "../api/v2/chat_details"; -import chat_actions from "../api/v2/chat_actions"; +import { chat_actions } from "../api/v2/chat_actions"; export const chat = { diff --git a/types/v2/chat_actions_keepalive.ts b/types/v2/chat_actions_keepalive.ts new file mode 100644 index 00000000..05bd979f --- /dev/null +++ b/types/v2/chat_actions_keepalive.ts @@ -0,0 +1,8 @@ +export interface ChatActionsKeepaliveResponse { + silences: Silence[] +} + +export interface Silence { + id: number + user_id: number +} diff --git a/types/v2/chat_actions_new.ts b/types/v2/chat_actions_new.ts new file mode 100644 index 00000000..fbe2ac49 --- /dev/null +++ b/types/v2/chat_actions_new.ts @@ -0,0 +1,45 @@ +export interface ChatActionsNewResponse { + channel: Channel + message: Message + new_channel_id: number +} + +export interface Channel { + channel_id: number + description: string + icon: string + message_length_limit: number + moderated: boolean + name: string + type: string + uuid: any + last_message_id: number + users: number[] +} + +export interface Message { + channel_id: number + content: string + is_action: boolean + message_id: number + sender_id: number + timestamp: string + type: string + sender: Sender +} + +export interface Sender { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: any + pm_friends_only: boolean + profile_colour: any + username: string +} From 215080f9b6b58694c98135bc1710c987254696b5 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 16:03:37 +0300 Subject: [PATCH 089/259] chat_channels_actions - errors handling & types --- api/v2/chat_channels_actions.ts | 52 +++++++++++++++++++------- routes/v2.ts | 2 +- types/v2/chat_channels_actions_join.ts | 20 ++++++++++ types/v2/chat_channels_actions_send.ts | 26 +++++++++++++ 4 files changed, 86 insertions(+), 14 deletions(-) create mode 100644 types/v2/chat_channels_actions_join.ts create mode 100644 types/v2/chat_channels_actions_send.ts diff --git a/api/v2/chat_channels_actions.ts b/api/v2/chat_channels_actions.ts index a9da0937..bbe009b9 100644 --- a/api/v2/chat_channels_actions.ts +++ b/api/v2/chat_channels_actions.ts @@ -1,5 +1,7 @@ import { request } from "../../utility/request"; -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { chatChannelsActionsSendResponse } from "../../types/v2/chat_channels_actions_send"; +import { chatChannelsActionsJoinResponse } from "../../types/v2/chat_channels_actions_join"; type params = ({ @@ -23,14 +25,18 @@ type params = ({ type Response = - T extends 'difficulty' - ? any - : T extends 'difficulties' - ? any - : never; - - -const name = async (params: T, addons?: IDefaultParams): Promise> => { + T extends 'send' + ? chatChannelsActionsSendResponse | IError + : T extends 'join' + ? chatChannelsActionsJoinResponse | IError + : T extends 'leave' + ? "" | IError + : T extends 'readed' + ? "" | IError + : IError; + + +export const chat_channels_actions = async (params: T, addons?: IDefaultParams): Promise> => { const object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; let method = 'POST'; @@ -38,6 +44,11 @@ const name = async (params: T, addons?: IDefaultParams): Promi switch (params.type) { case 'send': + if (params.id == null || params.message == null || params.is_action == null) { + return { error: new Error(`Missing required parameters`) } as Response; + }; + + url += `/chat/channels/${params.id}/messages`; object['message'] = params.message; @@ -45,19 +56,37 @@ const name = async (params: T, addons?: IDefaultParams): Promi break; case 'join': + if (params.id == null || params.user_id == null) { + return { error: new Error(`Missing required parameters`) } as Response; + }; + + url += `/chat/channels/${params.id}/users/${params.user_id}`; method = 'PUT'; break; case 'leave': + if (params.id == null || params.user_id == null) { + return { error: new Error(`Missing required parameters`) } as Response; + }; + + url += `/chat/channels/${params.id}/users/${params.user_id}`; method = 'DELETE'; break; case 'readed': + if (params.channel_id == null || params.message_id == null) { + return { error: new Error(`Missing required parameters`) } as Response; + }; + + url += `/chat/channels/${params.channel_id}/mark-as-read/${params.message_id}`; method = 'PUT'; break; + + default: + return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; }; @@ -69,7 +98,4 @@ const name = async (params: T, addons?: IDefaultParams): Promi return data as Response; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 48bff720..a4efa672 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -196,7 +196,7 @@ export const matches = { import chat_channels_list from "../api/v2/chat_channels_list"; -import chat_channels_actions from "../api/v2/chat_channels_actions"; +import { chat_channels_actions } from "../api/v2/chat_channels_actions"; import chat_list from "../api/v2/chat_list"; import chat_messages from "../api/v2/chat_messages"; diff --git a/types/v2/chat_channels_actions_join.ts b/types/v2/chat_channels_actions_join.ts new file mode 100644 index 00000000..0da481eb --- /dev/null +++ b/types/v2/chat_channels_actions_join.ts @@ -0,0 +1,20 @@ +export interface chatChannelsActionsJoinResponse { + channel_id: number + description: string + icon: any + message_length_limit: number + moderated: boolean + name: string + type: string + uuid: any + current_user_attributes: CurrentUserAttributes + last_message_id: number + last_read_id: any + users: any[] +} + +export interface CurrentUserAttributes { + can_message: boolean + can_message_error: any + last_read_id: any +} diff --git a/types/v2/chat_channels_actions_send.ts b/types/v2/chat_channels_actions_send.ts new file mode 100644 index 00000000..ea29b963 --- /dev/null +++ b/types/v2/chat_channels_actions_send.ts @@ -0,0 +1,26 @@ +export interface chatChannelsActionsSendResponse { + channel_id: number + content: string + is_action: boolean + message_id: number + sender_id: number + timestamp: string + type: string + sender: Sender +} + +export interface Sender { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: any + pm_friends_only: boolean + profile_colour: any + username: string +} From c684e270feb0018c77fc88ec424f8d3b77663d6e Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 16:08:23 +0300 Subject: [PATCH 090/259] prevent making requests without api key/authorization --- utility/request.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/utility/request.ts b/utility/request.ts index 2d51ed48..ded5869d 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -38,9 +38,15 @@ export const request: RequestType = (url, { method, headers, data, params = {}, // V1 add credentials - if (url.includes('https://osu.ppy.sh/api/') && !url.includes('https://osu.ppy.sh/api/v2')) + if (url.includes('https://osu.ppy.sh/api/') && !url.includes('https://osu.ppy.sh/api/v2')) { params.k = addons.authKey || auth.cache.v1; + if (params.k == null) { + return resolve({ error: new Error('v1 api key not specified'), }); + }; + }; + + // V2 add credentials if (url.includes('https://osu.ppy.sh/api/v2')) { if (!headers) headers = {}; @@ -49,6 +55,10 @@ export const request: RequestType = (url, { method, headers, data, params = {}, if (!headers.Accept) headers.Accept = `application/json`; if (!headers['Content-Type']) headers['Content-Type'] = `application/json`; headers['x-api-version'] = addons.apiVersion == '' ? null : addons.apiVersion || '20240130'; + + if ((addons.authKey || auth.cache.v2) == null) { + return resolve({ error: new Error('v2 not authorized'), }); + }; }; @@ -238,7 +248,7 @@ export const download = (url: string, dest: string, { _callback, headers = {}, d file.on('finish', () => { file.close(); - + const finish_time = performance.now(); resolve({ status: 'finished', destination: dest, elapsed_time: finish_time - start_time }); }); From 0863482c510578cb23051b0b73347ec19e9a23f6 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 16:08:34 +0300 Subject: [PATCH 091/259] chat_channels_list - errors handling & types --- api/v2/chat_channels_list.ts | 10 +++++----- routes/v2.ts | 2 +- types/v2/chat_channels_list.ts | 10 ++++++++++ 3 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 types/v2/chat_channels_list.ts diff --git a/api/v2/chat_channels_list.ts b/api/v2/chat_channels_list.ts index 103e3a4b..80ff53e9 100644 --- a/api/v2/chat_channels_list.ts +++ b/api/v2/chat_channels_list.ts @@ -1,14 +1,14 @@ +import { IError } from "../../types"; +import { chatChannelsListResponse } from "../../types/v2/chat_channels_list"; import { request } from "../../utility/request"; -const name = async () => { +export const chat_channels_list = async (): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/chat/channels`, { method: 'GET', }); - return data; -}; - -export default name; \ No newline at end of file + return data; +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index a4efa672..eb32105b 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -195,7 +195,7 @@ export const matches = { -import chat_channels_list from "../api/v2/chat_channels_list"; +import { chat_channels_list } from "../api/v2/chat_channels_list"; import { chat_channels_actions } from "../api/v2/chat_channels_actions"; import chat_list from "../api/v2/chat_list"; diff --git a/types/v2/chat_channels_list.ts b/types/v2/chat_channels_list.ts new file mode 100644 index 00000000..68d49df1 --- /dev/null +++ b/types/v2/chat_channels_list.ts @@ -0,0 +1,10 @@ +export interface chatChannelsListResponse { + channel_id: number + description: string + icon: any + message_length_limit: number + moderated: boolean + name: string + type: string + uuid: any +} From ffc254b8a0086ac64fa4b9fb2112f5127e77f1e2 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 16:18:49 +0300 Subject: [PATCH 092/259] chat_details - errors handling & types --- api/v2/chat_details.ts | 16 +++++++----- routes/v2.ts | 2 +- types/v2/chat_details.ts | 55 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 7 deletions(-) create mode 100644 types/v2/chat_details.ts diff --git a/api/v2/chat_details.ts b/api/v2/chat_details.ts index 38c5ea74..8ace4276 100644 --- a/api/v2/chat_details.ts +++ b/api/v2/chat_details.ts @@ -1,16 +1,20 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { ChatDetailsResponse } from "../../types/v2/chat_details"; import { request } from "../../utility/request"; -const name = async (channel_id: number, addons?: IDefaultParams) => { +export const chat_details = async (channel_id: number, addons?: IDefaultParams): Promise => { + if (channel_id == null) { + return { error: new Error(`Specify channel id`) }; + }; + + const data = await request(`https://osu.ppy.sh/api/v2/chat/channels/${channel_id}`, { method: 'GET', addons, }); - return data; -}; - -export default name; \ No newline at end of file + return data; +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index eb32105b..013f87fd 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -201,7 +201,7 @@ import { chat_channels_actions } from "../api/v2/chat_channels_actions"; import chat_list from "../api/v2/chat_list"; import chat_messages from "../api/v2/chat_messages"; import chat_updates from "../api/v2/chat_updates"; -import chat_details from "../api/v2/chat_details"; +import { chat_details } from "../api/v2/chat_details"; import { chat_actions } from "../api/v2/chat_actions"; diff --git a/types/v2/chat_details.ts b/types/v2/chat_details.ts new file mode 100644 index 00000000..e90b64a8 --- /dev/null +++ b/types/v2/chat_details.ts @@ -0,0 +1,55 @@ +export interface ChatDetailsResponse { + channel: Channel + users: User[] +} + +export interface Channel { + channel_id: number + description: string + icon: string + message_length_limit: number + moderated: boolean + name: string + type: string + uuid: any + current_user_attributes: CurrentUserAttributes + last_message_id: number + last_read_id: number + users: number[] +} + +export interface CurrentUserAttributes { + can_message: boolean + can_message_error: any + last_read_id: number +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour: any + username: string + country: Country + cover: Cover + groups: any[] +} + +export interface Country { + code: string + name: string +} + +export interface Cover { + custom_url: string + url: string + id: any +} From e19b9307d2e4c18d96f6bdabcaf0c8a7aaca1f40 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 16:20:48 +0300 Subject: [PATCH 093/259] chat_list - errors handling & types --- api/v2/chat_list.ts | 12 +++++------- routes/v2.ts | 2 +- types/v2/chat_list.ts | 20 ++++++++++++++++++++ 3 files changed, 26 insertions(+), 8 deletions(-) create mode 100644 types/v2/chat_list.ts diff --git a/api/v2/chat_list.ts b/api/v2/chat_list.ts index 76ce1e22..e406e3ad 100644 --- a/api/v2/chat_list.ts +++ b/api/v2/chat_list.ts @@ -1,12 +1,13 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { ChatListResponse } from "../../types/v2/chat_list"; import { request } from "../../utility/request"; -const name = async (params: { +export const chat_list = async (params: { unreaded?: boolean; sort?: 'date_desc' | 'date_asc'; -}, addons?: IDefaultParams) => { +}, addons?: IDefaultParams): Promise => { let data = await request(`https://osu.ppy.sh/api/v2/chat/presence/`, { method: 'GET', addons @@ -24,7 +25,4 @@ const name = async (params: { return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 013f87fd..db5a1ea1 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -198,7 +198,7 @@ export const matches = { import { chat_channels_list } from "../api/v2/chat_channels_list"; import { chat_channels_actions } from "../api/v2/chat_channels_actions"; -import chat_list from "../api/v2/chat_list"; +import { chat_list } from "../api/v2/chat_list"; import chat_messages from "../api/v2/chat_messages"; import chat_updates from "../api/v2/chat_updates"; import { chat_details } from "../api/v2/chat_details"; diff --git a/types/v2/chat_list.ts b/types/v2/chat_list.ts new file mode 100644 index 00000000..e7f9d709 --- /dev/null +++ b/types/v2/chat_list.ts @@ -0,0 +1,20 @@ +export interface ChatListResponse { + channel_id: number + description: string + icon?: string + message_length_limit: number + moderated: boolean + name: string + type: string + uuid: any + current_user_attributes: CurrentUserAttributes + last_message_id: number + last_read_id?: number + users: number[] +} + +export interface CurrentUserAttributes { + can_message: boolean + can_message_error: any + last_read_id?: number +} From be28cc490a51b596d9cdfdb79dc0d2393ddd7ab2 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 16:23:53 +0300 Subject: [PATCH 094/259] chat_messages - errors handling & types --- api/v2/chat_messages.ts | 17 ++++++++++------- routes/v2.ts | 2 +- types/v2/chat_messages.ts | 26 ++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 8 deletions(-) create mode 100644 types/v2/chat_messages.ts diff --git a/api/v2/chat_messages.ts b/api/v2/chat_messages.ts index dfc236bf..c7838005 100644 --- a/api/v2/chat_messages.ts +++ b/api/v2/chat_messages.ts @@ -1,15 +1,21 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { ChatMessagesResponse } from "../../types/v2/chat_messages"; import { request } from "../../utility/request"; -const name = async (params: { +export const chat_messages = async (params: { id: number; limit?: number; since?: number; until?: number; return_object?: boolean; -}, addons?: IDefaultParams) => { +}, addons?: IDefaultParams): Promise => { + if (params.id == null) { + return { error: new Error(`Specify channel id`) }; + }; + + const data = await request(`https://osu.ppy.sh/api/v2/chat/channels/${params.id}/messages`, { method: 'GET', params, @@ -18,7 +24,4 @@ const name = async (params: { return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index db5a1ea1..e01b89ed 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -199,7 +199,7 @@ import { chat_channels_list } from "../api/v2/chat_channels_list"; import { chat_channels_actions } from "../api/v2/chat_channels_actions"; import { chat_list } from "../api/v2/chat_list"; -import chat_messages from "../api/v2/chat_messages"; +import { chat_messages } from "../api/v2/chat_messages"; import chat_updates from "../api/v2/chat_updates"; import { chat_details } from "../api/v2/chat_details"; import { chat_actions } from "../api/v2/chat_actions"; diff --git a/types/v2/chat_messages.ts b/types/v2/chat_messages.ts new file mode 100644 index 00000000..895fd5ec --- /dev/null +++ b/types/v2/chat_messages.ts @@ -0,0 +1,26 @@ +export interface ChatMessagesResponse { + channel_id: number + content: string + is_action: boolean + message_id: number + sender_id: number + timestamp: string + type: string + sender: Sender +} + +export interface Sender { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour: any + username: string +} From ca0f8020a33977309ec0bf2f5450aca0f99328a6 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 16:25:46 +0300 Subject: [PATCH 095/259] chat_updates - errors handling & types --- api/v2/chat_updates.ts | 12 +++++------- routes/v2.ts | 2 +- types/v2/chat_updates.ts | 25 +++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 types/v2/chat_updates.ts diff --git a/api/v2/chat_updates.ts b/api/v2/chat_updates.ts index 623537b4..18e4f966 100644 --- a/api/v2/chat_updates.ts +++ b/api/v2/chat_updates.ts @@ -1,13 +1,14 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { ChatUpdatesResponse } from "../../types/v2/chat_updates"; import { request } from "../../utility/request"; -const name = async (params: { +export const chat_updates = async (params: { after_id: number; includes: ('presence' | 'silences' | 'messages')[]; history_since: number; -}, addons?: IDefaultParams) => { +}, addons?: IDefaultParams): Promise => { const object = { 'history_since': params.history_since, 'includes[]': params.includes, @@ -23,7 +24,4 @@ const name = async (params: { return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index e01b89ed..73733905 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -200,7 +200,7 @@ import { chat_channels_actions } from "../api/v2/chat_channels_actions"; import { chat_list } from "../api/v2/chat_list"; import { chat_messages } from "../api/v2/chat_messages"; -import chat_updates from "../api/v2/chat_updates"; +import { chat_updates } from "../api/v2/chat_updates"; import { chat_details } from "../api/v2/chat_details"; import { chat_actions } from "../api/v2/chat_actions"; diff --git a/types/v2/chat_updates.ts b/types/v2/chat_updates.ts new file mode 100644 index 00000000..a4b79ddf --- /dev/null +++ b/types/v2/chat_updates.ts @@ -0,0 +1,25 @@ +export interface ChatUpdatesResponse { + presence: Presence[] + silences: any[] +} + +export interface Presence { + channel_id: number + description: string + icon?: string + message_length_limit: number + moderated: boolean + name: string + type: string + uuid: any + current_user_attributes: CurrentUserAttributes + last_message_id: number + last_read_id?: number + users: number[] +} + +export interface CurrentUserAttributes { + can_message: boolean + can_message_error?: string + last_read_id?: number +} From cb891f902e9c31f1a9f92dd78957019545c20487 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 16:38:40 +0300 Subject: [PATCH 096/259] comments_actions - errors handling & types --- api/v2/comments_actions.ts | 71 +++++++++++++++++++++++------ routes/v2.ts | 2 +- types/v2/comments_actions_delete.ts | 67 +++++++++++++++++++++++++++ types/v2/comments_actions_edit.ts | 69 ++++++++++++++++++++++++++++ types/v2/comments_actions_new.ts | 69 ++++++++++++++++++++++++++++ types/v2/comments_actions_unvote.ts | 69 ++++++++++++++++++++++++++++ types/v2/comments_actions_vote.ts | 69 ++++++++++++++++++++++++++++ 7 files changed, 402 insertions(+), 14 deletions(-) create mode 100644 types/v2/comments_actions_delete.ts create mode 100644 types/v2/comments_actions_edit.ts create mode 100644 types/v2/comments_actions_new.ts create mode 100644 types/v2/comments_actions_unvote.ts create mode 100644 types/v2/comments_actions_vote.ts diff --git a/api/v2/comments_actions.ts b/api/v2/comments_actions.ts index 48cb20cb..ea2e4ab1 100644 --- a/api/v2/comments_actions.ts +++ b/api/v2/comments_actions.ts @@ -1,5 +1,10 @@ import { request } from "../../utility/request"; -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { CommentsActionsNewResponse } from "../../types/v2/comments_actions_new"; +import { CommentsActionsEditResponse } from "../../types/v2/comments_actions_edit"; +import { CommentsActionsDeleteResponse } from "../../types/v2/comments_actions_delete"; +import { CommentsActionsVoteResponse } from "../../types/v2/comments_actions_vote"; +import { CommentsActionsUnvoteResponse } from "../../types/v2/comments_actions_unvote"; type params = ({ @@ -31,14 +36,20 @@ type params = ({ type Response = - T extends 'difficulty' - ? any - : T extends 'difficulties' - ? any - : never; - - -const name = async (params: T, addons?: IDefaultParams): Promise | { error: string }> => { + T extends 'new' + ? CommentsActionsNewResponse | IError + : T extends 'edit' + ? CommentsActionsEditResponse | IError + : T extends 'delete' + ? CommentsActionsDeleteResponse | IError + : T extends 'vote' + ? CommentsActionsVoteResponse | IError + : T extends 'unvote' + ? CommentsActionsUnvoteResponse | IError + : IError; + + +export const comments_actions = async (params: T, addons?: IDefaultParams): Promise | { error: string }> => { const object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; let method = 'POST'; @@ -48,6 +59,19 @@ const name = async (params: T, addons?: IDefaultParams): Promi case 'new': url += `/comments`; + if (params.id == null) { + return { error: new Error(`Specify news id or beatmap set id`) } as Response; + }; + + if (params.commentable_type == null) { + return { error: new Error(`Specify commentable_type`) } as Response; + }; + + if (params.message == null) { + return { error: new Error(`You forgot to provide message`) } as Response; + }; + + if (params.commentable_type) object['comment[commentable_type]'] = params.commentable_type; if (params.parent_id) object['comment[parent_id]'] = params.parent_id; if (params.id) object['comment[commentable_id]'] = params.id; @@ -55,6 +79,15 @@ const name = async (params: T, addons?: IDefaultParams): Promi break; case 'edit': + if (params.id == null) { + return { error: new Error(`Specify comment id`) } as Response; + }; + + if (params.message == null) { + return { error: new Error(`You forgot to provide message`) } as Response; + }; + + url += `/comments/${params.id}`; method = 'PUT'; @@ -62,18 +95,33 @@ const name = async (params: T, addons?: IDefaultParams): Promi break; case 'delete': + if (params.id == null) { + return { error: new Error(`Specify comment id`) } as Response; + }; + + url += `/comments/${params.id}`; method = 'DELETE'; break; case 'vote': + if (params.id == null) { + return { error: new Error(`Specify comment id`) } as Response; + }; + + url += `/comments/${params.id}/vote`; method = 'POST'; break; case 'unvote': + if (params.id == null) { + return { error: new Error(`Specify comment id`) } as Response; + }; + + url += `/comments/${params.id}/vote`; method = 'DELETE'; @@ -89,7 +137,4 @@ const name = async (params: T, addons?: IDefaultParams): Promi return data as Response; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 73733905..98ecad6a 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -47,7 +47,7 @@ export const changelogs = { import comments_list from '../api/v2/comments_list'; import comments_details from '../api/v2/comments_details'; -import comments_actions from '../api/v2/comments_actions'; +import { comments_actions } from '../api/v2/comments_actions'; export const comments = { diff --git a/types/v2/comments_actions_delete.ts b/types/v2/comments_actions_delete.ts new file mode 100644 index 00000000..49fc6a84 --- /dev/null +++ b/types/v2/comments_actions_delete.ts @@ -0,0 +1,67 @@ +export interface CommentsActionsDeleteResponse { + comments: Comment[] + has_more: boolean + has_more_id: any + included_comments: any[] + pinned_comments: any[] + user_votes: any[] + user_follow: boolean + users: User[] + sort: string + cursor: Cursor + top_level_count: number + total: number + commentable_meta: CommentableMeum[] +} + +export interface Comment { + id: number + parent_id: any + user_id: number + pinned: boolean + replies_count: number + votes_count: number + commentable_type: string + commentable_id: number + legacy_name: any + created_at: string + updated_at: string + deleted_at: string + edited_at: string + edited_by_id: number +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: any + pm_friends_only: boolean + profile_colour: any + username: string +} + +export interface Cursor { + created_at: string + id: number +} + +export interface CommentableMeum { + current_user_attributes?: CurrentUserAttributes + id?: number + type?: string + title: string + url?: string + owner_id?: number + owner_title?: string +} + +export interface CurrentUserAttributes { + can_new_comment_reason: any +} diff --git a/types/v2/comments_actions_edit.ts b/types/v2/comments_actions_edit.ts new file mode 100644 index 00000000..d1603ef8 --- /dev/null +++ b/types/v2/comments_actions_edit.ts @@ -0,0 +1,69 @@ +export interface CommentsActionsEditResponse { + comments: Comment[] + has_more: boolean + has_more_id: any + included_comments: any[] + pinned_comments: any[] + user_votes: any[] + user_follow: boolean + users: User[] + sort: string + cursor: Cursor + top_level_count: number + total: number + commentable_meta: CommentableMeum[] +} + +export interface Comment { + id: number + parent_id: any + user_id: number + pinned: boolean + replies_count: number + votes_count: number + commentable_type: string + commentable_id: number + legacy_name: any + created_at: string + updated_at: string + deleted_at: any + edited_at: string + edited_by_id: number + message: string + message_html: string +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: any + pm_friends_only: boolean + profile_colour: any + username: string +} + +export interface Cursor { + created_at: string + id: number +} + +export interface CommentableMeum { + current_user_attributes?: CurrentUserAttributes + id?: number + type?: string + title: string + url?: string + owner_id?: number + owner_title?: string +} + +export interface CurrentUserAttributes { + can_new_comment_reason: any +} diff --git a/types/v2/comments_actions_new.ts b/types/v2/comments_actions_new.ts new file mode 100644 index 00000000..90223afc --- /dev/null +++ b/types/v2/comments_actions_new.ts @@ -0,0 +1,69 @@ +export interface CommentsActionsNewResponse { + comments: Comment[] + has_more: boolean + has_more_id: any + included_comments: any[] + pinned_comments: any[] + user_votes: any[] + user_follow: boolean + users: User[] + sort: string + cursor: Cursor + top_level_count: number + total: number + commentable_meta: CommentableMeum[] +} + +export interface Comment { + id: number + parent_id: any + user_id: number + pinned: boolean + replies_count: number + votes_count: number + commentable_type: string + commentable_id: number + legacy_name: any + created_at: string + updated_at: string + deleted_at: any + edited_at: any + edited_by_id: any + message: string + message_html: string +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: any + pm_friends_only: boolean + profile_colour: any + username: string +} + +export interface Cursor { + created_at: string + id: number +} + +export interface CommentableMeum { + current_user_attributes?: CurrentUserAttributes + id?: number + type?: string + title: string + url?: string + owner_id?: number + owner_title?: string +} + +export interface CurrentUserAttributes { + can_new_comment_reason: any +} diff --git a/types/v2/comments_actions_unvote.ts b/types/v2/comments_actions_unvote.ts new file mode 100644 index 00000000..bfe04350 --- /dev/null +++ b/types/v2/comments_actions_unvote.ts @@ -0,0 +1,69 @@ +export interface CommentsActionsUnvoteResponse { + comments: Comment[] + has_more: boolean + has_more_id: any + included_comments: any[] + pinned_comments: any[] + user_votes: any[] + user_follow: boolean + users: User[] + sort: string + cursor: Cursor + top_level_count: number + total: number + commentable_meta: CommentableMeum[] +} + +export interface Comment { + id: number + parent_id: any + user_id: number + pinned: boolean + replies_count: number + votes_count: number + commentable_type: string + commentable_id: number + legacy_name: any + created_at: string + updated_at: string + deleted_at: any + edited_at: any + edited_by_id: any + message: string + message_html: string +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour: any + username: string +} + +export interface Cursor { + created_at: string + id: number +} + +export interface CommentableMeum { + current_user_attributes?: CurrentUserAttributes + id?: number + type?: string + title: string + url?: string + owner_id?: number + owner_title?: string +} + +export interface CurrentUserAttributes { + can_new_comment_reason: any +} diff --git a/types/v2/comments_actions_vote.ts b/types/v2/comments_actions_vote.ts new file mode 100644 index 00000000..ab364485 --- /dev/null +++ b/types/v2/comments_actions_vote.ts @@ -0,0 +1,69 @@ +export interface CommentsActionsVoteResponse { + comments: Comment[] + has_more: boolean + has_more_id: any + included_comments: any[] + pinned_comments: any[] + user_votes: number[] + user_follow: boolean + users: User[] + sort: string + cursor: Cursor + top_level_count: number + total: number + commentable_meta: CommentableMeum[] +} + +export interface Comment { + id: number + parent_id: any + user_id: number + pinned: boolean + replies_count: number + votes_count: number + commentable_type: string + commentable_id: number + legacy_name: any + created_at: string + updated_at: string + deleted_at: any + edited_at: any + edited_by_id: any + message: string + message_html: string +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour: any + username: string +} + +export interface Cursor { + created_at: string + id: number +} + +export interface CommentableMeum { + current_user_attributes?: CurrentUserAttributes + id?: number + type?: string + title: string + url?: string + owner_id?: number + owner_title?: string +} + +export interface CurrentUserAttributes { + can_new_comment_reason: any +} From 5eb5d8131c92f70d1680760861b41b0c60686cb5 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 16:41:40 +0300 Subject: [PATCH 097/259] comments_details - errors handling & types --- api/v2/comments_details.ts | 15 ++++--- routes/v2.ts | 2 +- types/v2/comments_details.ts | 86 ++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 7 deletions(-) create mode 100644 types/v2/comments_details.ts diff --git a/api/v2/comments_details.ts b/api/v2/comments_details.ts index 7444161b..c12d11d9 100644 --- a/api/v2/comments_details.ts +++ b/api/v2/comments_details.ts @@ -1,9 +1,15 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { CommentsDetailsResponse } from "../../types/v2/comments_details"; import { request } from "../../utility/request"; -const name = async (comment_id: string, addons?: IDefaultParams) => { +export const comments_details = async (comment_id: string, addons?: IDefaultParams): Promise => { + if (comment_id == null) { + return { error: new Error(`Specify comment id`) }; + }; + + const data = await request(`https://osu.ppy.sh/api/v2/comments/${comment_id}`, { method: 'GET', addons, @@ -11,7 +17,4 @@ const name = async (comment_id: string, addons?: IDefaultParams) => { return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 98ecad6a..a5eed135 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -46,7 +46,7 @@ export const changelogs = { import comments_list from '../api/v2/comments_list'; -import comments_details from '../api/v2/comments_details'; +import { comments_details } from '../api/v2/comments_details'; import { comments_actions } from '../api/v2/comments_actions'; diff --git a/types/v2/comments_details.ts b/types/v2/comments_details.ts new file mode 100644 index 00000000..6887ce28 --- /dev/null +++ b/types/v2/comments_details.ts @@ -0,0 +1,86 @@ +export interface CommentsDetailsResponse { + comments: Comment[] + has_more: boolean + has_more_id: number + included_comments: IncludedComment[] + pinned_comments: any[] + user_votes: any[] + user_follow: boolean + users: User[] + sort: string + cursor: Cursor + commentable_meta: CommentableMeum[] +} + +export interface Comment { + id: number + parent_id: any + user_id: number + pinned: boolean + replies_count: number + votes_count: number + commentable_type: string + commentable_id: number + legacy_name: any + created_at: string + updated_at: string + deleted_at: any + edited_at: any + edited_by_id: any + message: string + message_html: string +} + +export interface IncludedComment { + id: number + parent_id: number + user_id: number + pinned: boolean + replies_count: number + votes_count: number + commentable_type: string + commentable_id: number + legacy_name: any + created_at: string + updated_at: string + deleted_at: any + edited_at: any + edited_by_id: any + message: string + message_html: string +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour?: string + username: string +} + +export interface Cursor { + created_at: string + id: number +} + +export interface CommentableMeum { + current_user_attributes?: CurrentUserAttributes + id?: number + type?: string + title: string + url?: string + owner_id: any + owner_title: any +} + +export interface CurrentUserAttributes { + can_new_comment_reason: string +} From 7513f2514dce4a6a755bbe727b3db78959edca14 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 16:43:24 +0300 Subject: [PATCH 098/259] comments_list - errors handling & types --- api/v2/comments_list.ts | 12 +++--- routes/v2.ts | 2 +- types/v2/comments_list.ts | 88 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 8 deletions(-) create mode 100644 types/v2/comments_list.ts diff --git a/api/v2/comments_list.ts b/api/v2/comments_list.ts index b0c5761b..d4e6c3b8 100644 --- a/api/v2/comments_list.ts +++ b/api/v2/comments_list.ts @@ -1,9 +1,10 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { CommentsListResponse } from "../../types/v2/comments_list"; import { request } from "../../utility/request"; -const name = async (params: { +export const comments_list = async (params: { type?: 'news_post' | 'beatmapset' | 'Build'; id?: string; @@ -15,7 +16,7 @@ const name = async (params: { created_at: string; }; sort?: 'new' | 'old' | 'top'; -}, addons?: IDefaultParams) => { +}, addons?: IDefaultParams): Promise => { const object = { after: params.after_id, commentable_type: params.type, @@ -35,7 +36,4 @@ const name = async (params: { return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index a5eed135..f0ac824f 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -45,7 +45,7 @@ export const changelogs = { -import comments_list from '../api/v2/comments_list'; +import { comments_list } from '../api/v2/comments_list'; import { comments_details } from '../api/v2/comments_details'; import { comments_actions } from '../api/v2/comments_actions'; diff --git a/types/v2/comments_list.ts b/types/v2/comments_list.ts new file mode 100644 index 00000000..cdd08147 --- /dev/null +++ b/types/v2/comments_list.ts @@ -0,0 +1,88 @@ +export interface CommentsListResponse { + comments: Comment[] + has_more: boolean + has_more_id: any + included_comments: any[] + pinned_comments: PinnedComment[] + user_votes: any[] + user_follow: boolean + users: User[] + sort: string + cursor?: Cursor + top_level_count: number + total: number + commentable_meta: CommentableMeum[] +} + +export interface Comment { + id: number + parent_id?: number + user_id: number + pinned: boolean + replies_count: number + votes_count: number + commentable_type: string + commentable_id: number + legacy_name: any + created_at: string + updated_at: string + deleted_at?: string + edited_at?: string + edited_by_id?: number + message?: string + message_html?: string +} + +export interface PinnedComment { + id: number + parent_id: any + user_id: number + pinned: boolean + replies_count: number + votes_count: number + commentable_type: string + commentable_id: number + legacy_name: any + created_at: string + updated_at: string + deleted_at: any + edited_at: any + edited_by_id: any + message: string + message_html: string +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour?: string + username: string +} + +export interface Cursor { + created_at: string + id: number +} + +export interface CommentableMeum { + current_user_attributes?: CurrentUserAttributes + id?: number + type?: string + title: string + url?: string + owner_id: any + owner_title: any +} + +export interface CurrentUserAttributes { + can_new_comment_reason: string +} From fb72b5070b50747605bee1ba0a68bf016bfc9149 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 17:02:31 +0300 Subject: [PATCH 099/259] forums_topics_actions - errors handling & types --- api/v2/forums_topics_actions.ts | 96 ++++++++++++++++---- routes/v2.ts | 2 +- types/v2/forums_topics_actions_create.ts | 37 ++++++++ types/v2/forums_topics_actions_edit_post.ts | 16 ++++ types/v2/forums_topics_actions_edit_topic.ts | 15 +++ types/v2/forums_topics_actions_reply.ts | 16 ++++ 6 files changed, 161 insertions(+), 21 deletions(-) create mode 100644 types/v2/forums_topics_actions_create.ts create mode 100644 types/v2/forums_topics_actions_edit_post.ts create mode 100644 types/v2/forums_topics_actions_edit_topic.ts create mode 100644 types/v2/forums_topics_actions_reply.ts diff --git a/api/v2/forums_topics_actions.ts b/api/v2/forums_topics_actions.ts index 84afe88f..3551459e 100644 --- a/api/v2/forums_topics_actions.ts +++ b/api/v2/forums_topics_actions.ts @@ -1,5 +1,9 @@ import { request } from "../../utility/request"; -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { ForumsTopicsActionsCreateResponse } from "../../types/v2/forums_topics_actions_create"; +import { ForumsTopicsActionsReplyResponse } from "../../types/v2/forums_topics_actions_reply"; +import { ForumsTopicsActionsEditTopicResponse } from "../../types/v2/forums_topics_actions_edit_topic"; +import { ForumsTopicsActionsEditPostResponse } from "../../types/v2/forums_topics_actions_edit_post"; type params = ({ @@ -23,7 +27,7 @@ type params = ({ } | { type: 'reply'; - topic_id: number; + post_id: number; message: string; } | { type: 'edit_post'; @@ -42,14 +46,18 @@ type params = ({ type Response = - T extends 'difficulty' - ? any - : T extends 'difficulties' - ? any - : never; - - -const name = async (params: T, addons?: IDefaultParams): Promise> => { + T extends 'create' + ? ForumsTopicsActionsCreateResponse | IError + : T extends 'reply' + ? ForumsTopicsActionsReplyResponse | IError + : T extends 'edit_post' + ? ForumsTopicsActionsEditPostResponse | IError + : T extends 'edit_topic' + ? ForumsTopicsActionsEditTopicResponse | IError + : IError; + + +export const forums_topics_actions = async (params: T, addons?: IDefaultParams): Promise> => { let object: any = {}; const body: any[] = []; @@ -60,6 +68,19 @@ const name = async (params: T, addons?: IDefaultParams): Promi switch (params.type) { case 'create': + if (params.forum_id == null) { + return { error: new Error(`Specify forum id`) } as Response; + }; + + if (params.title == null) { + return { error: new Error(`Specify title`) } as Response; + }; + + if (params.message == null) { + return { error: new Error(`Specify message`) } as Response; + }; + + urls.push(`https://osu.ppy.sh/api/v2/forums/topics`); methods.push('POST'); @@ -69,7 +90,7 @@ const name = async (params: T, addons?: IDefaultParams): Promi object['body'] = params.message; - object['with_poll'] = params.enable_poll; + if (params.enable_poll != null) object['with_poll'] = params.enable_poll; if (params.enable_poll != true) { body.push(object); break; @@ -89,7 +110,16 @@ const name = async (params: T, addons?: IDefaultParams): Promi break; case 'reply': - urls.push(`https://osu.ppy.sh/api/v2/forums/topics/${params.topic_id}/reply`); + if (params.post_id == null) { + return { error: new Error(`Specify post id`) } as Response; + }; + + if (params.message == null) { + return { error: new Error(`Specify message`) } as Response; + }; + + + urls.push(`https://osu.ppy.sh/api/v2/forums/topics/${params.post_id}/reply`); methods.push('POST'); object['body'] = params.message; @@ -98,8 +128,17 @@ const name = async (params: T, addons?: IDefaultParams): Promi break; case 'edit_post': - urls.push(`https://osu.ppy.sh/api/v2//forums/posts/${params.post_id}`); - methods.push('PUT'); + if (params.post_id == null) { + return { error: new Error(`Specify post id`) } as Response; + }; + + if (params.message == null) { + return { error: new Error(`Specify message`) } as Response; + }; + + + urls.push(`https://osu.ppy.sh/api/v2/forums/posts/${params.post_id}`); + methods.push('PATCH'); object['body'] = params.message; @@ -108,7 +147,15 @@ const name = async (params: T, addons?: IDefaultParams): Promi case 'edit_topic': if (params.topic_id && (params.title != null && params.title != '')) { - // @ts DOESNT WORK + if (params.topic_id == null) { + return { error: new Error(`Specify topic id`) } as Response; + }; + + if (params.title == null) { + return { error: new Error(`Specify title`) } as Response; + }; + + urls.push(`https://osu.ppy.sh/api/v2/forums/topics/${params.topic_id}`); methods.push('PUT'); @@ -126,6 +173,15 @@ const name = async (params: T, addons?: IDefaultParams): Promi if (params.post_id && (params.message != null && params.message != '')) { + if (params.post_id == null) { + return { error: new Error(`Specify post id`) } as Response; + }; + + if (params.message == null) { + return { error: new Error(`Specify message`) } as Response; + }; + + urls.push(`https://osu.ppy.sh/api/v2/forums/posts/${params.post_id}`); methods.push('PUT'); @@ -158,11 +214,11 @@ const name = async (params: T, addons?: IDefaultParams): Promi if (params.type == 'edit_topic') { let result = fields.map((r, index) => ({ [r]: results[index] })); - return result as Response; + if (result[0].error) return result[0].error as Response; + return result[0].topic as Response; }; - return results[0] as Response; -}; - -export default name; \ No newline at end of file + if (results[0].error) return results[0].error as Response; + return results[0] as Response; +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index f0ac824f..f8f215cc 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -93,7 +93,7 @@ export const scores = { import forums_topic_details from '../api/v2/forums_topics_details'; -import forums_topics_actions from '../api/v2/forums_topics_actions'; +import { forums_topics_actions } from '../api/v2/forums_topics_actions'; export const forums = { topics: { diff --git a/types/v2/forums_topics_actions_create.ts b/types/v2/forums_topics_actions_create.ts new file mode 100644 index 00000000..028c33d3 --- /dev/null +++ b/types/v2/forums_topics_actions_create.ts @@ -0,0 +1,37 @@ +export interface ForumsTopicsActionsCreateResponse { + topic: Topic + post: Post +} + +export interface Topic { + created_at: string + deleted_at: any + first_post_id: number + forum_id: number + id: number + is_locked: boolean + last_post_id: number + post_count: number + title: string + type: string + updated_at: string + user_id: number + poll: any +} + +export interface Post { + created_at: string + deleted_at: any + edited_at: any + edited_by_id: any + forum_id: number + id: number + topic_id: number + user_id: number + body: Body +} + +export interface Body { + html: string + raw: string +} diff --git a/types/v2/forums_topics_actions_edit_post.ts b/types/v2/forums_topics_actions_edit_post.ts new file mode 100644 index 00000000..c131cf7a --- /dev/null +++ b/types/v2/forums_topics_actions_edit_post.ts @@ -0,0 +1,16 @@ +export interface ForumsTopicsActionsEditPostResponse { + created_at: string + deleted_at: any + edited_at: string + edited_by_id: number + forum_id: number + id: number + topic_id: number + user_id: number + body: Body +} + +export interface Body { + html: string + raw: string +} diff --git a/types/v2/forums_topics_actions_edit_topic.ts b/types/v2/forums_topics_actions_edit_topic.ts new file mode 100644 index 00000000..a64c318b --- /dev/null +++ b/types/v2/forums_topics_actions_edit_topic.ts @@ -0,0 +1,15 @@ +export interface ForumsTopicsActionsEditTopicResponse { + created_at: string + deleted_at: any + first_post_id: number + forum_id: number + id: number + is_locked: boolean + last_post_id: number + post_count: number + title: string + type: string + updated_at: string + user_id: number + poll: any +} \ No newline at end of file diff --git a/types/v2/forums_topics_actions_reply.ts b/types/v2/forums_topics_actions_reply.ts new file mode 100644 index 00000000..3eded607 --- /dev/null +++ b/types/v2/forums_topics_actions_reply.ts @@ -0,0 +1,16 @@ +export interface ForumsTopicsActionsReplyResponse { + created_at: string + deleted_at: any + edited_at: any + edited_by_id: any + forum_id: number + id: number + topic_id: number + user_id: number + body: Body +} + +export interface Body { + html: string + raw: string +} From 99be4fbbe40c214d3f082a3db0f007d9fca99dff Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 17:23:00 +0300 Subject: [PATCH 100/259] forums_topics_details - errors handling & types --- api/v2/forums_topics_details.ts | 23 ++++++++++--------- routes/v2.ts | 4 ++-- .../forums_topics_details.ts} | 2 +- 3 files changed, 15 insertions(+), 14 deletions(-) rename types/{forums_topic_details.ts => v2/forums_topics_details.ts} (93%) diff --git a/api/v2/forums_topics_details.ts b/api/v2/forums_topics_details.ts index 0470ebbb..739f93d3 100644 --- a/api/v2/forums_topics_details.ts +++ b/api/v2/forums_topics_details.ts @@ -1,11 +1,10 @@ import { request } from "../../utility/request"; -import { ForumPostDetails } from '../../types/forums_topic_details'; -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { ForumsTopicsDetailsResponse } from "../../types/v2/forums_topics_details"; -// FIXME: add query params -const name = async (params: { - topic_id: number +export const forums_topics_details = async (params: { + id: number start_id?: string, end_id?: string, @@ -14,7 +13,12 @@ const name = async (params: { sort?: 'id_asc' | 'id_desc', cursor_string?: string, -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { + if (params.id == null) { + return { error: new Error(`Specify topic id`) }; + }; + + const object = { start: params.start_id, end: params.end_id, @@ -26,7 +30,7 @@ const name = async (params: { }; - const data = await request(`https://osu.ppy.sh/api/v2/forums/topics/${params.topic_id}`, { + const data = await request(`https://osu.ppy.sh/api/v2/forums/topics/${params.id}`, { method: 'GET', params: object, addons, @@ -34,7 +38,4 @@ const name = async (params: { return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index f8f215cc..dade98fa 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -92,12 +92,12 @@ export const scores = { -import forums_topic_details from '../api/v2/forums_topics_details'; +import { forums_topics_details } from '../api/v2/forums_topics_details'; import { forums_topics_actions } from '../api/v2/forums_topics_actions'; export const forums = { topics: { - details: forums_topic_details, + details: forums_topics_details, actions: forums_topics_actions, }, }; diff --git a/types/forums_topic_details.ts b/types/v2/forums_topics_details.ts similarity index 93% rename from types/forums_topic_details.ts rename to types/v2/forums_topics_details.ts index d837356f..2a6dfb8d 100644 --- a/types/forums_topic_details.ts +++ b/types/v2/forums_topics_details.ts @@ -1,4 +1,4 @@ -export interface ForumPostDetails { +export interface ForumsTopicsDetailsResponse { posts: Post[] search: Search topic: Topic From 540494e270462b6abe55b0cfb94a10b8831e979d Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 17:43:26 +0300 Subject: [PATCH 101/259] matches_details - errors handling & types --- api/v2/matches_details.ts | 17 ++-- routes/v2.ts | 2 +- types/v2/matches_detaIls.ts | 150 ++++++++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+), 8 deletions(-) create mode 100644 types/v2/matches_detaIls.ts diff --git a/api/v2/matches_details.ts b/api/v2/matches_details.ts index e4e5e319..80768f53 100644 --- a/api/v2/matches_details.ts +++ b/api/v2/matches_details.ts @@ -1,17 +1,20 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { MatchesDetailsResponse } from "../../types/v2/matches_detaIls"; import { request } from "../../utility/request"; -const name = async (match_id: number, addons?: IDefaultParams) => { +export const matches_details = async (match_id: number, addons?: IDefaultParams): Promise => { + if (match_id == null) { + return { error: new Error(`Specify match id`) }; + }; + + const data = await request(`https://osu.ppy.sh/api/v2/matches/${match_id}`, { method: 'GET', addons, }); - - return data; -}; - -export default name; \ No newline at end of file + return data; +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index dade98fa..7f7bd176 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -185,7 +185,7 @@ export const me = { import matches_list from "../api/v2/matches_list"; -import matches_details from "../api/v2/matches_details"; +import { matches_details } from "../api/v2/matches_details"; export const matches = { diff --git a/types/v2/matches_detaIls.ts b/types/v2/matches_detaIls.ts new file mode 100644 index 00000000..02b5ba8d --- /dev/null +++ b/types/v2/matches_detaIls.ts @@ -0,0 +1,150 @@ +export interface MatchesDetailsResponse { + match: Match + events: Event[] + users: User[] + first_event_id: number + latest_event_id: number + current_game_id: any +} + +export interface Match { + id: number + start_time: string + end_time: string + name: string +} + +export interface Event { + id: number + detail: Detail + timestamp: string + user_id?: number + game?: Game +} + +export interface Detail { + type: string + text?: string +} + +export interface Game { + beatmap_id: number + id: number + start_time: string + end_time: string + mode: string + mode_int: number + scoring_type: string + team_type: string + mods: string[] + beatmap?: Beatmap + scores: Score[] +} + +export interface Beatmap { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + beatmapset: Beatmapset +} + +export interface Beatmapset { + artist: string + artist_unicode: string + covers: Covers + creator: string + favourite_count: number + hype: any + id: number + nsfw: boolean + offset: number + play_count: number + preview_url: string + source: string + spotlight: boolean + status: string + title: string + title_unicode: string + track_id: any + user_id: number + video: boolean +} + +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} + +export interface Score { + accuracy: number + best_id: any + created_at: string + id: any + max_combo: number + mode: string + mode_int: number + mods: string[] + passed: boolean + perfect: number + pp: any + rank: string + replay: boolean + score: number + statistics: Statistics + type: string + user_id: number + current_user_attributes: CurrentUserAttributes + match: Match2 +} + +export interface Statistics { + count_100: number + count_300: number + count_50: number + count_geki: number + count_katu: number + count_miss: number +} + +export interface CurrentUserAttributes { + pin: any +} + +export interface Match2 { + slot: number + team: string + pass: boolean +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour?: string + username: string + country: Country +} + +export interface Country { + code: string + name: string +} From 9cee00fcc0c80219e51f5cedc30df4e4b94c98e7 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 18:12:18 +0300 Subject: [PATCH 102/259] matches_list - errors handling & types --- api/v2/matches_list.ts | 12 +++++------- routes/v2.ts | 2 +- types/v2/matches_list.ts | 22 ++++++++++++++++++++++ 3 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 types/v2/matches_list.ts diff --git a/api/v2/matches_list.ts b/api/v2/matches_list.ts index 814197fc..4d6671c9 100644 --- a/api/v2/matches_list.ts +++ b/api/v2/matches_list.ts @@ -1,16 +1,17 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { MatchesListResponse } from "../../types/v2/matches_list"; import { request } from "../../utility/request"; -const name = async (params: { +export const matches_list = async (params: { limit: number; sort: 'id_desc' | 'id_asc', /** * Use cursor.match_id */ after_id: number; -}, addons?: IDefaultParams) => { +}, addons?: IDefaultParams): Promise => { const object = { limit: params.limit, sort: params.sort, @@ -26,7 +27,4 @@ const name = async (params: { return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 7f7bd176..2bd1fbba 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -184,7 +184,7 @@ export const me = { -import matches_list from "../api/v2/matches_list"; +import { matches_list } from "../api/v2/matches_list"; import { matches_details } from "../api/v2/matches_details"; diff --git a/types/v2/matches_list.ts b/types/v2/matches_list.ts new file mode 100644 index 00000000..4c1003ed --- /dev/null +++ b/types/v2/matches_list.ts @@ -0,0 +1,22 @@ +export interface MatchesListResponse { + matches: Match[] + params: Params + cursor: Cursor + cursor_string: string +} + +export interface Match { + id: number + start_time: string + end_time: string + name: string +} + +export interface Params { + limit: number + sort: string +} + +export interface Cursor { + match_id: number +} From af2aaa0f72038dc074ae6f90ddcb9411473679ae Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 18:20:17 +0300 Subject: [PATCH 103/259] me_details - errors handling & types --- api/v2/me_details.ts | 16 ++- routes/v2.ts | 2 +- types/v2/me_details.ts | 317 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 328 insertions(+), 7 deletions(-) create mode 100644 types/v2/me_details.ts diff --git a/api/v2/me_details.ts b/api/v2/me_details.ts index fddb940c..488c0aa0 100644 --- a/api/v2/me_details.ts +++ b/api/v2/me_details.ts @@ -1,9 +1,16 @@ -import { IDefaultParams, Modes_names } from "../../types"; +import { credentials } from "../../utility/auth"; +import { IDefaultParams, IError, Modes_names } from "../../types"; +import { MeDetailsResponse } from "../../types/v2/me_details"; import { request } from "../../utility/request"; -const name = async (addons?: IDefaultParams & { mode: Modes_names }) => { +export const me_details = async (addons?: IDefaultParams & { mode: Modes_names }): Promise => { + if (credentials.method != 'lazer') { + return { error: new Error(`Login via lazer to use this endpoint`) }; + }; + + let url = 'https://osu.ppy.sh/api/v2/me'; if (addons?.mode) url += `/${addons.mode}`; @@ -13,7 +20,4 @@ const name = async (addons?: IDefaultParams & { mode: Modes_names }) => { }); return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 2bd1fbba..2738ea55 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -171,7 +171,7 @@ export const wiki = { -import me_details from "../api/v2/me_details"; +import { me_details } from "../api/v2/me_details"; import me_friends from "../api/v2/me_friends"; import me_download_quota from "../api/v2/me_download_quota"; diff --git a/types/v2/me_details.ts b/types/v2/me_details.ts new file mode 100644 index 00000000..41d021eb --- /dev/null +++ b/types/v2/me_details.ts @@ -0,0 +1,317 @@ +export interface MeDetailsResponse { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: any + pm_friends_only: boolean + profile_colour: any + username: string + cover_url: string + discord: string + has_supported: boolean + interests: string + join_date: string + location: string + max_blocks: number + max_friends: number + occupation: any + playmode: string + playstyle: string[] + post_count: number + profile_order: string[] + title: any + title_url: any + twitter: string + website: string + country: Country + cover: Cover + is_restricted: boolean + kudosu: Kudosu + account_history: any[] + active_tournament_banner: any + active_tournament_banners: any[] + badges: Badge[] + beatmap_playcounts_count: number + comments_count: number + favourite_beatmapset_count: number + follower_count: number + graveyard_beatmapset_count: number + groups: any[] + guest_beatmapset_count: number + loved_beatmapset_count: number + mapping_follower_count: number + monthly_playcounts: MonthlyPlaycount[] + nominated_beatmapset_count: number + page: Page + pending_beatmapset_count: number + previous_usernames: any[] + rank_highest: RankHighest + ranked_beatmapset_count: number + replays_watched_counts: ReplaysWatchedCount[] + scores_best_count: number + scores_first_count: number + scores_pinned_count: number + scores_recent_count: number + session_verified: boolean + statistics: Statistics + statistics_rulesets: StatisticsRulesets + support_level: number + user_achievements: UserAchievement[] + rank_history: RankHistory + rankHistory: RankHistory2 + ranked_and_approved_beatmapset_count: number + unranked_beatmapset_count: number +} + +export interface Country { + code: string + name: string +} + +export interface Cover { + custom_url: string + url: string + id: any +} + +export interface Kudosu { + available: number + total: number +} + +export interface Badge { + awarded_at: string + description: string + "image@2x_url": string + image_url: string + url: string +} + +export interface MonthlyPlaycount { + start_date: string + count: number +} + +export interface Page { + html: string + raw: string +} + +export interface RankHighest { + rank: number + updated_at: string +} + +export interface ReplaysWatchedCount { + start_date: string + count: number +} + +export interface Statistics { + count_100: number + count_300: number + count_50: number + count_miss: number + level: Level + global_rank: number + global_rank_exp: any + pp: number + pp_exp: number + ranked_score: number + hit_accuracy: number + play_count: number + play_time: number + total_score: number + total_hits: number + maximum_combo: number + replays_watched_by_others: number + is_ranked: boolean + grade_counts: GradeCounts + country_rank: number + rank: Rank +} + +export interface Level { + current: number + progress: number +} + +export interface GradeCounts { + ss: number + ssh: number + s: number + sh: number + a: number +} + +export interface Rank { + country: number +} + +export interface StatisticsRulesets { + osu: Osu + taiko: Taiko + fruits: Fruits + mania: Mania +} + +export interface Osu { + count_100: number + count_300: number + count_50: number + count_miss: number + level: Level2 + global_rank: number + global_rank_exp: any + pp: number + pp_exp: number + ranked_score: number + hit_accuracy: number + play_count: number + play_time: number + total_score: number + total_hits: number + maximum_combo: number + replays_watched_by_others: number + is_ranked: boolean + grade_counts: GradeCounts2 +} + +export interface Level2 { + current: number + progress: number +} + +export interface GradeCounts2 { + ss: number + ssh: number + s: number + sh: number + a: number +} + +export interface Taiko { + count_100: number + count_300: number + count_50: number + count_miss: number + level: Level3 + global_rank: any + global_rank_exp: any + pp: number + pp_exp: number + ranked_score: number + hit_accuracy: number + play_count: number + play_time: number + total_score: number + total_hits: number + maximum_combo: number + replays_watched_by_others: number + is_ranked: boolean + grade_counts: GradeCounts3 +} + +export interface Level3 { + current: number + progress: number +} + +export interface GradeCounts3 { + ss: number + ssh: number + s: number + sh: number + a: number +} + +export interface Fruits { + count_100: number + count_300: number + count_50: number + count_miss: number + level: Level4 + global_rank: any + global_rank_exp: any + pp: number + pp_exp: number + ranked_score: number + hit_accuracy: number + play_count: number + play_time: number + total_score: number + total_hits: number + maximum_combo: number + replays_watched_by_others: number + is_ranked: boolean + grade_counts: GradeCounts4 +} + +export interface Level4 { + current: number + progress: number +} + +export interface GradeCounts4 { + ss: number + ssh: number + s: number + sh: number + a: number +} + +export interface Mania { + count_100: number + count_300: number + count_50: number + count_miss: number + level: Level5 + global_rank: any + global_rank_exp: any + pp: number + pp_exp: number + ranked_score: number + hit_accuracy: number + play_count: number + play_time: number + total_score: number + total_hits: number + maximum_combo: number + replays_watched_by_others: number + is_ranked: boolean + grade_counts: GradeCounts5 +} + +export interface Level5 { + current: number + progress: number +} + +export interface GradeCounts5 { + ss: number + ssh: number + s: number + sh: number + a: number +} + +export interface UserAchievement { + achieved_at: string + achievement_id: number +} + +export interface RankHistory { + mode: string + data: number[] +} + +export interface RankHistory2 { + mode: string + data: number[] +} From d1a11bf1119eb52be59fba3db009a9664495358d Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 18:20:24 +0300 Subject: [PATCH 104/259] me_download_quota - errors handling & types --- api/v2/me_download_quota.ts | 15 ++++++++++----- routes/v2.ts | 2 +- types/v2/me_download_quota.ts | 3 +++ 3 files changed, 14 insertions(+), 6 deletions(-) create mode 100644 types/v2/me_download_quota.ts diff --git a/api/v2/me_download_quota.ts b/api/v2/me_download_quota.ts index a0ef864c..29e99e67 100644 --- a/api/v2/me_download_quota.ts +++ b/api/v2/me_download_quota.ts @@ -1,14 +1,19 @@ +import { credentials } from "../../utility/auth"; +import { IError } from "../../types"; +import { MedownloadquotaResponse } from "../../types/v2/me_download_quota"; import { request } from "../../utility/request"; -const name = async () => { +export const me_download_quota = async (): Promise => { + if (credentials.method != 'lazer') { + return { error: new Error(`Login via lazer to use this endpoint`) }; + }; + + const data = await request(`https://osu.ppy.sh/api/v2/me/download-quota-check`, { method: 'GET', }); return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 2738ea55..9d963efd 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -173,7 +173,7 @@ export const wiki = { import { me_details } from "../api/v2/me_details"; import me_friends from "../api/v2/me_friends"; -import me_download_quota from "../api/v2/me_download_quota"; +import { me_download_quota } from "../api/v2/me_download_quota"; export const me = { diff --git a/types/v2/me_download_quota.ts b/types/v2/me_download_quota.ts new file mode 100644 index 00000000..7b359884 --- /dev/null +++ b/types/v2/me_download_quota.ts @@ -0,0 +1,3 @@ +export interface MedownloadquotaResponse { + quota_used: number +} From 23b7b4c843e7f221313914d4d4f6e409c84b4686 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 18:22:18 +0300 Subject: [PATCH 105/259] me_friends - errors handling & types --- api/v2/me_friends.ts | 17 +++++---- routes/v2.ts | 2 +- types/v2/me_friends.ts | 78 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 7 deletions(-) create mode 100644 types/v2/me_friends.ts diff --git a/api/v2/me_friends.ts b/api/v2/me_friends.ts index 3f6a13e6..da24d9d9 100644 --- a/api/v2/me_friends.ts +++ b/api/v2/me_friends.ts @@ -1,16 +1,21 @@ -import { IDefaultParams } from "../../types"; +import { credentials } from "../../utility/auth"; +import { IDefaultParams, IError } from "../../types"; import { request } from "../../utility/request"; +import { MeFriendsResponse } from "../../types/v2/me_friends"; -const name = async (addons?: IDefaultParams) => { +export const me_friends = async (addons?: IDefaultParams): Promise => { + if (credentials.method != 'lazer') { + return { error: new Error(`Login via lazer to use this endpoint`) }; + }; + + const data = await request(`https://osu.ppy.sh/api/v2/friends`, { method: 'GET', addons, }); - return data; -}; - -export default name; \ No newline at end of file + return data; +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 9d963efd..4f7404f8 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -172,7 +172,7 @@ export const wiki = { import { me_details } from "../api/v2/me_details"; -import me_friends from "../api/v2/me_friends"; +import { me_friends } from "../api/v2/me_friends"; import { me_download_quota } from "../api/v2/me_download_quota"; diff --git a/types/v2/me_friends.ts b/types/v2/me_friends.ts new file mode 100644 index 00000000..bb86c75c --- /dev/null +++ b/types/v2/me_friends.ts @@ -0,0 +1,78 @@ +export interface MeFriendsResponse { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour?: string + username: string + country: Country + cover: Cover + groups: Group[] + statistics: Statistics + support_level: number +} + +export interface Country { + code: string + name: string +} + +export interface Cover { + custom_url?: string + url: string + id?: string +} + +export interface Group { + colour?: string + has_listing: boolean + has_playmodes: boolean + id: number + identifier: string + is_probationary: boolean + name: string + short_name: string + playmodes?: string[] +} + +export interface Statistics { + count_100: number + count_300: number + count_50: number + count_miss: number + level: Level + global_rank?: number + global_rank_exp: any + pp: number + pp_exp: number + ranked_score: number + hit_accuracy: number + play_count: number + play_time: number + total_score: number + total_hits: number + maximum_combo: number + replays_watched_by_others: number + is_ranked: boolean + grade_counts: GradeCounts +} + +export interface Level { + current: number + progress: number +} + +export interface GradeCounts { + ss: number + ssh: number + s: number + sh: number + a: number +} From 5e63d976d308fa23b7fcfcd95a36d3046302b2cd Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 18:24:54 +0300 Subject: [PATCH 106/259] news_details - errors handling & types --- api/v2/news_details.ts | 18 +++++++++++------- routes/v2.ts | 2 +- types/v2/news_details.ts | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 types/v2/news_details.ts diff --git a/api/v2/news_details.ts b/api/v2/news_details.ts index 8ba8714f..73a88e54 100644 --- a/api/v2/news_details.ts +++ b/api/v2/news_details.ts @@ -1,20 +1,24 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { NewsDetailsResponse } from "../../types/v2/news_details"; import { request } from "../../utility/request"; -const name = async (params: { +export const news_details = async (params: { news_id: string; key?: 'id' | null; -}, addons?: IDefaultParams) => { +}, addons?: IDefaultParams): Promise => { + if (params.news_id == null) { + return { error: new Error(`Specify news id`) }; + }; + + const data = await request(`https://osu.ppy.sh/api/v2/news/${params.news_id}`, { method: 'GET', params: { key: params?.key }, addons, }); - return data; -}; - -export default name; \ No newline at end of file + return data; +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 4f7404f8..eb4111b3 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -122,7 +122,7 @@ export const assets = { import news_list from "../api/v2/news_list"; -import news_details from "../api/v2/news_details"; +import { news_details } from "../api/v2/news_details"; export const news = { diff --git a/types/v2/news_details.ts b/types/v2/news_details.ts new file mode 100644 index 00000000..47874534 --- /dev/null +++ b/types/v2/news_details.ts @@ -0,0 +1,39 @@ +export interface NewsDetailsResponse { + id: number + author: string + edit_url: string + first_image: string + published_at: string + updated_at: string + slug: string + title: string + content: string + navigation: Navigation +} + +export interface Navigation { + newer: Newer + older: Older +} + +export interface Newer { + id: number + author: string + edit_url: string + first_image: string + published_at: string + updated_at: string + slug: string + title: string +} + +export interface Older { + id: number + author: string + edit_url: string + first_image: string + published_at: string + updated_at: string + slug: string + title: string +} From 2c980d730fa9bf2a7e0ff736f7e9befa8b4b92a9 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 18:28:18 +0300 Subject: [PATCH 107/259] news_list - errors handling & types --- api/v2/news_list.ts | 26 ++++++++++++------------ routes/v2.ts | 2 +- types/v2/news_list.ts | 47 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 14 deletions(-) create mode 100644 types/v2/news_list.ts diff --git a/api/v2/news_list.ts b/api/v2/news_list.ts index 1c6edab4..9237e802 100644 --- a/api/v2/news_list.ts +++ b/api/v2/news_list.ts @@ -1,26 +1,26 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { NewsListResponse } from "../../types/v2/news_list"; import { request } from "../../utility/request"; -const name = async (params: { +export const news_list = async (params: { from_year?: string; - limit?: string; cursor_string?: string; -} = {}, addons?: IDefaultParams) => { +} = {}, addons?: IDefaultParams): Promise => { + const object: any = {}; + if (params.from_year != null) object.year = params.from_year; + if (params.limit != null) object.limit = params.limit; + if (params.cursor_string != null) object.cursor_string = params.cursor_string; + + const data = await request(`https://osu.ppy.sh/api/v2/news`, { method: 'GET', - params: { - year: params.from_year, - limit: params.limit, - cursor_string: params.cursor_string, - }, + params: object, addons, }); - return data; -}; - -export default name; \ No newline at end of file + return data; +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index eb4111b3..c213cd0d 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -121,7 +121,7 @@ export const assets = { -import news_list from "../api/v2/news_list"; +import { news_list } from "../api/v2/news_list"; import { news_details } from "../api/v2/news_details"; diff --git a/types/v2/news_list.ts b/types/v2/news_list.ts new file mode 100644 index 00000000..29fc50fc --- /dev/null +++ b/types/v2/news_list.ts @@ -0,0 +1,47 @@ +export interface NewsListResponse { + news_posts: NewsPost[] + news_sidebar: NewsSidebar + search: Search + cursor: Cursor + cursor_string: string +} + +export interface NewsPost { + id: number + author: string + edit_url: string + first_image: string + published_at: string + updated_at: string + slug: string + title: string + preview: string +} + +export interface NewsSidebar { + current_year: number + news_posts: NewsPost2[] + years: number[] +} + +export interface NewsPost2 { + id: number + author: string + edit_url: string + first_image: string + published_at: string + updated_at: string + slug: string + title: string +} + +export interface Search { + limit: number + sort: string + year: any +} + +export interface Cursor { + published_at: string + id: number +} From 50b1952a6993e9543973922efb48ef1ece79a81f Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 18:35:09 +0300 Subject: [PATCH 108/259] notification_actions - errors handling & types --- api/v2/notification_actions.ts | 24 +++++++++--------------- routes/v2.ts | 2 +- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/api/v2/notification_actions.ts b/api/v2/notification_actions.ts index 9ad05c57..d4f1d863 100644 --- a/api/v2/notification_actions.ts +++ b/api/v2/notification_actions.ts @@ -1,11 +1,11 @@ import { request } from "../../utility/request"; -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; type params = ({ type: 'mark_as_readed'; - ids: number[]; + // ids: number[]; identities?: { category: string; @@ -24,11 +24,11 @@ type params = ({ type Response = T extends 'mark_as_readed' - ? any - : never; + ? "" + : IError; -const name = async (params: T, addons?: IDefaultParams): Promise => { +export const notification_actions = async (params: T, addons?: IDefaultParams): Promise => { const object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; let method = 'GET'; @@ -39,20 +39,17 @@ const name = async (params: T, addons?: IDefaultParams): Promi url += '/notifications/mark-read'; method = 'POST'; + if (params.notifications == null && params.identities == null) { + return { error: new Error(`Missing on of parameters`) } as Response; + }; // params.ids.forEach((r, index) => object[`identities[${index}][id]`] = r); if (Array.isArray(params.notifications)) { - // const formData = postData(params.notifications); - // object.push(formData); - object['notifications'] = params.notifications; }; if (Array.isArray(params.identities)) { - // const formData = postData(params.identities); - // object.push(formData); - object['identities'] = params.identities; }; break; @@ -67,7 +64,4 @@ const name = async (params: T, addons?: IDefaultParams): Promi return data as Response; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index c213cd0d..d5d1b132 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -134,7 +134,7 @@ export const news = { import notifications_list from '../api/v2/notifications_list'; -import notification_actions from '../api/v2/notification_actions'; +import { notification_actions } from '../api/v2/notification_actions'; export const notifications = { From 8a254dfae9af38bc5483d5eba74cb5127534dd20 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 18:35:23 +0300 Subject: [PATCH 109/259] notifications_list - errors handling & types --- api/v2/notifications_list.ts | 19 +++++++------ routes/v2.ts | 2 +- types/v2/notifications_list.ts | 50 ++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 types/v2/notifications_list.ts diff --git a/api/v2/notifications_list.ts b/api/v2/notifications_list.ts index eeabf4c1..c6004500 100644 --- a/api/v2/notifications_list.ts +++ b/api/v2/notifications_list.ts @@ -1,23 +1,26 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { NotificationsListResponse } from "../../types/v2/notifications_list"; import { request } from "../../utility/request"; -const name = async (params: { +export const notifications_list = async (params: { max_id: string; unreaded_only: boolean; -}, addons?: IDefaultParams) => { +}, addons?: IDefaultParams): Promise => { + const object: any = {}; + if (params.max_id != null) object.max_id = params.max_id; + + const data = await request(`https://osu.ppy.sh/api/v2/notifications`, { method: 'GET', - params: { max_id: params.max_id }, + params: object, addons, }); + if (params.unreaded_only == true && !('error' in data)) data.notifications = data.notifications.filter((r: any) => r.is_read == false); return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index d5d1b132..41fe6478 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -133,7 +133,7 @@ export const news = { -import notifications_list from '../api/v2/notifications_list'; +import { notifications_list } from '../api/v2/notifications_list'; import { notification_actions } from '../api/v2/notification_actions'; diff --git a/types/v2/notifications_list.ts b/types/v2/notifications_list.ts new file mode 100644 index 00000000..ae42e061 --- /dev/null +++ b/types/v2/notifications_list.ts @@ -0,0 +1,50 @@ +export interface NotificationsListResponse { + notifications: Notification[] + stacks: Stack[] + timestamp: string + types: Type[] + notification_endpoint: string +} + +export interface Notification { + id: number + name: string + created_at: string + object_type: string + object_id: number + source_user_id: number + is_read: boolean + details: Details +} + +export interface Details { + title: string + username: string + cover_url: string + beatmapset_id: number + title_unicode: string +} + +export interface Stack { + category: string + cursor?: Cursor + name: string + object_type: string + object_id: number + total: number +} + +export interface Cursor { + id: number +} + +export interface Type { + cursor: Cursor2 + name?: string + total: number +} + +export interface Cursor2 { + id: number + type?: string +} From bf1f94c941eb772f538391de6703d36d8b47afa9 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 18:49:39 +0300 Subject: [PATCH 110/259] ranking_list - errors handling & types --- api/v2/ranking_list.ts | 79 ++++++------- routes/v2.ts | 2 +- types/v2/ranking_list_charts.ts | 169 +++++++++++++++++++++++++++ types/v2/ranking_list_country.ts | 23 ++++ types/v2/ranking_list_kudosu.ts | 21 ++++ types/v2/ranking_list_performance.ts | 74 ++++++++++++ types/v2/ranking_list_score.ts | 74 ++++++++++++ 7 files changed, 398 insertions(+), 44 deletions(-) create mode 100644 types/v2/ranking_list_charts.ts create mode 100644 types/v2/ranking_list_country.ts create mode 100644 types/v2/ranking_list_kudosu.ts create mode 100644 types/v2/ranking_list_performance.ts create mode 100644 types/v2/ranking_list_score.ts diff --git a/api/v2/ranking_list.ts b/api/v2/ranking_list.ts index 5df08687..66eadc80 100644 --- a/api/v2/ranking_list.ts +++ b/api/v2/ranking_list.ts @@ -1,5 +1,10 @@ import { request } from "../../utility/request"; -import { IDefaultParams, Modes_names } from "../../types"; +import { IDefaultParams, IError, Modes_names } from "../../types"; +import { RankingListChartsResponse } from "../../types/v2/ranking_list_charts"; +import { RankingListCountryResponse } from "../../types/v2/ranking_list_country"; +import { RankingListPerformanceResponse } from "../../types/v2/ranking_list_performance"; +import { RankingListKudosuResponse } from "../../types/v2/ranking_list_kudosu"; +import { RankingListScoreResponse } from "../../types/v2/ranking_list_score"; type params = { @@ -36,28 +41,23 @@ type params = { type Response = T extends 'charts' - ? any + ? RankingListChartsResponse | IError : T extends 'country' - ? any + ? RankingListCountryResponse | IError : T extends 'performance' - ? any + ? RankingListPerformanceResponse | IError : T extends 'score' - ? any + ? RankingListScoreResponse | IError : T extends 'kudosu' - ? any - : never; + ? RankingListKudosuResponse | IError + : IError; -const name = async (params: T, addons?: IDefaultParams): Promise | { error: string }> => { - if (params.type == null) - return { - error: 'Ranking type not specified', - }; - +export const ranking_list = async (params: T, addons?: IDefaultParams): Promise> => { if (params.type != 'kudosu' && params.mode == null) return { - error: 'Gamemode not specified', - };; + error: new Error('Gamemode not specified'), + } as Response; let object: any = {}; @@ -68,47 +68,44 @@ const name = async (params: T, addons?: IDefaultParams): Promi case 'charts': url += `/rankings/${params.mode}/${params.type}`; - object = { - 'cursor[page]': params.page, - filter: params.filter, - spotlight: params.spotlight_id, - }; + if (params.page != null) object['cursor[page]'] = params.page; + if (params.filter != null) object.filter = params.filter; + if (params.spotlight_id != null) object.spotlight = params.spotlight_id; + break; case 'country': url += `/rankings/${params.mode}/${params.type}`; - object = { - 'cursor[page]': params.page, - filter: params.filter, - }; + if (params.page != null) object['cursor[page]'] = params.page; + if (params.filter != null) object.filter = params.filter; break; case 'performance': url += `/rankings/${params.mode}/${params.type}`; - object = { - 'cursor[page]': params.page, - filter: params.filter, - country: params.country_code, - variant: params.variant, - }; + if (params.page != null) object['cursor[page]'] = params.page; + if (params.filter != null) object.filter = params.filter; + if (params.country_code != null) object.country = params.country_code; + if (params.variant != null) object.variant = params.variant; + break; case 'score': url += `/rankings/${params.mode}/${params.type}`; - object = { - 'cursor[page]': params.page, - filter: params.filter, - }; + if (params.page != null) object['cursor[page]'] = params.page; + if (params.filter != null) object.filter = params.filter; break; case 'kudosu': url += `/rankings/kudosu`; - object.page = params.page; + if (params.page != null) object.page = params.page; break; + + default: + return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; }; @@ -119,15 +116,11 @@ const name = async (params: T, addons?: IDefaultParams): Promi }); - if ('error' in data) - return { - error: 'Api returned error, check your request parameters' - }; + if ('error' in data) { + return data as Response; + }; if (params.type == 'kudosu') return data.ranking as Response; return data as Response; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 41fe6478..59e31a79 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -144,7 +144,7 @@ export const notifications = { -import ranking_list from "../api/v2/ranking_list"; +import { ranking_list } from "../api/v2/ranking_list"; export const ranking = { diff --git a/types/v2/ranking_list_charts.ts b/types/v2/ranking_list_charts.ts new file mode 100644 index 00000000..9534cd3e --- /dev/null +++ b/types/v2/ranking_list_charts.ts @@ -0,0 +1,169 @@ +export interface RankingListChartsResponse { + beatmapsets: Beatmapset[] + ranking: Ranking[] + spotlight: Spotlight +} + +export interface Beatmapset { + artist: string + artist_unicode: string + covers: Covers + creator: string + favourite_count: number + hype: any + id: number + nsfw: boolean + offset: number + play_count: number + preview_url: string + source: string + spotlight: boolean + status: string + title: string + title_unicode: string + track_id?: number + user_id: number + video: boolean + bpm: number + can_be_hyped: boolean + deleted_at: any + discussion_enabled: boolean + discussion_locked: boolean + is_scoreable: boolean + last_updated: string + legacy_thread_url: string + nominations_summary: NominationsSummary + ranked: number + ranked_date: string + storyboard: boolean + submitted_date: string + tags: string + availability: Availability + beatmaps: Beatmap[] +} + +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} + +export interface NominationsSummary { + current: number + required: number +} + +export interface Availability { + download_disabled: boolean + more_information: any +} + +export interface Beatmap { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + accuracy: number + ar: number + bpm: number + convert: boolean + count_circles: number + count_sliders: number + count_spinners: number + cs: number + deleted_at: any + drain: number + hit_length: number + is_scoreable: boolean + last_updated: string + mode_int: number + passcount: number + playcount: number + ranked: number + url: string + checksum: string +} + +export interface Ranking { + count_100: number + count_300: number + count_50: number + count_miss: number + level: Level + global_rank: any + global_rank_exp: any + pp: any + pp_exp: number + ranked_score: number + hit_accuracy: number + play_count: number + play_time: any + total_score: number + total_hits: number + maximum_combo: number + replays_watched_by_others: number + is_ranked: boolean + grade_counts: GradeCounts + user: User +} + +export interface Level { + current: number + progress: number +} + +export interface GradeCounts { + ss: number + ssh: number + s: number + sh: number + a: number +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour?: string + username: string + country: Country + cover: Cover +} + +export interface Country { + code: string + name: string +} + +export interface Cover { + custom_url?: string + url: string + id?: string +} + +export interface Spotlight { + end_date: string + id: number + mode_specific: boolean + name: string + start_date: string + type: string + participant_count: number +} diff --git a/types/v2/ranking_list_country.ts b/types/v2/ranking_list_country.ts new file mode 100644 index 00000000..57f7b615 --- /dev/null +++ b/types/v2/ranking_list_country.ts @@ -0,0 +1,23 @@ +export interface RankingListCountryResponse { + cursor: Cursor + ranking: Ranking[] + total: number +} + +export interface Cursor { + page: number +} + +export interface Ranking { + code: string + active_users: number + play_count: number + ranked_score: number + performance: number + country: Country +} + +export interface Country { + code: string + name: string +} diff --git a/types/v2/ranking_list_kudosu.ts b/types/v2/ranking_list_kudosu.ts new file mode 100644 index 00000000..3d62e17d --- /dev/null +++ b/types/v2/ranking_list_kudosu.ts @@ -0,0 +1,21 @@ +export interface RankingListKudosuResponse { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour?: string + username: string + kudosu: Kudosu +} + +export interface Kudosu { + available: number + total: number +} diff --git a/types/v2/ranking_list_performance.ts b/types/v2/ranking_list_performance.ts new file mode 100644 index 00000000..5b4a46e3 --- /dev/null +++ b/types/v2/ranking_list_performance.ts @@ -0,0 +1,74 @@ +export interface RankingListPerformanceResponse { + cursor: Cursor + ranking: Ranking[] + total: number +} + +export interface Cursor { + page: number +} + +export interface Ranking { + count_100: number + count_300: number + count_50: number + count_miss: number + level: Level + global_rank: number + global_rank_exp: any + pp: number + pp_exp: number + ranked_score: number + hit_accuracy: number + play_count: number + play_time: number + total_score: number + total_hits: number + maximum_combo: number + replays_watched_by_others: number + is_ranked: boolean + grade_counts: GradeCounts + user: User +} + +export interface Level { + current: number + progress: number +} + +export interface GradeCounts { + ss: number + ssh: number + s: number + sh: number + a: number +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour: any + username: string + country: Country + cover: Cover +} + +export interface Country { + code: string + name: string +} + +export interface Cover { + custom_url?: string + url: string + id?: string +} diff --git a/types/v2/ranking_list_score.ts b/types/v2/ranking_list_score.ts new file mode 100644 index 00000000..55ff7387 --- /dev/null +++ b/types/v2/ranking_list_score.ts @@ -0,0 +1,74 @@ +export interface RankingListScoreResponse { + cursor: Cursor + ranking: Ranking[] + total: number +} + +export interface Cursor { + page: number +} + +export interface Ranking { + count_100: number + count_300: number + count_50: number + count_miss: number + level: Level + global_rank: number + global_rank_exp: any + pp: number + pp_exp: number + ranked_score: number + hit_accuracy: number + play_count: number + play_time: number + total_score: number + total_hits: number + maximum_combo: number + replays_watched_by_others: number + is_ranked: boolean + grade_counts: GradeCounts + user: User +} + +export interface Level { + current: number + progress: number +} + +export interface GradeCounts { + ss: number + ssh: number + s: number + sh: number + a: number +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour?: string + username: string + country: Country + cover: Cover +} + +export interface Country { + code: string + name: string +} + +export interface Cover { + custom_url?: string + url: string + id?: string +} From 5518ff66f14126a4e70f83e1e441b7d43058aeb0 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 18:53:33 +0300 Subject: [PATCH 111/259] rooms_details - errors handling & types --- api/v2/rooms_details.ts | 20 +++--- routes/v2.ts | 2 +- types/v2/rooms_details.ts | 137 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+), 11 deletions(-) create mode 100644 types/v2/rooms_details.ts diff --git a/api/v2/rooms_details.ts b/api/v2/rooms_details.ts index 5fa908fd..b7f77071 100644 --- a/api/v2/rooms_details.ts +++ b/api/v2/rooms_details.ts @@ -1,20 +1,20 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { RoomsDetailsResponse } from "../../types/v2/rooms_details"; import { request } from "../../utility/request"; -const name = async (params: { - id: number | 'latest'; -}, addons?: IDefaultParams) => { - const data = await request(`https://osu.ppy.sh/api/v2/rooms/${params.id}`, { +export const rooms_details = async (id: number | 'latest', addons?: IDefaultParams): Promise => { + if (id == null) { + return { error: new Error(`Specify room id`) }; + }; + + + const data = await request(`https://osu.ppy.sh/api/v2/rooms/${id}`, { method: 'GET', - params, addons, }); return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 59e31a79..c330ed71 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -229,7 +229,7 @@ export const session = { import rooms_list from "../api/v2/rooms_list"; -import rooms_details from "../api/v2/rooms_details"; +import { rooms_details } from "../api/v2/rooms_details"; import rooms_leaderboard from "../api/v2/rooms_leaderboard"; import rooms_scores from "../api/v2/rooms_scores"; diff --git a/types/v2/rooms_details.ts b/types/v2/rooms_details.ts new file mode 100644 index 00000000..38271e27 --- /dev/null +++ b/types/v2/rooms_details.ts @@ -0,0 +1,137 @@ +export interface RoomsDetailsResponse { + id: number + name: string + category: string + type: string + user_id: number + starts_at: string + ends_at: any + max_attempts: any + participant_count: number + channel_id: number + active: boolean + has_password: boolean + queue_mode: string + auto_skip: boolean + current_user_score: CurrentUserScore + host: Host + playlist: Playlist[] + recent_participants: RecentParticipant[] +} + +export interface CurrentUserScore { + accuracy: number + attempts: number + completed: number + pp: number + room_id: number + total_score: number + user_id: number + playlist_item_attempts: any[] +} + +export interface Host { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour: any + username: string + country: Country +} + +export interface Country { + code: string + name: string +} + +export interface Playlist { + id: number + room_id: number + beatmap_id: number + ruleset_id: number + allowed_mods: any[] + required_mods: RequiredMod[] + expired: boolean + owner_id: number + playlist_order?: number + played_at?: string + beatmap: Beatmap +} + +export interface RequiredMod { + acronym: string + settings: Settings +} + +export interface Settings { } + +export interface Beatmap { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + beatmapset: Beatmapset + checksum: string + max_combo: number +} + +export interface Beatmapset { + artist: string + artist_unicode: string + covers: Covers + creator: string + favourite_count: number + hype: any + id: number + nsfw: boolean + offset: number + play_count: number + preview_url: string + source: string + spotlight: boolean + status: string + title: string + title_unicode: string + track_id?: number + user_id: number + video: boolean +} + +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} + +export interface RecentParticipant { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour: any + username: string +} From 5c64e121c2ee8b46637a3d44b17d29c461ea7c27 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 18:55:58 +0300 Subject: [PATCH 112/259] rooms_leaderboard - errors handling & types --- api/v2/rooms_leaderboard.ts | 20 +++++++++++-------- routes/v2.ts | 2 +- types/v2/rooms_leaderboard.ts | 37 +++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 9 deletions(-) create mode 100644 types/v2/rooms_leaderboard.ts diff --git a/api/v2/rooms_leaderboard.ts b/api/v2/rooms_leaderboard.ts index 2f5fd115..4f15e7aa 100644 --- a/api/v2/rooms_leaderboard.ts +++ b/api/v2/rooms_leaderboard.ts @@ -1,20 +1,24 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { RoomsLeaderboardResponse } from "../../types/v2/rooms_leaderboard"; import { request } from "../../utility/request"; -const name = async (params: { +export const rooms_leaderboard = async (params: { id: number; limit?: number; -}, addons?: IDefaultParams) => { +}, addons?: IDefaultParams): Promise => { + if (params.id == null) { + return { error: new Error(`Specify room id`) }; + }; + + const data = await request(`https://osu.ppy.sh/api/v2/rooms/${params.id}/leaderboard`, { method: 'GET', - params, + params: { limit: params.limit }, addons, }); - return data; -}; - -export default name; \ No newline at end of file + return data; +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index c330ed71..52e7918d 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -230,7 +230,7 @@ export const session = { import rooms_list from "../api/v2/rooms_list"; import { rooms_details } from "../api/v2/rooms_details"; -import rooms_leaderboard from "../api/v2/rooms_leaderboard"; +import { rooms_leaderboard } from "../api/v2/rooms_leaderboard"; import rooms_scores from "../api/v2/rooms_scores"; diff --git a/types/v2/rooms_leaderboard.ts b/types/v2/rooms_leaderboard.ts new file mode 100644 index 00000000..5a875ee5 --- /dev/null +++ b/types/v2/rooms_leaderboard.ts @@ -0,0 +1,37 @@ +export interface RoomsLeaderboardResponse { + leaderboard: Leaderboard[] + user_score: any +} + +export interface Leaderboard { + accuracy: number + attempts: number + completed: number + pp: number + room_id: number + total_score: number + user_id: number + user: User +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour: any + username: string + country: Country +} + +export interface Country { + code: string + name: string +} From 9828b1f4de651494976fe78a5f84a77473480e50 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 18:58:58 +0300 Subject: [PATCH 113/259] rooms_list - errors handling & types --- api/v2/rooms_list.ts | 14 ++--- routes/v2.ts | 2 +- types/v2/rooms_list.ts | 139 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+), 8 deletions(-) create mode 100644 types/v2/rooms_list.ts diff --git a/api/v2/rooms_list.ts b/api/v2/rooms_list.ts index 7206daeb..d87aeff4 100644 --- a/api/v2/rooms_list.ts +++ b/api/v2/rooms_list.ts @@ -1,9 +1,10 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { RoomsListResponse } from "../../types/v2/rooms_list"; import { request } from "../../utility/request"; -const name = async (params: { +export const rooms_list = async (params: { type?: 'playlists' | 'realtime'; show?: 'all' | 'active' | 'ended' | 'participated' | 'owned'; @@ -13,7 +14,7 @@ const name = async (params: { sort?: 'ended' | 'created'; cursor_string?: string; -}, addons?: IDefaultParams) => { +}, addons?: IDefaultParams): Promise => { const object = { type_group: params.type, mode: params.show, @@ -25,18 +26,17 @@ const name = async (params: { if (addons == null) addons = { apiVersion: '99999999' } + const data = await request(`https://osu.ppy.sh/api/v2/rooms`, { method: 'GET', params: object, addons, }); + if (params?.query && !('error' in data)) data.rooms = data.rooms.filter((r: any) => r.name.toLowerCase().includes(params.query.trim().toLowerCase())) return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 52e7918d..2b895004 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -228,7 +228,7 @@ export const session = { -import rooms_list from "../api/v2/rooms_list"; +import { rooms_list } from "../api/v2/rooms_list"; import { rooms_details } from "../api/v2/rooms_details"; import { rooms_leaderboard } from "../api/v2/rooms_leaderboard"; import rooms_scores from "../api/v2/rooms_scores"; diff --git a/types/v2/rooms_list.ts b/types/v2/rooms_list.ts new file mode 100644 index 00000000..7d40a7dd --- /dev/null +++ b/types/v2/rooms_list.ts @@ -0,0 +1,139 @@ +export interface RoomsListResponse { + rooms: Room[] + cursor: Cursor + cursor_string: string +} + +export interface Room { + id: number + name: string + category: string + type: string + user_id: number + starts_at: string + ends_at: any + max_attempts: any + participant_count: number + channel_id: number + active: boolean + has_password: boolean + queue_mode: string + auto_skip: boolean + current_playlist_item: CurrentPlaylistItem + difficulty_range: DifficultyRange + host: Host + playlist_item_stats: PlaylistItemStats + recent_participants: RecentParticipant[] +} + +export interface CurrentPlaylistItem { + id: number + room_id: number + beatmap_id: number + ruleset_id: number + allowed_mods: any[] + required_mods: any[] + expired: boolean + owner_id: number + playlist_order: number + played_at: any + beatmap: Beatmap +} + +export interface Beatmap { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + beatmapset: Beatmapset +} + +export interface Beatmapset { + artist: string + artist_unicode: string + covers: Covers + creator: string + favourite_count: number + hype: any + id: number + nsfw: boolean + offset: number + play_count: number + preview_url: string + source: string + spotlight: boolean + status: string + title: string + title_unicode: string + track_id: any + user_id: number + video: boolean +} + +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} + +export interface DifficultyRange { + max: number + min: number +} + +export interface Host { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour: any + username: string + country: Country +} + +export interface Country { + code: string + name: string +} + +export interface PlaylistItemStats { + count_active: number + count_total: number + ruleset_ids: number[] +} + +export interface RecentParticipant { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour: any + username: string +} + +export interface Cursor { + id: number +} From 888deac1444ec565d4e874e394a42492f8b6c176 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 19:06:51 +0300 Subject: [PATCH 114/259] rooms_scores - errors handling & types --- api/v2/rooms_scores.ts | 41 +++-- routes/v2.ts | 2 +- types/v2/rooms_scores_all.ts | 104 +++++++++++++ types/v2/rooms_scores_single.ts | 207 +++++++++++++++++++++++++ types/v2/rooms_scores_user_highest.ts | 210 ++++++++++++++++++++++++++ 5 files changed, 547 insertions(+), 17 deletions(-) create mode 100644 types/v2/rooms_scores_all.ts create mode 100644 types/v2/rooms_scores_single.ts create mode 100644 types/v2/rooms_scores_user_highest.ts diff --git a/api/v2/rooms_scores.ts b/api/v2/rooms_scores.ts index 39baa460..3ff7d92b 100644 --- a/api/v2/rooms_scores.ts +++ b/api/v2/rooms_scores.ts @@ -1,5 +1,8 @@ import { request } from "../../utility/request"; -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { RoomsScoresSingleResponse } from "../../types/v2/rooms_scores_single"; +import { RoomScoresUserHighestResponse } from "../../types/v2/rooms_scores_user_highest"; +import { RoomsScoresAllResponse } from "../../types/v2/rooms_scores_all"; type params = ({ @@ -28,28 +31,37 @@ type params = ({ type Response = - T extends 'difficulty' - ? any - : T extends 'difficulties' - ? any - : never; + T extends 'all' + ? RoomsScoresAllResponse | IError + : T extends 'single' + ? RoomsScoresSingleResponse | IError + : T extends 'user_highest' + ? RoomScoresUserHighestResponse | IError + : IError; -const name = async (params: T, addons?: IDefaultParams): Promise> => { +export const rooms_scores = async (params: T, addons?: IDefaultParams): Promise> => { let object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; let method = 'GET'; + if (params.id == null) { + return { error: new Error(`Specify room id`) } as Response; + }; + + if (params.playlist_id == null) { + return { error: new Error(`Specify playlist id`) } as Response; + }; + + switch (params.type) { case 'all': url += `/rooms/${params.id}/playlist/${params.playlist_id}/scores`; - object = { - limit: params.limit, - sort: params.sort, - cursor_string: params.cursor_string, - }; + if (params.limit != null) object.limit = params.limit; + if (params.sort != null) object.sort = params.sort; + if (params.cursor_string != null) object.cursor_string = params.cursor_string; break; case 'single': @@ -72,7 +84,4 @@ const name = async (params: T, addons?: IDefaultParams): Promi return data as Response; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 2b895004..3e2ed829 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -231,7 +231,7 @@ export const session = { import { rooms_list } from "../api/v2/rooms_list"; import { rooms_details } from "../api/v2/rooms_details"; import { rooms_leaderboard } from "../api/v2/rooms_leaderboard"; -import rooms_scores from "../api/v2/rooms_scores"; +import { rooms_scores } from "../api/v2/rooms_scores"; export const rooms = { diff --git a/types/v2/rooms_scores_all.ts b/types/v2/rooms_scores_all.ts new file mode 100644 index 00000000..8e4dee7b --- /dev/null +++ b/types/v2/rooms_scores_all.ts @@ -0,0 +1,104 @@ +export interface RoomsScoresAllResponse { + params: Params + scores: Score[] + total: number + user_score: any + cursor: any + cursor_string: any +} + +export interface Params { + limit: number + sort: string +} + +export interface Score { + playlist_item_id: number + room_id: number + solo_score_id: number + ranked: boolean + preserve: boolean + processed: boolean + maximum_statistics: MaximumStatistics + mods: any[] + statistics: Statistics + beatmap_id: number + best_id: any + id: number + rank: string + type: string + user_id: number + accuracy: number + build_id: number + ended_at: string + has_replay: boolean + is_perfect_combo: boolean + legacy_perfect: boolean + legacy_score_id: any + legacy_total_score: number + max_combo: number + passed: boolean + pp: number + ruleset_id: number + started_at: string + total_score: number + replay: boolean + current_user_attributes: CurrentUserAttributes + user: User +} + +export interface MaximumStatistics { + great: number + ignore_hit: number + large_bonus: number + small_bonus: number + large_tick_hit: number + slider_tail_hit: number +} + +export interface Statistics { + ok: number + great: number + ignore_hit: number + ignore_miss: number + large_bonus: number + small_bonus: number + large_tick_hit: number + slider_tail_hit: number + meh?: number + miss?: number + large_tick_miss?: number +} + +export interface CurrentUserAttributes { + pin: any +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour: any + username: string + country: Country + cover: Cover +} + +export interface Country { + code: string + name: string +} + +export interface Cover { + custom_url: any + url: string + id: string +} diff --git a/types/v2/rooms_scores_single.ts b/types/v2/rooms_scores_single.ts new file mode 100644 index 00000000..f43a0689 --- /dev/null +++ b/types/v2/rooms_scores_single.ts @@ -0,0 +1,207 @@ +export interface RoomsScoresSingleResponse { + playlist_item_id: number + room_id: number + solo_score_id: number + ranked: boolean + preserve: boolean + maximum_statistics: MaximumStatistics + mods: any[] + statistics: Statistics + beatmap_id: number + best_id: any + id: number + rank: string + type: string + user_id: number + accuracy: number + build_id: number + ended_at: string + has_replay: boolean + is_perfect_combo: boolean + legacy_perfect: boolean + legacy_score_id: any + legacy_total_score: number + max_combo: number + passed: boolean + pp: number + ruleset_id: number + started_at: string + total_score: number + replay: boolean + current_user_attributes: CurrentUserAttributes + user: User + position: number + scores_around: ScoresAround +} + +export interface MaximumStatistics { + great: number + ignore_hit: number + large_bonus: number + small_bonus: number + large_tick_hit: number + slider_tail_hit: number +} + +export interface Statistics { + ok: number + great: number + ignore_hit: number + ignore_miss: number + large_bonus: number + small_bonus: number + large_tick_hit: number + slider_tail_hit: number +} + +export interface CurrentUserAttributes { + pin: any +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour: any + username: string + country: Country + cover: Cover +} + +export interface Country { + code: string + name: string +} + +export interface Cover { + custom_url: any + url: string + id: string +} + +export interface ScoresAround { + higher: Higher + lower: Lower +} + +export interface Higher { + scores: any[] + params: Params + cursor: any + cursor_string: any +} + +export interface Params { + limit: number + sort: string +} + +export interface Lower { + scores: Score[] + params: Params2 + cursor: any + cursor_string: any +} + +export interface Score { + playlist_item_id: number + room_id: number + solo_score_id: number + ranked: boolean + preserve: boolean + maximum_statistics: MaximumStatistics2 + mods: any[] + statistics: Statistics2 + beatmap_id: number + best_id: any + id: number + rank: string + type: string + user_id: number + accuracy: number + build_id: number + ended_at: string + has_replay: boolean + is_perfect_combo: boolean + legacy_perfect: boolean + legacy_score_id: any + legacy_total_score: number + max_combo: number + passed: boolean + pp: number + ruleset_id: number + started_at: string + total_score: number + replay: boolean + current_user_attributes: CurrentUserAttributes2 + user: User2 +} + +export interface MaximumStatistics2 { + great: number + ignore_hit: number + large_bonus: number + small_bonus: number + large_tick_hit: number + slider_tail_hit: number +} + +export interface Statistics2 { + ok: number + meh: number + miss: number + great: number + ignore_hit: number + ignore_miss: number + large_bonus: number + small_bonus: number + large_tick_hit: number + large_tick_miss: number + slider_tail_hit: number +} + +export interface CurrentUserAttributes2 { + pin: any +} + +export interface User2 { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour: any + username: string + country: Country2 + cover: Cover2 +} + +export interface Country2 { + code: string + name: string +} + +export interface Cover2 { + custom_url: any + url: string + id: string +} + +export interface Params2 { + limit: number + sort: string +} diff --git a/types/v2/rooms_scores_user_highest.ts b/types/v2/rooms_scores_user_highest.ts new file mode 100644 index 00000000..a9aa01ea --- /dev/null +++ b/types/v2/rooms_scores_user_highest.ts @@ -0,0 +1,210 @@ +export interface RoomScoresUserHighestResponse { + playlist_item_id: number + room_id: number + solo_score_id: number + ranked: boolean + preserve: boolean + maximum_statistics: MaximumStatistics + mods: any[] + statistics: Statistics + beatmap_id: number + best_id: any + id: number + rank: string + type: string + user_id: number + accuracy: number + build_id: number + ended_at: string + has_replay: boolean + is_perfect_combo: boolean + legacy_perfect: boolean + legacy_score_id: any + legacy_total_score: number + max_combo: number + passed: boolean + pp: number + ruleset_id: number + started_at: string + total_score: number + replay: boolean + current_user_attributes: CurrentUserAttributes + user: User + position: number + scores_around: ScoresAround +} + +export interface MaximumStatistics { + great: number + ignore_hit: number + large_bonus: number + small_bonus: number + large_tick_hit: number + slider_tail_hit: number +} + +export interface Statistics { + ok: number + meh: number + miss: number + great: number + ignore_hit: number + ignore_miss: number + large_bonus: number + small_bonus: number + large_tick_hit: number + large_tick_miss: number + slider_tail_hit: number +} + +export interface CurrentUserAttributes { + pin: any +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour: any + username: string + country: Country + cover: Cover +} + +export interface Country { + code: string + name: string +} + +export interface Cover { + custom_url: any + url: string + id: string +} + +export interface ScoresAround { + higher: Higher + lower: Lower +} + +export interface Higher { + scores: Score[] + params: Params + cursor: any + cursor_string: any +} + +export interface Score { + playlist_item_id: number + room_id: number + solo_score_id: number + ranked: boolean + preserve: boolean + maximum_statistics: MaximumStatistics2 + mods: any[] + statistics: Statistics2 + beatmap_id: number + best_id: any + id: number + rank: string + type: string + user_id: number + accuracy: number + build_id: number + ended_at: string + has_replay: boolean + is_perfect_combo: boolean + legacy_perfect: boolean + legacy_score_id: any + legacy_total_score: number + max_combo: number + passed: boolean + pp: number + ruleset_id: number + started_at: string + total_score: number + replay: boolean + current_user_attributes: CurrentUserAttributes2 + user: User2 +} + +export interface MaximumStatistics2 { + great: number + ignore_hit: number + large_bonus: number + small_bonus: number + large_tick_hit: number + slider_tail_hit: number +} + +export interface Statistics2 { + ok: number + meh?: number + miss?: number + great: number + ignore_hit: number + ignore_miss: number + large_bonus: number + small_bonus: number + large_tick_hit: number + large_tick_miss?: number + slider_tail_hit: number +} + +export interface CurrentUserAttributes2 { + pin: any +} + +export interface User2 { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour: any + username: string + country: Country2 + cover: Cover2 +} + +export interface Country2 { + code: string + name: string +} + +export interface Cover2 { + custom_url: any + url: string + id: string +} + +export interface Params { + limit: number + sort: string +} + +export interface Lower { + scores: any[] + params: Params2 + cursor: any + cursor_string: any +} + +export interface Params2 { + limit: number + sort: string +} From 524e30b3a1fa1322a1235d675c2b8842ec9f8040 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 19:09:40 +0300 Subject: [PATCH 115/259] scores_details --- api/v2/scores_details.ts | 20 +++-- routes/v2.ts | 2 +- types/v2/scores_details.ts | 170 +++++++++++++++++++++++++++++++++++++ 3 files changed, 183 insertions(+), 9 deletions(-) create mode 100644 types/v2/scores_details.ts diff --git a/api/v2/scores_details.ts b/api/v2/scores_details.ts index 3d268886..73d06040 100644 --- a/api/v2/scores_details.ts +++ b/api/v2/scores_details.ts @@ -1,21 +1,25 @@ -import { IDefaultParams, Modes_names } from "../../types"; +import { IDefaultParams, IError, Modes_names } from "../../types"; +import { ScoresDetailsResponse } from "../../types/v2/scores_details"; import { request } from "../../utility/request"; -const name = async (params: { +export const scores_details = async (params: { id: number; mode?: Modes_names; -}, addons?: IDefaultParams) => { - let url = params.mode ? `https://osu.ppy.sh/api/v2/scores/${params.mode}/${params.id}` : `https://osu.ppy.sh/api/v2/scores/${params.id}`; +}, addons?: IDefaultParams): Promise => { + if (params.id == null) { + return { error: new Error(`Specify score id`) }; + }; + + + const url = params.mode ? `https://osu.ppy.sh/api/v2/scores/${params.mode}/${params.id}` : `https://osu.ppy.sh/api/v2/scores/${params.id}`; const data = await request(url, { method: 'GET', addons, }); - return data; -}; - -export default name; \ No newline at end of file + return data; +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 3e2ed829..9c084a4f 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -80,7 +80,7 @@ export const users = { import scores_list from "../api/v2/scores_list"; -import scores_details from "../api/v2/scores_details"; +import { scores_details } from "../api/v2/scores_details"; import scores_download from "../api/v2/scores_download"; diff --git a/types/v2/scores_details.ts b/types/v2/scores_details.ts new file mode 100644 index 00000000..367b3b7b --- /dev/null +++ b/types/v2/scores_details.ts @@ -0,0 +1,170 @@ +export interface ScoresDetailsResponse { + ranked: boolean + preserve: boolean + processed: boolean + maximum_statistics: MaximumStatistics + mods: Mod[] + statistics: Statistics + beatmap_id: number + best_id: any + id: number + rank: string + type: string + user_id: number + accuracy: number + build_id?: number + ended_at: string + has_replay: boolean + is_perfect_combo: boolean + legacy_perfect: boolean + legacy_score_id?: number + legacy_total_score: number + max_combo: number + passed: boolean + pp: number + ruleset_id: number + started_at?: string + total_score: number + replay: boolean + current_user_attributes: CurrentUserAttributes + beatmap: Beatmap + beatmapset: Beatmapset + rank_global: number + user: User2 +} + +export interface MaximumStatistics { + great: number + legacy_combo_increase?: number + ignore_hit?: number + large_tick_hit?: number + slider_tail_hit?: number +} + +export interface Mod { + acronym: string +} + +export interface Statistics { + ok: number + miss?: number + great: number + ignore_hit?: number + large_tick_hit?: number + slider_tail_hit?: number +} + +export interface CurrentUserAttributes { + pin: any +} + +export interface Beatmap { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + accuracy: number + ar: number + bpm: number + convert: boolean + count_circles: number + count_sliders: number + count_spinners: number + cs: number + deleted_at: any + drain: number + hit_length: number + is_scoreable: boolean + last_updated: string + mode_int: number + passcount: number + playcount: number + ranked: number + url: string + checksum: string + max_combo: number + user: User +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: any + pm_friends_only: boolean + profile_colour: any + username: string +} + +export interface Beatmapset { + artist: string + artist_unicode: string + covers: Covers + creator: string + favourite_count: number + hype: any + id: number + nsfw: boolean + offset: number + play_count: number + preview_url: string + source: string + spotlight: boolean + status: string + title: string + title_unicode: string + track_id: any + user_id: number + video: boolean +} + +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} + +export interface User2 { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour: any + username: string + country: Country + cover: Cover + groups: any[] +} + +export interface Country { + code: string + name: string +} + +export interface Cover { + custom_url?: string + url: string + id?: string +} From b5f396ab55d91c4e14a2324527f391f1f99e6980 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 19:13:16 +0300 Subject: [PATCH 116/259] scores_download - errors handling & types --- api/v2/scores_download.ts | 18 ++++++++++-------- routes/v2.ts | 2 +- types/v2/scores_download.ts | 5 +++++ 3 files changed, 16 insertions(+), 9 deletions(-) create mode 100644 types/v2/scores_download.ts diff --git a/api/v2/scores_download.ts b/api/v2/scores_download.ts index 08c93196..3e186f8d 100644 --- a/api/v2/scores_download.ts +++ b/api/v2/scores_download.ts @@ -1,23 +1,25 @@ -import { Modes_names } from "../../types"; +import { IError, Modes_names } from "../../types"; +import { ScoresDownloadResponse } from "../../types/v2/scores_download"; import { download } from "../../utility/request"; -const name = async (params: { +export const scores_download = async (params: { id: number; mode?: Modes_names; file_path?: string; -}) => { - let url = params.mode ? `https://osu.ppy.sh/api/v2/scores/${params.mode}/${params.id}` : `https://osu.ppy.sh/api/v2/scores/${params.id}`; +}): Promise => { + if (params.id == null) { + return { error: new Error(`Specify score id`) }; + }; + const url = params.mode ? `https://osu.ppy.sh/api/v2/scores/${params.mode}/${params.id}` : `https://osu.ppy.sh/api/v2/scores/${params.id}`; + const data = await download(`${url}/download`, params.file_path, { _callback: false, }); return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 9c084a4f..d2c329c7 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -81,7 +81,7 @@ export const users = { import scores_list from "../api/v2/scores_list"; import { scores_details } from "../api/v2/scores_details"; -import scores_download from "../api/v2/scores_download"; +import { scores_download } from "../api/v2/scores_download"; export const scores = { diff --git a/types/v2/scores_download.ts b/types/v2/scores_download.ts new file mode 100644 index 00000000..b27d3fa6 --- /dev/null +++ b/types/v2/scores_download.ts @@ -0,0 +1,5 @@ +export interface ScoresDownloadResponse { + status: string + destination: string + elapsed_time: number +} From 9a15d221f23fe9bc1df9347b1a27ea169ddc8f67 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 19:33:55 +0300 Subject: [PATCH 117/259] scores_list - errors handling & types --- api/v2/scores_list.ts | 81 ++++++++++++--- routes/v2.ts | 2 +- types/v2/scores_list_beatmap_all.ts | 51 +++++++++ types/v2/scores_list_beatmap_best.ts | 114 ++++++++++++++++++++ types/v2/scores_list_leaderboard.ts | 91 ++++++++++++++++ types/v2/scores_list_solo_scores.ts | 94 +++++++++++++++++ types/v2/scores_list_user_best.ts | 149 +++++++++++++++++++++++++++ types/v2/scores_list_user_firsts.ts | 133 ++++++++++++++++++++++++ types/v2/scores_list_user_pinned.ts | 133 ++++++++++++++++++++++++ types/v2/scores_list_user_recent.ts | 133 ++++++++++++++++++++++++ 10 files changed, 966 insertions(+), 15 deletions(-) create mode 100644 types/v2/scores_list_beatmap_all.ts create mode 100644 types/v2/scores_list_beatmap_best.ts create mode 100644 types/v2/scores_list_leaderboard.ts create mode 100644 types/v2/scores_list_solo_scores.ts create mode 100644 types/v2/scores_list_user_best.ts create mode 100644 types/v2/scores_list_user_firsts.ts create mode 100644 types/v2/scores_list_user_pinned.ts create mode 100644 types/v2/scores_list_user_recent.ts diff --git a/api/v2/scores_list.ts b/api/v2/scores_list.ts index d3be1f13..9ea1722b 100644 --- a/api/v2/scores_list.ts +++ b/api/v2/scores_list.ts @@ -1,5 +1,13 @@ import { request } from "../../utility/request"; -import { IDefaultParams, Modes_names } from "../../types"; +import { IDefaultParams, IError, Modes_names } from "../../types"; +import { ScoresListLeaderboardResponse } from "../../types/v2/scores_list_leaderboard"; +import { ScoresListSoloScoresResponse } from "../../types/v2/scores_list_solo_scores"; +import { ScoresListBeatmapBestResponse } from "../../types/v2/scores_list_beatmap_best"; +import { ScoresListBeatmapAllResponse } from "../../types/v2/scores_list_beatmap_all"; +import { ScoresListUserBestResponse } from "../../types/v2/scores_list_user_best"; +import { ScoresListUserFirstsResponse } from "../../types/v2/scores_list_user_firsts"; +import { ScoresListUserRecentResponse } from "../../types/v2/scores_list_user_recent"; +import { ScoresListUserPinnedResponse } from "../../types/v2/scores_list_user_pinned"; type params = { @@ -34,14 +42,26 @@ type params = { type Response = - T extends 'difficulty' - ? any - : T extends 'difficulties' - ? any - : never; - - -const name = async (params: T, addons?: IDefaultParams): Promise> => { + T extends 'leaderboard' + ? ScoresListLeaderboardResponse | IError + : T extends 'solo_scores' + ? ScoresListSoloScoresResponse | IError + : T extends 'beatmap_best' + ? ScoresListBeatmapBestResponse | IError + : T extends 'beatmap_all' + ? ScoresListBeatmapAllResponse | IError + : T extends 'user_best' + ? ScoresListUserBestResponse | IError + : T extends 'user_firsts' + ? ScoresListUserFirstsResponse | IError + : T extends 'user_recent' + ? ScoresListUserRecentResponse | IError + : T extends 'user_pinned' + ? ScoresListUserPinnedResponse | IError + : IError; + + +export const scores_list = async (params: T, addons?: IDefaultParams): Promise> => { const object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; let method = 'GET'; @@ -49,6 +69,11 @@ const name = async (params: T, addons?: IDefaultParams): Promi switch (params.type) { case 'leaderboard': + if (params.beatmap_id == null) { + return { error: new Error(`Specify beatmap id`) } as Response; + }; + + url += `/beatmaps/${params.beatmap_id}/scores`; @@ -58,6 +83,15 @@ const name = async (params: T, addons?: IDefaultParams): Promi break; case 'beatmap_best': + if (params.beatmap_id == null) { + return { error: new Error(`Specify beatmap id`) } as Response; + }; + + if (params.user_id == null) { + return { error: new Error(`Specify user id`) } as Response; + }; + + url += `/beatmaps/${params.beatmap_id}/scores/users/${params.user_id}`; @@ -66,6 +100,15 @@ const name = async (params: T, addons?: IDefaultParams): Promi break; case 'beatmap_all': + if (params.beatmap_id == null) { + return { error: new Error(`Specify beatmap id`) } as Response; + }; + + if (params.user_id == null) { + return { error: new Error(`Specify user id`) } as Response; + }; + + url += `/beatmaps/${params.beatmap_id}/scores/users/${params.user_id}/all`; @@ -76,6 +119,11 @@ const name = async (params: T, addons?: IDefaultParams): Promi case 'user_firsts': case 'user_recent': case 'user_pinned': + if (params.user_id == null) { + return { error: new Error(`Specify user id`) } as Response; + }; + + url += `/users/${params.user_id}/scores/${params.type.replace('user_', '')}`; @@ -86,6 +134,11 @@ const name = async (params: T, addons?: IDefaultParams): Promi break; case 'solo_scores': + if (params.beatmap_id == null) { + return { error: new Error(`Specify beatmap id`) } as Response; + }; + + url += `/beatmaps/${params.beatmap_id}/solo-scores`; @@ -93,6 +146,9 @@ const name = async (params: T, addons?: IDefaultParams): Promi object['mode'] = params.mode; object['mods[]'] = params.mods; break; + + default: + return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; }; @@ -107,15 +163,12 @@ const name = async (params: T, addons?: IDefaultParams): Promi return data; }; + if (['leaderboard', 'beatmap_all'].includes(params.type)) { data.scores.forEach((r: any, index: number) => r.index = index); return data.scores as Response; }; if (params.type != 'beatmap_best') data.forEach((r: any, index: number) => r.index = index); - return data as Response; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index d2c329c7..686f8620 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -79,7 +79,7 @@ export const users = { -import scores_list from "../api/v2/scores_list"; +import { scores_list } from "../api/v2/scores_list"; import { scores_details } from "../api/v2/scores_details"; import { scores_download } from "../api/v2/scores_download"; diff --git a/types/v2/scores_list_beatmap_all.ts b/types/v2/scores_list_beatmap_all.ts new file mode 100644 index 00000000..b278fc77 --- /dev/null +++ b/types/v2/scores_list_beatmap_all.ts @@ -0,0 +1,51 @@ +export interface ScoresListBeatmapAllResponse { + ranked: boolean + preserve: boolean + processed: boolean + maximum_statistics: MaximumStatistics + mods: Mod[] + statistics: Statistics + beatmap_id: number + best_id: any + id: number + rank: string + type: string + user_id: number + accuracy: number + build_id: any + ended_at: string + has_replay: boolean + is_perfect_combo: boolean + legacy_perfect: boolean + legacy_score_id: number + legacy_total_score: number + max_combo: number + passed: boolean + pp: number + ruleset_id: number + started_at: any + total_score: number + replay: boolean + current_user_attributes: CurrentUserAttributes + index: number +} + +export interface MaximumStatistics { + great: number + legacy_combo_increase: number +} + +export interface Mod { + acronym: string +} + +export interface Statistics { + ok: number + great: number + meh?: number + miss?: number +} + +export interface CurrentUserAttributes { + pin: any +} diff --git a/types/v2/scores_list_beatmap_best.ts b/types/v2/scores_list_beatmap_best.ts new file mode 100644 index 00000000..784a6eeb --- /dev/null +++ b/types/v2/scores_list_beatmap_best.ts @@ -0,0 +1,114 @@ +export interface ScoresListBeatmapBestResponse { + position: number + score: Score +} + +export interface Score { + ranked: boolean + preserve: boolean + processed: boolean + maximum_statistics: MaximumStatistics + mods: Mod[] + statistics: Statistics + beatmap_id: number + best_id: any + id: number + rank: string + type: string + user_id: number + accuracy: number + build_id: any + ended_at: string + has_replay: boolean + is_perfect_combo: boolean + legacy_perfect: boolean + legacy_score_id: number + legacy_total_score: number + max_combo: number + passed: boolean + pp: number + ruleset_id: number + started_at: any + total_score: number + replay: boolean + current_user_attributes: CurrentUserAttributes + beatmap: Beatmap + user: User +} + +export interface MaximumStatistics { + great: number + legacy_combo_increase: number +} + +export interface Mod { + acronym: string +} + +export interface Statistics { + ok: number + great: number +} + +export interface CurrentUserAttributes { + pin: any +} + +export interface Beatmap { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + accuracy: number + ar: number + bpm: number + convert: boolean + count_circles: number + count_sliders: number + count_spinners: number + cs: number + deleted_at: any + drain: number + hit_length: number + is_scoreable: boolean + last_updated: string + mode_int: number + passcount: number + playcount: number + ranked: number + url: string + checksum: string +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour: any + username: string + country: Country + cover: Cover +} + +export interface Country { + code: string + name: string +} + +export interface Cover { + custom_url: string + url: string + id: any +} diff --git a/types/v2/scores_list_leaderboard.ts b/types/v2/scores_list_leaderboard.ts new file mode 100644 index 00000000..fe40c3c4 --- /dev/null +++ b/types/v2/scores_list_leaderboard.ts @@ -0,0 +1,91 @@ +export interface ScoresListLeaderboardResponse { + ranked: boolean + preserve: boolean + processed: boolean + maximum_statistics: MaximumStatistics + mods: Mod[] + statistics: Statistics + beatmap_id: number + best_id: any + id: number + rank: string + type: string + user_id: number + accuracy: number + build_id?: number + ended_at: string + has_replay: boolean + is_perfect_combo: boolean + legacy_perfect: boolean + legacy_score_id?: number + legacy_total_score: number + max_combo: number + passed: boolean + pp?: number + ruleset_id: number + started_at?: string + total_score: number + replay: boolean + current_user_attributes: CurrentUserAttributes + user: User + index: number +} + +export interface MaximumStatistics { + great: number + legacy_combo_increase?: number + ignore_hit?: number + slider_tail_hit?: number +} + +export interface Mod { + acronym: string + settings?: Settings +} + +export interface Settings { + speed_change: number +} + +export interface Statistics { + ok?: number + great: number + miss?: number + meh?: number + ignore_hit?: number + ignore_miss?: number + slider_tail_hit?: number +} + +export interface CurrentUserAttributes { + pin: any +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour: any + username: string + country: Country + cover: Cover +} + +export interface Country { + code: string + name: string +} + +export interface Cover { + custom_url?: string + url: string + id?: string +} diff --git a/types/v2/scores_list_solo_scores.ts b/types/v2/scores_list_solo_scores.ts new file mode 100644 index 00000000..24d72854 --- /dev/null +++ b/types/v2/scores_list_solo_scores.ts @@ -0,0 +1,94 @@ +export interface ScoresListSoloScoresResponse { + ranked: boolean + preserve: boolean + processed: boolean + maximum_statistics: MaximumStatistics + mods: Mod[] + statistics: Statistics + beatmap_id: number + best_id: any + id: number + rank: string + type: string + user_id: number + accuracy: number + build_id?: number + ended_at: string + has_replay: boolean + is_perfect_combo: boolean + legacy_perfect: boolean + legacy_score_id?: number + legacy_total_score: number + max_combo: number + passed: boolean + pp?: number + ruleset_id: number + started_at?: string + total_score: number + replay: boolean + current_user_attributes: CurrentUserAttributes + user: User + index: number +} + +export interface MaximumStatistics { + great?: number + ignore_hit?: number + slider_tail_hit?: number + legacy_combo_increase?: number + perfect?: number +} + +export interface Mod { + acronym: string + settings?: Settings +} + +export interface Settings { + speed_change: number +} + +export interface Statistics { + great?: number + ignore_hit?: number + slider_tail_hit?: number + ok?: number + miss?: number + good?: number + perfect?: number + meh?: number + ignore_miss?: number +} + +export interface CurrentUserAttributes { + pin: any +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour?: string + username: string + country: Country + cover: Cover +} + +export interface Country { + code: string + name: string +} + +export interface Cover { + custom_url?: string + url: string + id?: string +} diff --git a/types/v2/scores_list_user_best.ts b/types/v2/scores_list_user_best.ts new file mode 100644 index 00000000..3ede20ea --- /dev/null +++ b/types/v2/scores_list_user_best.ts @@ -0,0 +1,149 @@ +export interface ScoresListUserBestResponse { + ranked: boolean + preserve: boolean + processed: boolean + maximum_statistics: MaximumStatistics + mods: Mod[] + statistics: Statistics + beatmap_id: number + best_id: any + id: number + rank: string + type: string + user_id: number + accuracy: number + build_id?: number + ended_at: string + has_replay: boolean + is_perfect_combo: boolean + legacy_perfect: boolean + legacy_score_id?: number + legacy_total_score: number + max_combo: number + passed: boolean + pp: number + ruleset_id: number + started_at?: string + total_score: number + replay: boolean + current_user_attributes: CurrentUserAttributes + beatmap: Beatmap + beatmapset: Beatmapset + user: User + weight: Weight + index: number +} + +export interface MaximumStatistics { + great: number + legacy_combo_increase?: number + ignore_hit?: number + large_bonus?: number + small_bonus?: number + large_tick_hit?: number + slider_tail_hit?: number +} + +export interface Mod { + acronym: string +} + +export interface Statistics { + ok?: number + great: number + miss?: number + meh?: number + ignore_hit?: number + ignore_miss?: number + small_bonus?: number + large_tick_hit?: number + slider_tail_hit?: number +} + +export interface CurrentUserAttributes { + pin: any +} + +export interface Beatmap { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + accuracy: number + ar: number + bpm: number + convert: boolean + count_circles: number + count_sliders: number + count_spinners: number + cs: number + deleted_at: any + drain: number + hit_length: number + is_scoreable: boolean + last_updated: string + mode_int: number + passcount: number + playcount: number + ranked: number + url: string + checksum: string +} + +export interface Beatmapset { + artist: string + artist_unicode: string + covers: Covers + creator: string + favourite_count: number + hype: any + id: number + nsfw: boolean + offset: number + play_count: number + preview_url: string + source: string + spotlight: boolean + status: string + title: string + title_unicode: string + track_id?: number + user_id: number + video: boolean +} + +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: any + pm_friends_only: boolean + profile_colour: any + username: string +} + +export interface Weight { + percentage: number + pp: number +} diff --git a/types/v2/scores_list_user_firsts.ts b/types/v2/scores_list_user_firsts.ts new file mode 100644 index 00000000..e2c38d68 --- /dev/null +++ b/types/v2/scores_list_user_firsts.ts @@ -0,0 +1,133 @@ +export interface ScoresListUserFirstsResponse { + ranked: boolean + preserve: boolean + processed: boolean + maximum_statistics: MaximumStatistics + mods: Mod[] + statistics: Statistics + beatmap_id: number + best_id: any + id: number + rank: string + type: string + user_id: number + accuracy: number + build_id: any + ended_at: string + has_replay: boolean + is_perfect_combo: boolean + legacy_perfect: boolean + legacy_score_id: number + legacy_total_score: number + max_combo: number + passed: boolean + pp?: number + ruleset_id: number + started_at: any + total_score: number + replay: boolean + current_user_attributes: CurrentUserAttributes + beatmap: Beatmap + beatmapset: Beatmapset + user: User + index: number +} + +export interface MaximumStatistics { + great: number + legacy_combo_increase: number +} + +export interface Mod { + acronym: string +} + +export interface Statistics { + ok?: number + miss?: number + great: number + meh?: number +} + +export interface CurrentUserAttributes { + pin: any +} + +export interface Beatmap { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + accuracy: number + ar: number + bpm: number + convert: boolean + count_circles: number + count_sliders: number + count_spinners: number + cs: number + deleted_at: any + drain: number + hit_length: number + is_scoreable: boolean + last_updated: string + mode_int: number + passcount: number + playcount: number + ranked: number + url: string + checksum: string +} + +export interface Beatmapset { + artist: string + artist_unicode: string + covers: Covers + creator: string + favourite_count: number + hype: any + id: number + nsfw: boolean + offset: number + play_count: number + preview_url: string + source: string + spotlight: boolean + status: string + title: string + title_unicode: string + track_id?: number + user_id: number + video: boolean +} + +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour: any + username: string +} diff --git a/types/v2/scores_list_user_pinned.ts b/types/v2/scores_list_user_pinned.ts new file mode 100644 index 00000000..f37961fa --- /dev/null +++ b/types/v2/scores_list_user_pinned.ts @@ -0,0 +1,133 @@ +export interface ScoresListUserPinnedResponse { + ranked: boolean + preserve: boolean + processed: boolean + maximum_statistics: MaximumStatistics + mods: Mod[] + statistics: Statistics + beatmap_id: number + best_id: any + id: number + rank: string + type: string + user_id: number + accuracy: number + build_id: any + ended_at: string + has_replay: boolean + is_perfect_combo: boolean + legacy_perfect: boolean + legacy_score_id: number + legacy_total_score: number + max_combo: number + passed: boolean + pp: number + ruleset_id: number + started_at: any + total_score: number + replay: boolean + current_user_attributes: CurrentUserAttributes + beatmap: Beatmap + beatmapset: Beatmapset + user: User + index: number +} + +export interface MaximumStatistics { + great: number + legacy_combo_increase: number +} + +export interface Mod { + acronym: string +} + +export interface Statistics { + ok: number + meh?: number + miss: number + great: number +} + +export interface CurrentUserAttributes { + pin: any +} + +export interface Beatmap { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + accuracy: number + ar: number + bpm: number + convert: boolean + count_circles: number + count_sliders: number + count_spinners: number + cs: number + deleted_at: any + drain: number + hit_length: number + is_scoreable: boolean + last_updated: string + mode_int: number + passcount: number + playcount: number + ranked: number + url: string + checksum: string +} + +export interface Beatmapset { + artist: string + artist_unicode: string + covers: Covers + creator: string + favourite_count: number + hype: any + id: number + nsfw: boolean + offset: number + play_count: number + preview_url: string + source: string + spotlight: boolean + status: string + title: string + title_unicode: string + track_id: any + user_id: number + video: boolean +} + +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour: any + username: string +} diff --git a/types/v2/scores_list_user_recent.ts b/types/v2/scores_list_user_recent.ts new file mode 100644 index 00000000..6cadcf1b --- /dev/null +++ b/types/v2/scores_list_user_recent.ts @@ -0,0 +1,133 @@ +export interface ScoresListUserRecentResponse { + ranked: boolean + preserve: boolean + processed: boolean + maximum_statistics: MaximumStatistics + mods: Mod[] + statistics: Statistics + beatmap_id: number + best_id: any + id: number + rank: string + type: string + user_id: number + accuracy: number + build_id: any + ended_at: string + has_replay: boolean + is_perfect_combo: boolean + legacy_perfect: boolean + legacy_score_id: number + legacy_total_score: number + max_combo: number + passed: boolean + pp?: number + ruleset_id: number + started_at: any + total_score: number + replay: boolean + current_user_attributes: CurrentUserAttributes + beatmap: Beatmap + beatmapset: Beatmapset + user: User + index: number +} + +export interface MaximumStatistics { + great: number + legacy_combo_increase: number +} + +export interface Mod { + acronym: string +} + +export interface Statistics { + ok: number + meh?: number + miss?: number + great: number +} + +export interface CurrentUserAttributes { + pin: any +} + +export interface Beatmap { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + accuracy: number + ar: number + bpm: number + convert: boolean + count_circles: number + count_sliders: number + count_spinners: number + cs: number + deleted_at: any + drain: number + hit_length: number + is_scoreable: boolean + last_updated: string + mode_int: number + passcount: number + playcount: number + ranked: number + url: string + checksum: string +} + +export interface Beatmapset { + artist: string + artist_unicode: string + covers: Covers + creator: string + favourite_count: number + hype: any + id: number + nsfw: boolean + offset: number + play_count: number + preview_url: string + source: string + spotlight: boolean + status: string + title: string + title_unicode: string + track_id?: number + user_id: number + video: boolean +} + +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour: any + username: string +} From 72d107986c1aa761cdf01ce5e40c78987ecef9bc Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 19:35:29 +0300 Subject: [PATCH 118/259] search - errors handling & types --- api/v2/search.ts | 40 +++++++++++++++++++--------------------- routes/v2.ts | 2 +- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/api/v2/search.ts b/api/v2/search.ts index 8dafc35f..1fff951f 100644 --- a/api/v2/search.ts +++ b/api/v2/search.ts @@ -1,4 +1,4 @@ -import { beatmap_category, beatmap_sorting, beatmap_statuses, Modes_names, beatmap_genres, beatmap_languages, beatmap_ranks, beatmap_extra, IDefaultParams } from "../../types"; +import { beatmap_category, beatmap_sorting, beatmap_statuses, Modes_names, beatmap_genres, beatmap_languages, beatmap_ranks, beatmap_extra, IDefaultParams, IError } from "../../types"; import { Genres_enum, Languages_enum, Modes_enums } from "../../types/enums"; import { SearchBeatmaps, SearchWiki } from '../../types/v2/search_all'; import { request } from "../../utility/request"; @@ -32,13 +32,13 @@ type params = ({ type Response = T extends 'site' - ? SearchWiki + ? SearchWiki | IError : T extends 'beatmaps' - ? SearchBeatmaps - : never; + ? SearchBeatmaps | IError + : IError; -const name = async (params: T, addons?: IDefaultParams): Promise> => { +export const search_all = async (params: T, addons?: IDefaultParams): Promise> => { const object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; @@ -56,23 +56,23 @@ const name = async (params: T, addons?: IDefaultParams): Promi case 'beatmaps': url += '/beatmapsets/search'; - if (params._played) object.played = params._played ? 'played' : 'unplayed'; - if (params._nsfw) object.nsfw = params._nsfw; + if (params._played != null) object.played = params._played ? 'played' : 'unplayed'; + if (params._nsfw != null) object.nsfw = params._nsfw; - if (params.query) object.q = params.query; - if (params.mode) object.m = typeof params.mode == 'number' ? params.mode : Modes_enums[params.mode]; - if (params.status) object.s = params.status; - if (params.category) object.c = params.category.join('.'); + if (params.query != null) object.q = params.query; + if (params.mode != null) object.m = typeof params.mode == 'number' ? params.mode : Modes_enums[params.mode]; + if (params.status != null) object.s = params.status; + if (params.category != null) object.c = params.category.join('.'); - if (params.genre) object.g = typeof params.genre == 'number' ? params.genre : Genres_enum[params.genre]; - if (params.language) object.l = typeof params.language == 'number' ? params.language : Languages_enum[params.language]; + if (params.genre != null) object.g = typeof params.genre == 'number' ? params.genre : Genres_enum[params.genre]; + if (params.language != null) object.l = typeof params.language == 'number' ? params.language : Languages_enum[params.language]; - if (params.achieved_rank) object.r = params.achieved_rank.join('.'); + if (params.achieved_rank != null) object.r = params.achieved_rank.join('.'); - if (params.extra) object.e = params.extra.join('.'); + if (params.extra != null) object.e = params.extra.join('.'); - if (params.sort) object.sort = params.sort; - if (params.cursor_string) object.cursor_string = params.cursor_string; + if (params.sort != null) object.sort = params.sort; + if (params.cursor_string != null) object.cursor_string = params.cursor_string; break; }; @@ -83,8 +83,6 @@ const name = async (params: T, addons?: IDefaultParams): Promi addons }); - return data as Response; -}; - -export default name; \ No newline at end of file + return data as Response; +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 686f8620..f4ba852a 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -104,7 +104,7 @@ export const forums = { -import search_all from '../api/v2/search'; +import { search_all } from '../api/v2/search'; export const search = search_all; From f90a0d879fdda5841ddd19663cf6d990e3604649 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 19:40:20 +0300 Subject: [PATCH 119/259] session_actions --- api/v2/session_actions.ts | 22 +++++++++++----------- routes/v2.ts | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/api/v2/session_actions.ts b/api/v2/session_actions.ts index 877c4f50..6047ed0f 100644 --- a/api/v2/session_actions.ts +++ b/api/v2/session_actions.ts @@ -1,5 +1,5 @@ import { request } from "../../utility/request"; -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; type params = ({ @@ -12,14 +12,17 @@ type params = ({ type Response = - T extends 'difficulty' - ? any - : T extends 'difficulties' - ? any - : never; + T extends 'verify' + ? any | IError + : T extends 'reissue' + ? any | IError + : T extends 'delete' + ? any | IError + : IError; -const name = async (params: T, addons?: IDefaultParams): Promise> => { +// FIXME? +export const session_actions = async (params: T, addons?: IDefaultParams): Promise> => { const object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; let method = 'POST'; @@ -52,7 +55,4 @@ const name = async (params: T, addons?: IDefaultParams): Promi return data as Response; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index f4ba852a..c213e414 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -219,7 +219,7 @@ export const chat = { -import session_actions from "../api/v2/session_actions"; +import { session_actions } from "../api/v2/session_actions"; export const session = { From 9b8e719f8a0c712487947c3927dd157c0580826e Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 19:42:45 +0300 Subject: [PATCH 120/259] spotlights_list - errors handling & types --- api/v2/spotlights_list.ts | 11 +++++------ routes/v2.ts | 2 +- types/v2/spotlights_list.ts | 8 ++++++++ 3 files changed, 14 insertions(+), 7 deletions(-) create mode 100644 types/v2/spotlights_list.ts diff --git a/api/v2/spotlights_list.ts b/api/v2/spotlights_list.ts index 5cd968e3..f665000d 100644 --- a/api/v2/spotlights_list.ts +++ b/api/v2/spotlights_list.ts @@ -1,16 +1,15 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { SpotlightsListResponse } from "../../types/v2/spotlights_list"; import { request } from "../../utility/request"; -const name = async (addons?: IDefaultParams) => { +export const spotlights_list = async (addons?: IDefaultParams): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/spotlights`, { method: 'GET', addons, }); - return data.spotlights; -}; - -export default name; \ No newline at end of file + return data.spotlights; +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index c213e414..fd6a3e1d 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -153,7 +153,7 @@ export const ranking = { -import spotlights_list from "../api/v2/spotlights_list"; +import { spotlights_list } from "../api/v2/spotlights_list"; export const spotlights = { diff --git a/types/v2/spotlights_list.ts b/types/v2/spotlights_list.ts new file mode 100644 index 00000000..f2688268 --- /dev/null +++ b/types/v2/spotlights_list.ts @@ -0,0 +1,8 @@ +export interface SpotlightsListResponse { + end_date: string + id: number + mode_specific: boolean + name: string + start_date: string + type: string +} From 04081b052a6ee9980206010a8bcc74fa63ee0cde Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 19:45:08 +0300 Subject: [PATCH 121/259] users_activity - errors handling & types --- api/v2/users_activity.ts | 17 ++++++++++------- routes/v2.ts | 2 +- types/v2/users_activity.ts | 21 +++++++++++++++++++++ 3 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 types/v2/users_activity.ts diff --git a/api/v2/users_activity.ts b/api/v2/users_activity.ts index f1ce2994..fbd3ecd3 100644 --- a/api/v2/users_activity.ts +++ b/api/v2/users_activity.ts @@ -1,13 +1,19 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { UsersActivityResponse } from "../../types/v2/users_activity"; import { request } from "../../utility/request"; -const name = async (params: { +export const users_activity = async (params: { id: number; limit?: number; offset?: number; -}, addons?: IDefaultParams) => { +}, addons?: IDefaultParams): Promise => { + if (params.id == null) { + return { error: new Error(`Specify activity id`) }; + }; + + const data = await request(`https://osu.ppy.sh/api/v2/users/${params.id}/recent_activity`, { method: 'GET', params: { @@ -19,7 +25,4 @@ const name = async (params: { return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index fd6a3e1d..d4db2108 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -62,7 +62,7 @@ export const comments = { import users_list from "../api/v2/users_list"; import users_events from "../api/v2/users_events"; import users_details from "../api/v2/users_details"; -import users_activity from "../api/v2/users_activity"; +import { users_activity } from "../api/v2/users_activity"; import users_beatmaps from "../api/v2/users_beatmaps"; import users_kudosu from "../api/v2/users_kudosu"; diff --git a/types/v2/users_activity.ts b/types/v2/users_activity.ts new file mode 100644 index 00000000..4a17e485 --- /dev/null +++ b/types/v2/users_activity.ts @@ -0,0 +1,21 @@ +export interface UsersActivityResponse { + created_at: string + createdAt: string + id: number + type: string + mode: string + beatmap: Beatmap + user: User + scoreRank?: string + rank?: number +} + +export interface Beatmap { + title: string + url: string +} + +export interface User { + username: string + url: string +} From 5f945d56b34c4059a748f89fa7eef98bca779b0b Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 19:48:06 +0300 Subject: [PATCH 122/259] users_beatmaps - errors handling & types --- api/v2/users_beatmaps.ts | 21 ++++-- routes/v2.ts | 2 +- types/v2/users_beatmaps.ts | 141 +++++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+), 8 deletions(-) create mode 100644 types/v2/users_beatmaps.ts diff --git a/api/v2/users_beatmaps.ts b/api/v2/users_beatmaps.ts index fe6c32af..47dbf88c 100644 --- a/api/v2/users_beatmaps.ts +++ b/api/v2/users_beatmaps.ts @@ -1,15 +1,25 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { UsersBeatmapsResponse } from "../../types/v2/users_beatmaps"; import { request } from "../../utility/request"; -const name = async (params: { +export const users_beatmaps = async (params: { type: 'favourite' | 'graveyard' | 'guest' | 'loved' | 'most_played' | 'nominated' | 'pending' | 'ranked'; id: number; limit?: number; offset?: number; -}, addons?: IDefaultParams) => { +}, addons?: IDefaultParams): Promise => { + if (params.id == null) { + return { error: new Error(`Specify user id`) }; + }; + + if (params.type == null) { + return { error: new Error(`Specify beatmaps type`) }; + }; + + const data = await request(`https://osu.ppy.sh/api/v2/users/${params.id}/beatmapsets/${params.type}`, { method: 'GET', params: { @@ -21,7 +31,4 @@ const name = async (params: { return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index d4db2108..3e065cfc 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -63,7 +63,7 @@ import users_list from "../api/v2/users_list"; import users_events from "../api/v2/users_events"; import users_details from "../api/v2/users_details"; import { users_activity } from "../api/v2/users_activity"; -import users_beatmaps from "../api/v2/users_beatmaps"; +import { users_beatmaps } from "../api/v2/users_beatmaps"; import users_kudosu from "../api/v2/users_kudosu"; diff --git a/types/v2/users_beatmaps.ts b/types/v2/users_beatmaps.ts new file mode 100644 index 00000000..6f77fe24 --- /dev/null +++ b/types/v2/users_beatmaps.ts @@ -0,0 +1,141 @@ +export interface UsersBeatmapsResponse { + artist?: string + artist_unicode?: string + covers?: Covers + creator?: string + favourite_count?: number + hype?: Hype + id?: number + nsfw?: boolean + offset?: number + play_count?: number + preview_url?: string + source?: string + spotlight?: boolean + status?: string + title?: string + title_unicode?: string + track_id?: number + user_id?: number + video?: boolean + bpm?: number + can_be_hyped?: boolean + deleted_at: any + discussion_enabled?: boolean + discussion_locked?: boolean + is_scoreable?: boolean + last_updated?: string + legacy_thread_url?: string + nominations_summary?: NominationsSummary + ranked?: number + ranked_date?: string + storyboard?: boolean + submitted_date?: string + tags?: string + availability?: Availability + beatmaps?: Beatmap[] + beatmap_id?: number + count?: number + beatmap?: Beatmap2 + beatmapset?: Beatmapset +} + +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} + +export interface Hype { + current: number + required: number +} + +export interface NominationsSummary { + current: number + required: number +} + +export interface Availability { + download_disabled: boolean + more_information: any +} + +export interface Beatmap { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + accuracy: number + ar: number + bpm: number + convert: boolean + count_circles: number + count_sliders: number + count_spinners: number + cs: number + deleted_at: any + drain: number + hit_length: number + is_scoreable: boolean + last_updated: string + mode_int: number + passcount: number + playcount: number + ranked: number + url: string + checksum: string +} + +export interface Beatmap2 { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string +} + +export interface Beatmapset { + artist: string + artist_unicode: string + covers: Covers2 + creator: string + favourite_count: number + hype: any + id: number + nsfw: boolean + offset: number + play_count: number + preview_url: string + source: string + spotlight: boolean + status: string + title: string + title_unicode: string + track_id?: number + user_id: number + video: boolean +} + +export interface Covers2 { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} From a34cf7187d489dd1b48f542542ec982309965747 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 19:49:42 +0300 Subject: [PATCH 123/259] users_details - errors handling & types --- api/v2/users_details.ts | 17 ++-- routes/v2.ts | 2 +- types/v2/users_details.ts | 179 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 190 insertions(+), 8 deletions(-) create mode 100644 types/v2/users_details.ts diff --git a/api/v2/users_details.ts b/api/v2/users_details.ts index 00b490a9..03df8b1c 100644 --- a/api/v2/users_details.ts +++ b/api/v2/users_details.ts @@ -1,13 +1,19 @@ -import { IDefaultParams, Modes_names } from "../../types"; +import { IDefaultParams, IError, Modes_names } from "../../types"; +import { UsersDetailsResponse } from "../../types/v2/users_details"; import { request } from "../../utility/request"; -const name = async (params: { +export const users_details = async (params: { id: number; mode?: Modes_names; key?: 'id' | 'username'; -}, addons?: IDefaultParams) => { +}, addons?: IDefaultParams): Promise => { + if (params.id == null) { + return { error: new Error(`Specify user id`) }; + }; + + const data = await request(`https://osu.ppy.sh/api/v2/users/${params.id}${params.mode ? `/${params.mode}` : ''}`, { method: 'GET', params: { key: params.key }, @@ -16,7 +22,4 @@ const name = async (params: { return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 3e065cfc..a4a1d087 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -61,7 +61,7 @@ export const comments = { import users_list from "../api/v2/users_list"; import users_events from "../api/v2/users_events"; -import users_details from "../api/v2/users_details"; +import { users_details } from "../api/v2/users_details"; import { users_activity } from "../api/v2/users_activity"; import { users_beatmaps } from "../api/v2/users_beatmaps"; import users_kudosu from "../api/v2/users_kudosu"; diff --git a/types/v2/users_details.ts b/types/v2/users_details.ts new file mode 100644 index 00000000..17e86e4a --- /dev/null +++ b/types/v2/users_details.ts @@ -0,0 +1,179 @@ +export interface UsersDetailsResponse { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour?: string + username: string + cover_url: string + discord?: string + has_supported: boolean + interests?: string + join_date: string + location?: string + max_blocks: number + max_friends: number + occupation?: string + playmode: string + playstyle?: string[] + post_count: number + profile_order: string[] + title: any + title_url: any + twitter?: string + website?: string + country: Country + cover: Cover + kudosu: Kudosu + account_history: any[] + active_tournament_banner: any + active_tournament_banners: any[] + badges: Badge[] + beatmap_playcounts_count: number + comments_count: number + favourite_beatmapset_count: number + follower_count: number + graveyard_beatmapset_count: number + groups: Group[] + guest_beatmapset_count: number + loved_beatmapset_count: number + mapping_follower_count: number + monthly_playcounts: MonthlyPlaycount[] + nominated_beatmapset_count: number + page: Page + pending_beatmapset_count: number + previous_usernames: string[] + rank_highest: RankHighest + ranked_beatmapset_count: number + replays_watched_counts: ReplaysWatchedCount[] + scores_best_count: number + scores_first_count: number + scores_pinned_count: number + scores_recent_count: number + statistics: Statistics + support_level: number + user_achievements: UserAchievement[] + rank_history: RankHistory + rankHistory: RankHistory2 + ranked_and_approved_beatmapset_count: number + unranked_beatmapset_count: number +} + +export interface Country { + code: string + name: string +} + +export interface Cover { + custom_url: string + url: string + id: any +} + +export interface Kudosu { + available: number + total: number +} + +export interface Badge { + awarded_at: string + description: string + "image@2x_url": string + image_url: string + url: string +} + +export interface Group { + colour: string + has_listing: boolean + has_playmodes: boolean + id: number + identifier: string + is_probationary: boolean + name: string + short_name: string + playmodes: any +} + +export interface MonthlyPlaycount { + start_date: string + count: number +} + +export interface Page { + html: string + raw: string +} + +export interface RankHighest { + rank: number + updated_at: string +} + +export interface ReplaysWatchedCount { + start_date: string + count: number +} + +export interface Statistics { + count_100: number + count_300: number + count_50: number + count_miss: number + level: Level + global_rank: number + global_rank_exp: any + pp: number + pp_exp: number + ranked_score: number + hit_accuracy: number + play_count: number + play_time: number + total_score: number + total_hits: number + maximum_combo: number + replays_watched_by_others: number + is_ranked: boolean + grade_counts: GradeCounts + country_rank: number + rank: Rank +} + +export interface Level { + current: number + progress: number +} + +export interface GradeCounts { + ss: number + ssh: number + s: number + sh: number + a: number +} + +export interface Rank { + country: number +} + +export interface UserAchievement { + achieved_at: string + achievement_id: number +} + +export interface RankHistory { + mode: string + data: number[] +} + +export interface RankHistory2 { + mode: string + data: number[] +} From 4c50311e9809901a477135e0d76e57b00faae795 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 19:52:11 +0300 Subject: [PATCH 124/259] users_events - errors handling & types --- api/v2/users_events.ts | 26 +++++++++++--------------- routes/v2.ts | 2 +- types/{ => v2}/users_events.ts | 4 ++-- 3 files changed, 14 insertions(+), 18 deletions(-) rename types/{ => v2}/users_events.ts (93%) diff --git a/api/v2/users_events.ts b/api/v2/users_events.ts index 97ca4522..35b5395b 100644 --- a/api/v2/users_events.ts +++ b/api/v2/users_events.ts @@ -1,31 +1,27 @@ import { request } from "../../utility/request"; -import { UsersEvents } from '../../types/users_events'; -import { IDefaultParams } from "../../types"; +import { UsersEventsResponse } from '../../types/v2/users_events'; +import { IDefaultParams, IError } from "../../types"; -const name = async ({ sort, cursor_string, type }: { +export const users_events = async ({ sort, cursor_string, type }: { type?: ('achievement' | 'beatmapPlaycount' | 'beatmapsetApprove' | 'beatmapsetDelete' | 'beatmapsetRevive' | 'beatmapsetUpdate' | 'beatmapsetUpload' | 'rank' | 'userSupportAgain' | 'userSupportFirst' | 'userSupportGift' | 'usernameChange')[] sort?: 'id_desc' | 'id_asc', cursor_string?: string; -} = {}, addons?: IDefaultParams): Promise => { - const data: UsersEvents = await request(`https://osu.ppy.sh/api/v2/events`, { +} = {}, addons?: IDefaultParams): Promise => { + const data: UsersEventsResponse = await request(`https://osu.ppy.sh/api/v2/events`, { method: 'GET', params: { sort: sort, cursor_string: cursor_string }, + addons, }); - if (type != null) { - if (!Array.isArray(type)) - throw new Error('Event Type must be an Array of options'); - - const sorted = data.events.filter(r => type.includes(r.type)); - data.events = sorted; + if (!Array.isArray(type)) { + return { error: new Error(`Events Type must be an Array of types. Example: ['achievement', 'rank']`) }; }; + const sorted = data.events.filter(r => type.includes(r.type)); + data.events = sorted; return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index a4a1d087..c5ad9f01 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -60,7 +60,7 @@ export const comments = { import users_list from "../api/v2/users_list"; -import users_events from "../api/v2/users_events"; +import { users_events } from "../api/v2/users_events"; import { users_details } from "../api/v2/users_details"; import { users_activity } from "../api/v2/users_activity"; import { users_beatmaps } from "../api/v2/users_beatmaps"; diff --git a/types/users_events.ts b/types/v2/users_events.ts similarity index 93% rename from types/users_events.ts rename to types/v2/users_events.ts index 4f821d3f..b5d5eb7d 100644 --- a/types/users_events.ts +++ b/types/v2/users_events.ts @@ -1,4 +1,4 @@ -import { Modes_names } from "."; +import { Modes_names } from "../index"; export enum ActionType { Rank = 'rank', @@ -12,7 +12,7 @@ export enum ActionType { BeatmapsetApprove = 'beatmapsetApprove', } -export interface UsersEvents { +export interface UsersEventsResponse { events: Event[]; cursor: Cursor; cursor_string: string; From 11d23b5d17119d6b79af03b11e72270679c2b7a5 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 19:53:49 +0300 Subject: [PATCH 125/259] users_kudosu - errors handling & types --- api/v2/users_kudosu.ts | 17 ++++++++++------- routes/v2.ts | 2 +- types/v2/users_kudosu.ts | 19 +++++++++++++++++++ 3 files changed, 30 insertions(+), 8 deletions(-) create mode 100644 types/v2/users_kudosu.ts diff --git a/api/v2/users_kudosu.ts b/api/v2/users_kudosu.ts index 8fdbbb33..96f33088 100644 --- a/api/v2/users_kudosu.ts +++ b/api/v2/users_kudosu.ts @@ -1,13 +1,19 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { UsersKudosuResponse } from "../../types/v2/users_kudosu"; import { request } from "../../utility/request"; -const name = async (params: { +export const users_kudosu = async (params: { id: number; limit?: number; offset?: number; -}, addons?: IDefaultParams) => { +}, addons?: IDefaultParams): Promise => { + if (params.id == null) { + return { error: new Error(`Specify user id`) }; + }; + + const data = await request(`https://osu.ppy.sh/api/v2/users/${params.id}/kudosu`, { method: 'GET', params: { @@ -19,7 +25,4 @@ const name = async (params: { return data; -}; - - -export default name; \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index c5ad9f01..62eb8237 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -64,7 +64,7 @@ import { users_events } from "../api/v2/users_events"; import { users_details } from "../api/v2/users_details"; import { users_activity } from "../api/v2/users_activity"; import { users_beatmaps } from "../api/v2/users_beatmaps"; -import users_kudosu from "../api/v2/users_kudosu"; +import { users_kudosu } from "../api/v2/users_kudosu"; export const users = { diff --git a/types/v2/users_kudosu.ts b/types/v2/users_kudosu.ts new file mode 100644 index 00000000..7afd990b --- /dev/null +++ b/types/v2/users_kudosu.ts @@ -0,0 +1,19 @@ +export interface UsersKudosuResponse { + id: number + action: string + amount: number + model: string + created_at: string + giver: any + post: Post + details: Details +} + +export interface Post { + url: string + title: string +} + +export interface Details { + event: string +} From 4a5d904deb7313c280dd9cab8137af41d9f40c86 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 19:59:41 +0300 Subject: [PATCH 126/259] users_list - errors handling & types --- api/v2/users_list.ts | 17 ++-- routes/v2.ts | 2 +- types/ranking_details.ts | 195 -------------------------------------- types/scores_details.ts | 178 ---------------------------------- types/scores_user.ts | 166 -------------------------------- types/user_details.ts | 181 ----------------------------------- types/users_details.ts | 84 ---------------- types/v2/users_details.ts | 6 ++ types/v2/users_list.ts | 189 ++++++++++++++++++++++++++++++++++++ utility/auth.ts | 2 +- 10 files changed, 207 insertions(+), 813 deletions(-) delete mode 100644 types/ranking_details.ts delete mode 100644 types/scores_details.ts delete mode 100644 types/scores_user.ts delete mode 100644 types/user_details.ts delete mode 100644 types/users_details.ts create mode 100644 types/v2/users_list.ts diff --git a/api/v2/users_list.ts b/api/v2/users_list.ts index ce7bff38..caaef394 100644 --- a/api/v2/users_list.ts +++ b/api/v2/users_list.ts @@ -1,10 +1,15 @@ import { request } from "../../utility/request"; -import { UsersDetails } from '../../types/users_details'; -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { UsersLisResponse } from "../../types/v2/users_list"; -const name = async (ids: number[], addons?: IDefaultParams): Promise => { +export const users_list = async (ids: number[], addons?: IDefaultParams): Promise => { + if ((ids || [])?.length == 0) { + return { error: new Error(`Specify at least one user id`) }; + }; + + const data = await request(`https://osu.ppy.sh/api/v2/users`, { method: 'GET', params: { @@ -13,9 +18,7 @@ const name = async (ids: number[], addons?: IDefaultParams): Promise Date: Fri, 26 Apr 2024 20:02:08 +0300 Subject: [PATCH 127/259] wiki_details - errors handling & types --- api/v2/wiki_details.ts | 22 +++++++++++++++------- routes/v2.ts | 2 +- types/v2/wiki_details.ts | 10 ++++++++++ 3 files changed, 26 insertions(+), 8 deletions(-) create mode 100644 types/v2/wiki_details.ts diff --git a/api/v2/wiki_details.ts b/api/v2/wiki_details.ts index 7e2a5ed4..7d6b198f 100644 --- a/api/v2/wiki_details.ts +++ b/api/v2/wiki_details.ts @@ -1,19 +1,27 @@ -import { IDefaultParams } from "../../types"; +import { IDefaultParams, IError } from "../../types"; +import { WikiDetailsResponse } from "../../types/v2/wiki_details"; import { request } from "../../utility/request"; -const name = async (params: { +export const wiki_details = async (params: { locale: string; path_name: string; -}, addons?: IDefaultParams) => { +}, addons?: IDefaultParams): Promise => { + if (params.locale == null) { + return { error: new Error(`Specify locale code. Example: en`) }; + }; + + if (params.path_name == null) { + return { error: new Error(`Specify wiki page path`) }; + }; + + const data = await request(`https://osu.ppy.sh/api/v2/wiki/${params.locale}/${params.path_name}`, { method: 'GET', addons, }); - return data; -}; - -export default name; \ No newline at end of file + return data; +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 7d0c474f..7bf615be 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -162,7 +162,7 @@ export const spotlights = { -import wiki_details from "../api/v2/wiki_details"; +import { wiki_details } from "../api/v2/wiki_details"; export const wiki = { diff --git a/types/v2/wiki_details.ts b/types/v2/wiki_details.ts new file mode 100644 index 00000000..25af2be1 --- /dev/null +++ b/types/v2/wiki_details.ts @@ -0,0 +1,10 @@ +export interface WikiDetailsResponse { + available_locales: string[] + layout: string + locale: string + markdown: string + path: string + subtitle: any + tags: any[] + title: string +} From 04daec1a9e58beecec72982589bf3acfeeda2800 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 20:06:21 +0300 Subject: [PATCH 128/259] move v1 --- {src/api => api}/v1/form/beatmap/category.ts | 0 {src/api => api}/v1/form/beatmap/creator.ts | 0 {src/api => api}/v1/form/beatmap/scores.ts | 0 {src/api => api}/v1/form/match.ts | 0 {src/api => api}/v1/form/replays.ts | 0 {src/api => api}/v1/form/user/best.ts | 0 {src/api => api}/v1/form/user/details.ts | 0 {src/api => api}/v1/form/user/recent.ts | 0 {src/api => api}/v1/index.ts | 0 {src/api => api}/v1/pre | 0 {src/api => api}/v1/routes/beatmap/creator.ts | 0 {src/api => api}/v1/routes/beatmap/diff.ts | 0 {src/api => api}/v1/routes/beatmap/scores.ts | 0 {src/api => api}/v1/routes/beatmap/set.ts | 0 {src/api => api}/v1/routes/match.ts | 0 {src/api => api}/v1/routes/replay.ts | 0 {src/api => api}/v1/routes/user/details.ts | 0 .../api => api}/v1/routes/user/scores-category.ts | 0 src/index.ts | 15 +-------------- 19 files changed, 1 insertion(+), 14 deletions(-) rename {src/api => api}/v1/form/beatmap/category.ts (100%) rename {src/api => api}/v1/form/beatmap/creator.ts (100%) rename {src/api => api}/v1/form/beatmap/scores.ts (100%) rename {src/api => api}/v1/form/match.ts (100%) rename {src/api => api}/v1/form/replays.ts (100%) rename {src/api => api}/v1/form/user/best.ts (100%) rename {src/api => api}/v1/form/user/details.ts (100%) rename {src/api => api}/v1/form/user/recent.ts (100%) rename {src/api => api}/v1/index.ts (100%) rename {src/api => api}/v1/pre (100%) rename {src/api => api}/v1/routes/beatmap/creator.ts (100%) rename {src/api => api}/v1/routes/beatmap/diff.ts (100%) rename {src/api => api}/v1/routes/beatmap/scores.ts (100%) rename {src/api => api}/v1/routes/beatmap/set.ts (100%) rename {src/api => api}/v1/routes/match.ts (100%) rename {src/api => api}/v1/routes/replay.ts (100%) rename {src/api => api}/v1/routes/user/details.ts (100%) rename {src/api => api}/v1/routes/user/scores-category.ts (100%) diff --git a/src/api/v1/form/beatmap/category.ts b/api/v1/form/beatmap/category.ts similarity index 100% rename from src/api/v1/form/beatmap/category.ts rename to api/v1/form/beatmap/category.ts diff --git a/src/api/v1/form/beatmap/creator.ts b/api/v1/form/beatmap/creator.ts similarity index 100% rename from src/api/v1/form/beatmap/creator.ts rename to api/v1/form/beatmap/creator.ts diff --git a/src/api/v1/form/beatmap/scores.ts b/api/v1/form/beatmap/scores.ts similarity index 100% rename from src/api/v1/form/beatmap/scores.ts rename to api/v1/form/beatmap/scores.ts diff --git a/src/api/v1/form/match.ts b/api/v1/form/match.ts similarity index 100% rename from src/api/v1/form/match.ts rename to api/v1/form/match.ts diff --git a/src/api/v1/form/replays.ts b/api/v1/form/replays.ts similarity index 100% rename from src/api/v1/form/replays.ts rename to api/v1/form/replays.ts diff --git a/src/api/v1/form/user/best.ts b/api/v1/form/user/best.ts similarity index 100% rename from src/api/v1/form/user/best.ts rename to api/v1/form/user/best.ts diff --git a/src/api/v1/form/user/details.ts b/api/v1/form/user/details.ts similarity index 100% rename from src/api/v1/form/user/details.ts rename to api/v1/form/user/details.ts diff --git a/src/api/v1/form/user/recent.ts b/api/v1/form/user/recent.ts similarity index 100% rename from src/api/v1/form/user/recent.ts rename to api/v1/form/user/recent.ts diff --git a/src/api/v1/index.ts b/api/v1/index.ts similarity index 100% rename from src/api/v1/index.ts rename to api/v1/index.ts diff --git a/src/api/v1/pre b/api/v1/pre similarity index 100% rename from src/api/v1/pre rename to api/v1/pre diff --git a/src/api/v1/routes/beatmap/creator.ts b/api/v1/routes/beatmap/creator.ts similarity index 100% rename from src/api/v1/routes/beatmap/creator.ts rename to api/v1/routes/beatmap/creator.ts diff --git a/src/api/v1/routes/beatmap/diff.ts b/api/v1/routes/beatmap/diff.ts similarity index 100% rename from src/api/v1/routes/beatmap/diff.ts rename to api/v1/routes/beatmap/diff.ts diff --git a/src/api/v1/routes/beatmap/scores.ts b/api/v1/routes/beatmap/scores.ts similarity index 100% rename from src/api/v1/routes/beatmap/scores.ts rename to api/v1/routes/beatmap/scores.ts diff --git a/src/api/v1/routes/beatmap/set.ts b/api/v1/routes/beatmap/set.ts similarity index 100% rename from src/api/v1/routes/beatmap/set.ts rename to api/v1/routes/beatmap/set.ts diff --git a/src/api/v1/routes/match.ts b/api/v1/routes/match.ts similarity index 100% rename from src/api/v1/routes/match.ts rename to api/v1/routes/match.ts diff --git a/src/api/v1/routes/replay.ts b/api/v1/routes/replay.ts similarity index 100% rename from src/api/v1/routes/replay.ts rename to api/v1/routes/replay.ts diff --git a/src/api/v1/routes/user/details.ts b/api/v1/routes/user/details.ts similarity index 100% rename from src/api/v1/routes/user/details.ts rename to api/v1/routes/user/details.ts diff --git a/src/api/v1/routes/user/scores-category.ts b/api/v1/routes/user/scores-category.ts similarity index 100% rename from src/api/v1/routes/user/scores-category.ts rename to api/v1/routes/user/scores-category.ts diff --git a/src/index.ts b/src/index.ts index 2f7c9ec6..e87145bf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,15 +1,2 @@ -// export * as v1 from "./api/v1/index"; -// export * as v2 from "./api/v2/index"; - export * as mods from './utility/mods'; -export * as tools from './utility/tools/index'; - -export * as auth from './utility/auth' - - -export * as v1 from "./api/v1/index"; -export * as v2 from "./api/v2/index"; - -export { download } from "./utility/request"; - -// export * as md from './md'; \ No newline at end of file +export * as tools from './utility/tools/index'; \ No newline at end of file From 9ad2154f7e818f2d445316fe4390b72f01205b70 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 26 Apr 2024 20:25:45 +0300 Subject: [PATCH 129/259] fix 1/? --- api/v2/beatmaps_details.ts | 3 ++- api/v2/beatmaps_lookup.ts | 10 +++++----- api/v2/chat_updates.ts | 13 +++++-------- api/v2/comments_actions.ts | 11 +++++++---- api/v2/comments_list.ts | 21 +++++++++------------ api/v2/forums_topics_actions.ts | 3 +++ api/v2/forums_topics_details.ts | 21 +++++++++------------ api/v2/matches_list.ts | 13 +++++-------- api/v2/me_details.ts | 1 + api/v2/me_download_quota.ts | 1 + api/v2/news_list.ts | 9 +++++---- api/v2/notification_actions.ts | 3 +++ api/v2/notifications_list.ts | 8 +++----- api/v2/ranking_list.ts | 27 ++++++++++++++------------- api/v2/rooms_list.ts | 16 +++++++--------- api/v2/rooms_scores.ts | 9 ++++++--- api/v2/session_actions.ts | 2 -- api/v2/users_events.ts | 7 +++++-- package.json | 2 +- utility/request.ts | 19 +++++++++++++++++-- 20 files changed, 108 insertions(+), 91 deletions(-) diff --git a/api/v2/beatmaps_details.ts b/api/v2/beatmaps_details.ts index 3fb57084..f78b2251 100644 --- a/api/v2/beatmaps_details.ts +++ b/api/v2/beatmaps_details.ts @@ -17,7 +17,8 @@ type Response = T extends 'difficulty' ? BeamapsDetailsDifficulty | IError : T extends 'set' - ? BeamapsDetailsSet | IError : IError; + ? BeamapsDetailsSet | IError + : IError; export const beatmaps_details = async (params: T, addons?: IDefaultParams): Promise> => { diff --git a/api/v2/beatmaps_lookup.ts b/api/v2/beatmaps_lookup.ts index 5243a519..304e6f83 100644 --- a/api/v2/beatmaps_lookup.ts +++ b/api/v2/beatmaps_lookup.ts @@ -52,9 +52,9 @@ export const beatmaps_lookup = async (params: T, addons?: IDef return { error: new Error(`Specify at least one parameter`) } as Response; }; - if (params.id) object.id = params.id; - if (params.checksum) object.checksum = params.checksum; - if (params.filename) object.filename = params.filename; + object.id = params.id; + object.checksum = params.checksum; + object.filename = params.filename; break; @@ -65,7 +65,7 @@ export const beatmaps_lookup = async (params: T, addons?: IDef return { error: new Error(`Specify beatmap set id`) } as Response; }; - if (params.id) object.beatmap_id = params.id; + object.beatmap_id = params.id; break; @@ -77,7 +77,7 @@ export const beatmaps_lookup = async (params: T, addons?: IDef return { error: new Error(`Specify beatmap id`) } as Response; }; - if (params.mods) object.mods = params.mods; + object.mods = params.mods; if (typeof params.mode == 'string') object.ruleset = params.mode; else if (typeof params.mode == 'number') object.ruleset_id = Modes_enums[params.mode]; diff --git a/api/v2/chat_updates.ts b/api/v2/chat_updates.ts index 18e4f966..58770da2 100644 --- a/api/v2/chat_updates.ts +++ b/api/v2/chat_updates.ts @@ -9,16 +9,13 @@ export const chat_updates = async (params: { includes: ('presence' | 'silences' | 'messages')[]; history_since: number; }, addons?: IDefaultParams): Promise => { - const object = { - 'history_since': params.history_since, - 'includes[]': params.includes, - 'since': params.after_id, - }; - - const data = await request(`https://osu.ppy.sh/api/v2/chat/updates`, { method: 'GET', - params: object, + params: { + 'history_since': params.history_since, + 'includes[]': params.includes, + 'since': params.after_id, + }, addons, }); diff --git a/api/v2/comments_actions.ts b/api/v2/comments_actions.ts index ea2e4ab1..6faaa5ed 100644 --- a/api/v2/comments_actions.ts +++ b/api/v2/comments_actions.ts @@ -72,10 +72,10 @@ export const comments_actions = async (params: T, addons?: IDe }; - if (params.commentable_type) object['comment[commentable_type]'] = params.commentable_type; - if (params.parent_id) object['comment[parent_id]'] = params.parent_id; - if (params.id) object['comment[commentable_id]'] = params.id; - if (params.message) object['comment[message]'] = params.message; + object['comment[commentable_type]'] = params.commentable_type; + object['comment[parent_id]'] = params.parent_id; + object['comment[commentable_id]'] = params.id; + object['comment[message]'] = params.message; break; case 'edit': @@ -126,6 +126,9 @@ export const comments_actions = async (params: T, addons?: IDe method = 'DELETE'; break; + + default: + return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; }; diff --git a/api/v2/comments_list.ts b/api/v2/comments_list.ts index d4e6c3b8..d4d69bab 100644 --- a/api/v2/comments_list.ts +++ b/api/v2/comments_list.ts @@ -17,20 +17,17 @@ export const comments_list = async (params: { }; sort?: 'new' | 'old' | 'top'; }, addons?: IDefaultParams): Promise => { - const object = { - after: params.after_id, - commentable_type: params.type, - commentable_id: params.id, - 'cursor[id]': params.cursor?.id, - 'cursor[created_at]': params.cursor?.created_at, - parent_id: params.parent_id, - sort: params.sort, - }; - - const data = await request(`https://osu.ppy.sh/api/v2/comments`, { method: 'GET', - params: object, + params: { + after: params.after_id, + commentable_type: params.type, + commentable_id: params.id, + 'cursor[id]': params.cursor?.id, + 'cursor[created_at]': params.cursor?.created_at, + parent_id: params.parent_id, + sort: params.sort, + }, addons, }); diff --git a/api/v2/forums_topics_actions.ts b/api/v2/forums_topics_actions.ts index 3551459e..29a50894 100644 --- a/api/v2/forums_topics_actions.ts +++ b/api/v2/forums_topics_actions.ts @@ -193,6 +193,9 @@ export const forums_topics_actions = async (params: T, addons? object = {}; }; break; + + default: + return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; }; diff --git a/api/v2/forums_topics_details.ts b/api/v2/forums_topics_details.ts index 739f93d3..743464e0 100644 --- a/api/v2/forums_topics_details.ts +++ b/api/v2/forums_topics_details.ts @@ -19,20 +19,17 @@ export const forums_topics_details = async (params: { }; - const object = { - start: params.start_id, - end: params.end_id, - - sort: params.sort, - limit: params.limit, - - cursor_string: params.cursor_string, - }; - - const data = await request(`https://osu.ppy.sh/api/v2/forums/topics/${params.id}`, { method: 'GET', - params: object, + params: { + start: params.start_id, + end: params.end_id, + + sort: params.sort, + limit: params.limit, + + cursor_string: params.cursor_string, + }, addons, }); diff --git a/api/v2/matches_list.ts b/api/v2/matches_list.ts index 4d6671c9..a5b641b8 100644 --- a/api/v2/matches_list.ts +++ b/api/v2/matches_list.ts @@ -12,16 +12,13 @@ export const matches_list = async (params: { */ after_id: number; }, addons?: IDefaultParams): Promise => { - const object = { - limit: params.limit, - sort: params.sort, - 'cursor[match_id]': params.after_id, - }; - - const data = await request(`https://osu.ppy.sh/api/v2/matches`, { method: 'GET', - params: object, + params: { + limit: params.limit, + sort: params.sort, + 'cursor[match_id]': params.after_id, + }, addons, }); diff --git a/api/v2/me_details.ts b/api/v2/me_details.ts index 488c0aa0..08c833ef 100644 --- a/api/v2/me_details.ts +++ b/api/v2/me_details.ts @@ -19,5 +19,6 @@ export const me_details = async (addons?: IDefaultParams & { mode: Modes_names } addons, }); + return data; }; \ No newline at end of file diff --git a/api/v2/me_download_quota.ts b/api/v2/me_download_quota.ts index 29e99e67..f7b44a1b 100644 --- a/api/v2/me_download_quota.ts +++ b/api/v2/me_download_quota.ts @@ -15,5 +15,6 @@ export const me_download_quota = async (): Promise => { - const object: any = {}; - if (params.from_year != null) object.year = params.from_year; - if (params.limit != null) object.limit = params.limit; - if (params.cursor_string != null) object.cursor_string = params.cursor_string; + const object: any = { + year: params.from_year, + limit: params.limit, + cursor_string: params.cursor_string, + }; const data = await request(`https://osu.ppy.sh/api/v2/news`, { diff --git a/api/v2/notification_actions.ts b/api/v2/notification_actions.ts index d4f1d863..0cb3dc2b 100644 --- a/api/v2/notification_actions.ts +++ b/api/v2/notification_actions.ts @@ -53,6 +53,9 @@ export const notification_actions = async (params: T, addons?: object['identities'] = params.identities; }; break; + + default: + return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; }; diff --git a/api/v2/notifications_list.ts b/api/v2/notifications_list.ts index c6004500..1589eea1 100644 --- a/api/v2/notifications_list.ts +++ b/api/v2/notifications_list.ts @@ -8,13 +8,11 @@ export const notifications_list = async (params: { max_id: string; unreaded_only: boolean; }, addons?: IDefaultParams): Promise => { - const object: any = {}; - if (params.max_id != null) object.max_id = params.max_id; - - const data = await request(`https://osu.ppy.sh/api/v2/notifications`, { method: 'GET', - params: object, + params: { + max_id: params.max_id + }, addons, }); diff --git a/api/v2/ranking_list.ts b/api/v2/ranking_list.ts index 66eadc80..464ba5a2 100644 --- a/api/v2/ranking_list.ts +++ b/api/v2/ranking_list.ts @@ -54,10 +54,11 @@ type Response = export const ranking_list = async (params: T, addons?: IDefaultParams): Promise> => { - if (params.type != 'kudosu' && params.mode == null) + if (params.type != 'kudosu' && params.mode == null) { return { error: new Error('Gamemode not specified'), } as Response; + }; let object: any = {}; @@ -68,40 +69,40 @@ export const ranking_list = async (params: T, addons?: IDefaul case 'charts': url += `/rankings/${params.mode}/${params.type}`; - if (params.page != null) object['cursor[page]'] = params.page; - if (params.filter != null) object.filter = params.filter; - if (params.spotlight_id != null) object.spotlight = params.spotlight_id; + object['cursor[page]'] = params.page; + object.filter = params.filter; + object.spotlight = params.spotlight_id; break; case 'country': url += `/rankings/${params.mode}/${params.type}`; - if (params.page != null) object['cursor[page]'] = params.page; - if (params.filter != null) object.filter = params.filter; + object['cursor[page]'] = params.page; + object.filter = params.filter; break; case 'performance': url += `/rankings/${params.mode}/${params.type}`; - if (params.page != null) object['cursor[page]'] = params.page; - if (params.filter != null) object.filter = params.filter; - if (params.country_code != null) object.country = params.country_code; - if (params.variant != null) object.variant = params.variant; + object['cursor[page]'] = params.page; + object.filter = params.filter; + object.country = params.country_code; + object.variant = params.variant; break; case 'score': url += `/rankings/${params.mode}/${params.type}`; - if (params.page != null) object['cursor[page]'] = params.page; - if (params.filter != null) object.filter = params.filter; + object['cursor[page]'] = params.page; + object.filter = params.filter; break; case 'kudosu': url += `/rankings/kudosu`; - if (params.page != null) object.page = params.page; + object.page = params.page; break; default: diff --git a/api/v2/rooms_list.ts b/api/v2/rooms_list.ts index d87aeff4..82f05e64 100644 --- a/api/v2/rooms_list.ts +++ b/api/v2/rooms_list.ts @@ -15,21 +15,19 @@ export const rooms_list = async (params: { cursor_string?: string; }, addons?: IDefaultParams): Promise => { - const object = { - type_group: params.type, - mode: params.show, - sort: params.sort, - limit: params.limit, - cursor_string: params.cursor_string, - }; - if (addons == null) addons = { apiVersion: '99999999' } const data = await request(`https://osu.ppy.sh/api/v2/rooms`, { method: 'GET', - params: object, + params: { + type_group: params.type, + mode: params.show, + sort: params.sort, + limit: params.limit, + cursor_string: params.cursor_string, + }, addons, }); diff --git a/api/v2/rooms_scores.ts b/api/v2/rooms_scores.ts index 3ff7d92b..103e1d17 100644 --- a/api/v2/rooms_scores.ts +++ b/api/v2/rooms_scores.ts @@ -59,9 +59,9 @@ export const rooms_scores = async (params: T, addons?: IDefaul case 'all': url += `/rooms/${params.id}/playlist/${params.playlist_id}/scores`; - if (params.limit != null) object.limit = params.limit; - if (params.sort != null) object.sort = params.sort; - if (params.cursor_string != null) object.cursor_string = params.cursor_string; + object.limit = params.limit; + object.sort = params.sort; + object.cursor_string = params.cursor_string; break; case 'single': @@ -73,6 +73,9 @@ export const rooms_scores = async (params: T, addons?: IDefaul url += `/rooms/${params.id}/playlist/${params.playlist_id}/scores/users/${params.user_id}`; break; + + default: + return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; }; diff --git a/api/v2/session_actions.ts b/api/v2/session_actions.ts index 6047ed0f..6f24dfa4 100644 --- a/api/v2/session_actions.ts +++ b/api/v2/session_actions.ts @@ -23,7 +23,6 @@ type Response = // FIXME? export const session_actions = async (params: T, addons?: IDefaultParams): Promise> => { - const object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; let method = 'POST'; @@ -49,7 +48,6 @@ export const session_actions = async (params: T, addons?: IDef const data = await request(url, { method: method, - params: object, addons, }); diff --git a/api/v2/users_events.ts b/api/v2/users_events.ts index 35b5395b..ba2d4aac 100644 --- a/api/v2/users_events.ts +++ b/api/v2/users_events.ts @@ -9,18 +9,21 @@ export const users_events = async ({ sort, cursor_string, type }: { sort?: 'id_desc' | 'id_asc', cursor_string?: string; } = {}, addons?: IDefaultParams): Promise => { - const data: UsersEventsResponse = await request(`https://osu.ppy.sh/api/v2/events`, { + const data: any = await request(`https://osu.ppy.sh/api/v2/events`, { method: 'GET', params: { sort: sort, cursor_string: cursor_string }, addons, }); + if (data.error) return data.error; + if (!Array.isArray(type)) { return { error: new Error(`Events Type must be an Array of types. Example: ['achievement', 'rank']`) }; }; - const sorted = data.events.filter(r => type.includes(r.type)); + + const sorted = data.events.filter((r: any) => type.includes(r.type)); data.events = sorted; return data; diff --git a/package.json b/package.json index 64193f09..a2632dcc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.27", + "version": "3.0.0-beta.30", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/utility/request.ts b/utility/request.ts index ded5869d..18957083 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -25,6 +25,21 @@ export interface RequestType { let total_retries = 0; +const sanitize_query = (obj: object): string => { + const object: any = Object.assign({}, obj); + + const array = Object.keys(object); + for (let i = 0; i < array.length; i++) { + const key = array[i]; + const value = object[key]; + + if (value != null) continue; + delete object[key]; + }; + + return querystring.encode(object); +}; + export const request: RequestType = (url, { method, headers, data, params = {}, addons = {} }) => new Promise((resolve, reject) => { // check required args @@ -66,7 +81,7 @@ export const request: RequestType = (url, { method, headers, data, params = {}, params.legacy_only = params.legacy_only == true ? 1 : 0; - const generate_query = querystring.encode(params); + const generate_query = sanitize_query(params); const build_url = url + (generate_query ? `?${generate_query}` : ''); // console.log({ url: build_url, method, headers, data, generate_query, params }); // debug @@ -185,7 +200,7 @@ export const download = (url: string, dest: string, { _callback, headers = {}, d if (!headers['accept']) headers['accept'] = `application/octet-stream`; - const generate_query = querystring.encode(params); + const generate_query = sanitize_query(params); const build_url = url + (generate_query ? `?${generate_query}` : ''); // console.log({ url: build_url, headers, data }); // debug From caa33a8e47db3063832bb94efc8cdb324761f6b4 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 27 Apr 2024 11:27:48 +0300 Subject: [PATCH 130/259] mods test --- tools/mods.ts | 419 +++++++++++++++++++++++++++++++++++-------------- types/enums.ts | 100 +++++++++++- 2 files changed, 394 insertions(+), 125 deletions(-) diff --git a/tools/mods.ts b/tools/mods.ts index ce6bf6a4..b1cd6a26 100644 --- a/tools/mods.ts +++ b/tools/mods.ts @@ -1,142 +1,317 @@ -const num_codes: { [key: string]: string } = { - 1: 'NF', - 2: 'EZ', - 4: 'TD', - 8: 'HD', - 16: 'HR', - 32: 'SD', - 64: 'DT', - 128: 'RX', - 256: 'HT', - 576: 'NC', - 1024: 'FL', - 2048: 'AT', - 4096: 'SO', - 8192: 'AP', - 16416: 'PF', - 32768: '4K', - 65536: '5K', - 131072: '6K', - 262144: '7K', - 524288: '8K', - 1048576: 'FI', - 2097152: 'RD', - 4194304: 'LM', - 8388608: 'Target', - 16777216: '9K', - 33554432: 'KeyCoop', - 67108864: '1K', - 134217728: '3K', - 268435456: '2K', - 536870912: 'ScoreV2', - 1073741824: 'MR', -}; +import { IError } from "../types"; +import { ModsCodes, ModsOrder } from "../types/enums"; -export const enums = { - None: 0, - NoFail: 1, - Easy: 1 << 1, - TouchDevice: 1 << 2, - Hidden: 1 << 3, - HardRock: 1 << 4, - SuddenDeath: 1 << 5, - DoubleTime: 1 << 6, - Relax: 1 << 7, - HalfTime: 1 << 8, - Nightcore: 1 << 9, // DoubleTime mod - Flashlight: 1 << 10, - Autoplay: 1 << 11, - SpunOut: 1 << 12, - Relax2: 1 << 13, // Autopilot - Perfect: 1 << 14, // SuddenDeath mod - Key4: 1 << 15, - Key5: 1 << 16, - Key6: 1 << 17, - Key7: 1 << 18, - Key8: 1 << 19, - FadeIn: 1 << 20, - Random: 1 << 21, - Cinema: 1 << 22, - Target: 1 << 23, - Key9: 1 << 24, - KeyCoop: 1 << 25, - Key1: 1 << 26, - Key3: 1 << 27, - Key2: 1 << 28, - KeyMod: 521109504, - FreeModAllowed: 522171579, - ScoreIncreaseMods: 1049662 -}; -const mods_order: { [key: string]: number } = { - nf: 0, - ez: 1, - hd: 2, - dt: 3, - nc: 3, - ht: 3, - hr: 4, - so: 5, - sd: 5, - pf: 5, - fl: 6, - td: 7, -}; -/** - * - * @param mods Mods number - * @returns {string} Mods name - */ -const name = (mods: number): string => { - let enabled = []; - let _mods = mods; - let converted = ''; +export const ModsToName = (modsNumber: number): string => { + const convertedParts = []; + const values = Object.keys(ModsCodes); + let mods_id = modsNumber; - const values = Object.keys(num_codes).map(a => Number(a)); - for (let i = values.length - 1; i >= 0; i--) { + for (let i = values.length - 1; i >= 0 && mods_id > 0; i--) { const v = values[i]; - if (_mods >= v) { - const mode = num_codes[v]; - enabled.push({ i: mods_order[mode.toLowerCase()], n: mode }); - _mods -= v; + if (mods_id >= +v) { + const mode = ModsCodes[v]; + convertedParts.push(mode); + mods_id -= +v; }; }; - enabled = enabled.sort((a, b) => (a.i > b.i ? 1 : b.i > a.i ? -1 : 0)); - enabled.filter(r => converted += r.n); + convertedParts.sort((a, b) => ModsOrder[a.toLowerCase()] - ModsOrder[b.toLowerCase()]); - // if (converted === '') return 'NM'; + + const converted = convertedParts.join(''); return converted; }; -/** - * - * @param mods Mods name - * @returns {string | undefined} Mods number - */ -const id = (mods: string | number): number | undefined => { - if (!mods) return undefined; - if (typeof mods == 'number') return mods; - - let _mods = 0; - const name = mods.match(/.{1,2}/g); - if (name == null) return undefined; - - const values: string[] = Object.keys(num_codes).map((a) => a); - for (let i = 0; i < name.length; i++) { - const find = values.find((v) => num_codes[v].toLowerCase() === name[i].toLowerCase()); - if (!find) continue; - - _mods += parseInt(find); + +export const calculate_mods = (ModsName: string | number): { number: number, name: string } | IError => { + if (ModsName == null) { + return { error: new Error(`Specify mods name (HDDT or 72)`) }; + }; + + + if (typeof ModsName == 'number') { + const name = ModsToName(ModsName); + return { + number: ModsName, + name: name, + }; + }; + + + let mods_id = 0; + const ModsArray = ModsName.match(/.{1,2}/g); + if (!Array.isArray(ModsArray)) { + return { error: new Error(`Can't convert mods (${ModsName}) to array of mods`) }; }; - return _mods; + + const codes = Object.keys(ModsCodes); + for (let i = 0; i < ModsArray.length; i++) { + const mod_name = ModsArray[i]; + + const find = codes.find(v => ModsCodes[v].toLowerCase() === mod_name?.toLowerCase()); + if (find == null) continue; + + mods_id += parseInt(find); + }; + + + return { + number: mods_id, + name: ModsName, + }; }; -export { id, name, num_codes }; -export default { id, name, enums, num_codes }; \ No newline at end of file + +export const calculate_mods_switch = (ModsName: string | number): { number: number, name: string } | IError => { + if (ModsName == null) { + return { error: new Error(`Specify mods name (HDDT or 72)`) }; + }; + + + if (typeof ModsName == 'number') { + const name = ModsToName(ModsName); + return { + number: ModsName, + name: name, + }; + }; + + + let mods_id = 0; + + const ModsArray = ModsName.toLowerCase().match(/.{1,2}/g); + if (!Array.isArray(ModsArray)) { + return { error: new Error(`Can't convert mods (${ModsName}) to array of mods`) }; + }; + + + for (let i = 0; i < ModsArray.length; i++) { + const mod_name = ModsArray[i]; + switch (mod_name) { + case 'nf': + mods_id += 1; + break; + case 'ez': + mods_id += 2; + break; + case 'td': + mods_id += 4; + break; + case 'hd': + mods_id += 8; + break; + case 'hr': + mods_id += 16; + break; + case 'sd': + mods_id += 32; + break; + case 'dt': + mods_id += 64; + break; + case 'rx': + mods_id += 128; + break; + case 'ht': + mods_id += 256; + break; + case 'nc': + mods_id += 576; + break; + case 'fl': + mods_id += 1024; + break; + case 'at': + mods_id += 2048; + break; + case 'so': + mods_id += 4096; + break; + case 'ap': + mods_id += 8192; + break; + case 'pf': + mods_id += 16416; + break; + case '4k': + mods_id += 32768; + break; + case '5k': + mods_id += 65536; + break; + case '6k': + mods_id += 131072; + break; + case '7k': + mods_id += 262144; + break; + case '8k': + mods_id += 524288; + break; + case 'fi': + mods_id += 1048576; + break; + case 'rd': + mods_id += 2097152; + break; + case 'lm': + mods_id += 4194304; + break; + case 'target': + mods_id += 8388608; + break; + case '9k': + mods_id += 16777216; + break; + case 'keycoop': + mods_id += 33554432; + break; + case '1k': + mods_id += 67108864; + break; + case '3k': + mods_id += 134217728; + break; + case '2k': + mods_id += 268435456; + break; + case 'scorev2': + mods_id += 536870912; + break; + case 'mr': + mods_id += 1073741824; + break; + }; + }; + + + return { + number: mods_id, + name: ModsName, + }; +}; + + +export const calculate_mods_if = (ModsName: string | number): { number: number, name: string } | IError => { + if (ModsName == null) { + return { error: new Error(`Specify mods name (HDDT or 72)`) }; + } + + if (typeof ModsName === 'number') { + return { + number: ModsName, + name: ModsToName(ModsName), + }; + } + + + let mods_id = 0; + let mods_name = ModsName.toLowerCase(); + + if (mods_name.includes('nf')) { + mods_id += 1; + } + if (mods_name.includes('ez')) { + mods_id += 2; + } + if (mods_name.includes('td')) { + mods_id += 4; + } + if (mods_name.includes('hd')) { + mods_id += 8; + } + if (mods_name.includes('hr')) { + mods_id += 16; + } + if (mods_name.includes('sd')) { + mods_id += 32; + } + if (mods_name.includes('dt')) { + mods_id += 64; + } + if (mods_name.includes('rx')) { + mods_id += 128; + } + if (mods_name.includes('ht')) { + mods_id += 256; + } + if (mods_name.includes('nc')) { + mods_id += 576; + } + if (mods_name.includes('fl')) { + mods_id += 1024; + } + if (mods_name.includes('at')) { + mods_id += 2048; + } + if (mods_name.includes('so')) { + mods_id += 4096; + } + if (mods_name.includes('ap')) { + mods_id += 8192; + } + if (mods_name.includes('pf')) { + mods_id += 16416; + } + if (mods_name.includes('4k')) { + mods_id += 32768; + } + if (mods_name.includes('5k')) { + mods_id += 65536; + } + if (mods_name.includes('6k')) { + mods_id += 131072; + } + if (mods_name.includes('7k')) { + mods_id += 262144; + } + if (mods_name.includes('8k')) { + mods_id += 524288; + } + if (mods_name.includes('fi')) { + mods_id += 1048576; + } + if (mods_name.includes('rd')) { + mods_id += 2097152; + } + if (mods_name.includes('lm')) { + mods_id += 4194304; + } + if (mods_name.includes('target')) { + mods_id += 8388608; + } + if (mods_name.includes('9k')) { + mods_id += 16777216; + } + if (mods_name.includes('keycoop')) { + mods_id += 33554432; + } + if (mods_name.includes('1k')) { + mods_id += 67108864; + } + if (mods_name.includes('3k')) { + mods_id += 134217728; + } + if (mods_name.includes('2k')) { + mods_id += 268435456; + } + if (mods_name.includes('scorev2')) { + mods_id += 536870912; + } + if (mods_name.includes('mr')) { + mods_id += 1073741824; + } + + + return { + number: mods_id, + name: ModsName, + }; +}; \ No newline at end of file diff --git a/types/enums.ts b/types/enums.ts index a0735817..61e4c8b5 100644 --- a/types/enums.ts +++ b/types/enums.ts @@ -1,10 +1,11 @@ -export enum Modes_enums { +export enum GamemodeEnum { osu = 0, taiko = 1, fruits = 2, mania = 3, }; + export enum Genres_enum { 'Unspecified', 'Video Game', @@ -19,7 +20,8 @@ export enum Genres_enum { 'Classical', 'Folk', 'Jazz' -} +}; + export enum Languages_enum { Any, @@ -37,4 +39,96 @@ export enum Languages_enum { Instrumental, Unspecified, Other, -} \ No newline at end of file +}; + + +export const ModsCodes: { + [key: string]: string; +} = { + 1: 'NF', + 2: 'EZ', + 4: 'TD', + 8: 'HD', + 16: 'HR', + 32: 'SD', + 64: 'DT', + 128: 'RX', + 256: 'HT', + 576: 'NC', + 1024: 'FL', + 2048: 'AT', + 4096: 'SO', + 8192: 'AP', + 16416: 'PF', + 32768: '4K', + 65536: '5K', + 131072: '6K', + 262144: '7K', + 524288: '8K', + 1048576: 'FI', + 2097152: 'RD', + 4194304: 'LM', + 8388608: 'Target', + 16777216: '9K', + 33554432: 'KeyCoop', + 67108864: '1K', + 134217728: '3K', + 268435456: '2K', + 536870912: 'ScoreV2', + 1073741824: 'MR', +}; + + +export const ModsBitwise = { + None: 0, + NoFail: 1, + Easy: 1 << 1, + TouchDevice: 1 << 2, + Hidden: 1 << 3, + HardRock: 1 << 4, + SuddenDeath: 1 << 5, + DoubleTime: 1 << 6, + Relax: 1 << 7, + HalfTime: 1 << 8, + Nightcore: 1 << 9, // DoubleTime mod + Flashlight: 1 << 10, + Autoplay: 1 << 11, + SpunOut: 1 << 12, + Relax2: 1 << 13, // Autopilot + Perfect: 1 << 14, // SuddenDeath mod + Key4: 1 << 15, + Key5: 1 << 16, + Key6: 1 << 17, + Key7: 1 << 18, + Key8: 1 << 19, + FadeIn: 1 << 20, + Random: 1 << 21, + Cinema: 1 << 22, + Target: 1 << 23, + Key9: 1 << 24, + KeyCoop: 1 << 25, + Key1: 1 << 26, + Key3: 1 << 27, + Key2: 1 << 28, + KeyMod: 521109504, + FreeModAllowed: 522171579, + ScoreIncreaseMods: 1049662 +}; + + +export const ModsOrder: { + [key: string]: number; +} = { + nf: 0, + ez: 1, + hd: 2, + dt: 3, + nc: 3, + ht: 3, + hr: 4, + so: 5, + sd: 5, + pf: 5, + fl: 6, + td: 7, +}; \ No newline at end of file From 9e4ca2091eace67da55c92764e41c9b2ad994eb9 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 27 Apr 2024 11:59:20 +0300 Subject: [PATCH 131/259] testing modsToName speed --- tools/mods.ts | 337 ++++++++++++++++++++++++++++---------------------- 1 file changed, 192 insertions(+), 145 deletions(-) diff --git a/tools/mods.ts b/tools/mods.ts index b1cd6a26..7efd90af 100644 --- a/tools/mods.ts +++ b/tools/mods.ts @@ -4,7 +4,10 @@ import { ModsCodes, ModsOrder } from "../types/enums"; -export const ModsToName = (modsNumber: number): string => { +export const ModsToName = (modsNumber: number, order?: boolean): string => { + if (modsNumber == 0) return ''; + + const convertedParts = []; const values = Object.keys(ModsCodes); let mods_id = modsNumber; @@ -20,7 +23,9 @@ export const ModsToName = (modsNumber: number): string => { }; - convertedParts.sort((a, b) => ModsOrder[a.toLowerCase()] - ModsOrder[b.toLowerCase()]); + if (order) { + convertedParts.sort((a, b) => ModsOrder[a.toLowerCase()] - ModsOrder[b.toLowerCase()]); + }; const converted = convertedParts.join(''); @@ -28,48 +33,208 @@ export const ModsToName = (modsNumber: number): string => { }; -export const calculate_mods = (ModsName: string | number): { number: number, name: string } | IError => { - if (ModsName == null) { - return { error: new Error(`Specify mods name (HDDT or 72)`) }; - }; +export const ModsToName1 = (modsNumber: number, order?: boolean): string => { + if (modsNumber == 0) return ''; - if (typeof ModsName == 'number') { - const name = ModsToName(ModsName); - return { - number: ModsName, - name: name, - }; + const convertedParts = []; + + // NF + if (modsNumber & 1) convertedParts.push('NF'); + // EZ + if (modsNumber & 2) convertedParts.push('EZ'); + // TD + if (modsNumber & 4) convertedParts.push('TD'); + // HD + if (modsNumber & 8) convertedParts.push('HD'); + // HR + if (modsNumber & 16) convertedParts.push('HR'); + // SD + if (modsNumber & 32) convertedParts.push('SD'); + // DT + if (modsNumber & 64) convertedParts.push('DT'); + // RX + if (modsNumber & 128) convertedParts.push('RX'); + // HT + if (modsNumber & 256) convertedParts.push('HT'); + // NC + if (modsNumber & 576) convertedParts.push('NC'); + // FL + if (modsNumber & 1024) convertedParts.push('FL'); + // AT + if (modsNumber & 2048) convertedParts.push('AT'); + // SO + if (modsNumber & 4096) convertedParts.push('SO'); + // AP + if (modsNumber & 8192) convertedParts.push('AP'); + // PF + if (modsNumber & 16416) convertedParts.push('PF'); + // 4K + if (modsNumber & 32768) convertedParts.push('4K'); + // 5K + if (modsNumber & 65536) convertedParts.push('5K'); + // 6K + if (modsNumber & 131072) convertedParts.push('6K'); + // 7K + if (modsNumber & 262144) convertedParts.push('7K'); + // 8K + if (modsNumber & 524288) convertedParts.push('8K'); + // FI + if (modsNumber & 1048576) convertedParts.push('FI'); + // RD + if (modsNumber & 2097152) convertedParts.push('RD'); + // LM + if (modsNumber & 4194304) convertedParts.push('LM'); + // Target + if (modsNumber & 8388608) convertedParts.push('Target'); + // 9K + if (modsNumber & 16777216) convertedParts.push('9K'); + // KeyCoop + if (modsNumber & 33554432) convertedParts.push('KeyCoop'); + // 1K + if (modsNumber & 67108864) convertedParts.push('1K'); + // 3K + if (modsNumber & 134217728) convertedParts.push('3K'); + // 2K + if (modsNumber & 268435456) convertedParts.push('2K'); + // ScoreV2 + if (modsNumber & 536870912) convertedParts.push('ScoreV2'); + // MR + if (modsNumber & 1073741824) convertedParts.push('MR'); + + + if (order) { + convertedParts.sort((a, b) => ModsOrder[a.toLowerCase()] - ModsOrder[b.toLowerCase()]); }; - let mods_id = 0; - const ModsArray = ModsName.match(/.{1,2}/g); - if (!Array.isArray(ModsArray)) { - return { error: new Error(`Can't convert mods (${ModsName}) to array of mods`) }; - }; + const converted = convertedParts.join(''); + return converted; +}; - const codes = Object.keys(ModsCodes); - for (let i = 0; i < ModsArray.length; i++) { - const mod_name = ModsArray[i]; +export const ModsToName2 = (modsNumber: number, order?: boolean): string => { + const convertedParts = []; + let bit = 1; + + + while (bit <= modsNumber) { + switch (bit) { + case 1: + if (modsNumber & bit) convertedParts.push('NF'); + break; + case 2: + if (modsNumber & bit) convertedParts.push('EZ'); + break; + case 4: + if (modsNumber & bit) convertedParts.push('TD'); + break; + case 8: + if (modsNumber & bit) convertedParts.push('HD'); + break; + case 16: + if (modsNumber & bit) convertedParts.push('HR'); + break; + case 32: + if (modsNumber & bit) convertedParts.push('SD'); + break; + case 64: + if (modsNumber & bit) convertedParts.push('DT'); + break; + case 128: + if (modsNumber & bit) convertedParts.push('RX'); + break; + case 256: + if (modsNumber & bit) convertedParts.push('HT'); + break; + case 576: + if (modsNumber & bit) convertedParts.push('NC'); + break; + case 1024: + if (modsNumber & bit) convertedParts.push('FL'); + break; + case 2048: + if (modsNumber & bit) convertedParts.push('AT'); + break; + case 4096: + if (modsNumber & bit) convertedParts.push('SO'); + break; + case 8192: + if (modsNumber & bit) convertedParts.push('AP'); + break; + case 16416: + if (modsNumber & bit) convertedParts.push('PF'); + break; + case 32768: + if (modsNumber & bit) convertedParts.push('4K'); + break; + case 65536: + if (modsNumber & bit) convertedParts.push('5K'); + break; + case 131072: + if (modsNumber & bit) convertedParts.push('6K'); + break; + case 262144: + if (modsNumber & bit) convertedParts.push('7K'); + break; + case 524288: + if (modsNumber & bit) convertedParts.push('8K'); + break; + case 1048576: + if (modsNumber & bit) convertedParts.push('FI'); + break; + case 2097152: + if (modsNumber & bit) convertedParts.push('RD'); + break; + case 4194304: + if (modsNumber & bit) convertedParts.push('LM'); + break; + case 8388608: + if (modsNumber & bit) convertedParts.push('Target'); + break; + case 16777216: + if (modsNumber & bit) convertedParts.push('9K'); + break; + case 33554432: + if (modsNumber & bit) convertedParts.push('KeyCoop'); + break; + case 67108864: + if (modsNumber & bit) convertedParts.push('1K'); + break; + case 134217728: + if (modsNumber & bit) convertedParts.push('3K'); + break; + case 268435456: + if (modsNumber & bit) convertedParts.push('2K'); + break; + case 536870912: + if (modsNumber & bit) convertedParts.push('ScoreV2'); + break; + case 1073741824: + if (modsNumber & bit) convertedParts.push('MR'); + break; + default: + break; + }; - const find = codes.find(v => ModsCodes[v].toLowerCase() === mod_name?.toLowerCase()); - if (find == null) continue; - mods_id += parseInt(find); + bit <<= 1; }; - return { - number: mods_id, - name: ModsName, + if (order) { + convertedParts.sort((a, b) => ModsOrder[a.toLowerCase()] - ModsOrder[b.toLowerCase()]); }; + + + const converted = convertedParts.join(''); + return converted; }; -export const calculate_mods_switch = (ModsName: string | number): { number: number, name: string } | IError => { +// SWITCH STATEMENT CREATED ON PURPOSE BECAUSE IT'S WAY FASTER +export const calculate_mods = (ModsName: string | number): { number: number, name: string } | IError => { if (ModsName == null) { return { error: new Error(`Specify mods name (HDDT or 72)`) }; }; @@ -192,124 +357,6 @@ export const calculate_mods_switch = (ModsName: string | number): { number: numb }; - return { - number: mods_id, - name: ModsName, - }; -}; - - -export const calculate_mods_if = (ModsName: string | number): { number: number, name: string } | IError => { - if (ModsName == null) { - return { error: new Error(`Specify mods name (HDDT or 72)`) }; - } - - if (typeof ModsName === 'number') { - return { - number: ModsName, - name: ModsToName(ModsName), - }; - } - - - let mods_id = 0; - let mods_name = ModsName.toLowerCase(); - - if (mods_name.includes('nf')) { - mods_id += 1; - } - if (mods_name.includes('ez')) { - mods_id += 2; - } - if (mods_name.includes('td')) { - mods_id += 4; - } - if (mods_name.includes('hd')) { - mods_id += 8; - } - if (mods_name.includes('hr')) { - mods_id += 16; - } - if (mods_name.includes('sd')) { - mods_id += 32; - } - if (mods_name.includes('dt')) { - mods_id += 64; - } - if (mods_name.includes('rx')) { - mods_id += 128; - } - if (mods_name.includes('ht')) { - mods_id += 256; - } - if (mods_name.includes('nc')) { - mods_id += 576; - } - if (mods_name.includes('fl')) { - mods_id += 1024; - } - if (mods_name.includes('at')) { - mods_id += 2048; - } - if (mods_name.includes('so')) { - mods_id += 4096; - } - if (mods_name.includes('ap')) { - mods_id += 8192; - } - if (mods_name.includes('pf')) { - mods_id += 16416; - } - if (mods_name.includes('4k')) { - mods_id += 32768; - } - if (mods_name.includes('5k')) { - mods_id += 65536; - } - if (mods_name.includes('6k')) { - mods_id += 131072; - } - if (mods_name.includes('7k')) { - mods_id += 262144; - } - if (mods_name.includes('8k')) { - mods_id += 524288; - } - if (mods_name.includes('fi')) { - mods_id += 1048576; - } - if (mods_name.includes('rd')) { - mods_id += 2097152; - } - if (mods_name.includes('lm')) { - mods_id += 4194304; - } - if (mods_name.includes('target')) { - mods_id += 8388608; - } - if (mods_name.includes('9k')) { - mods_id += 16777216; - } - if (mods_name.includes('keycoop')) { - mods_id += 33554432; - } - if (mods_name.includes('1k')) { - mods_id += 67108864; - } - if (mods_name.includes('3k')) { - mods_id += 134217728; - } - if (mods_name.includes('2k')) { - mods_id += 268435456; - } - if (mods_name.includes('scorev2')) { - mods_id += 536870912; - } - if (mods_name.includes('mr')) { - mods_id += 1073741824; - } - - return { number: mods_id, name: ModsName, From ee76874a72f41e8c1a42049ee5bdc2c822b2dc99 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 27 Apr 2024 12:05:21 +0300 Subject: [PATCH 132/259] improve mods a little bit --- tools/index.ts | 54 ++++++++++++++++++----- tools/mods.ts | 117 ++----------------------------------------------- 2 files changed, 46 insertions(+), 125 deletions(-) diff --git a/tools/index.ts b/tools/index.ts index 12fad69c..a834e560 100644 --- a/tools/index.ts +++ b/tools/index.ts @@ -1,17 +1,47 @@ -export const postDataArray = (field_name: string, array: any[]) => { - const data = array.map((data, index) => { - return postDataObject(`${field_name}[${index}]`, data); - }).join('&'); +import { calculate_accuracy } from "./accuracy"; +import { calculate_mods } from "./mods"; - return data; +export const calculate = { + accuracy: calculate_accuracy, + /** + * Hello world + */ + mods: calculate_mods, }; -export const postDataObject = (field_name: string, object: object) => { - return Object.entries(object).map(([key, value]) => { - if (field_name == '') - return `${key}=${encodeURIComponent(value as any)}`; - return `${field_name}[${key}]=${encodeURIComponent(value as any)}`; - }).join('&'); -}; \ No newline at end of file + + + + + + + + + + + + + + + + + +// const postDataArray = (field_name: string, array: any[]) => { +// const data = array.map((data, index) => { +// return postDataObject(`${field_name}[${index}]`, data); +// }).join('&'); + + +// return data; +// }; + +// const postDataObject = (field_name: string, object: object) => { +// return Object.entries(object).map(([key, value]) => { +// if (field_name == '') +// return `${key}=${encodeURIComponent(value as any)}`; + +// return `${field_name}[${key}]=${encodeURIComponent(value as any)}`; +// }).join('&'); +// }; \ No newline at end of file diff --git a/tools/mods.ts b/tools/mods.ts index 7efd90af..47939adf 100644 --- a/tools/mods.ts +++ b/tools/mods.ts @@ -1,119 +1,10 @@ import { IError } from "../types"; -import { ModsCodes, ModsOrder } from "../types/enums"; - +import { ModsOrder } from "../types/enums"; +// WHILE LOOP FASTER dot export const ModsToName = (modsNumber: number, order?: boolean): string => { - if (modsNumber == 0) return ''; - - - const convertedParts = []; - const values = Object.keys(ModsCodes); - let mods_id = modsNumber; - - - for (let i = values.length - 1; i >= 0 && mods_id > 0; i--) { - const v = values[i]; - if (mods_id >= +v) { - const mode = ModsCodes[v]; - convertedParts.push(mode); - mods_id -= +v; - }; - }; - - - if (order) { - convertedParts.sort((a, b) => ModsOrder[a.toLowerCase()] - ModsOrder[b.toLowerCase()]); - }; - - - const converted = convertedParts.join(''); - return converted; -}; - - -export const ModsToName1 = (modsNumber: number, order?: boolean): string => { - if (modsNumber == 0) return ''; - - - const convertedParts = []; - - // NF - if (modsNumber & 1) convertedParts.push('NF'); - // EZ - if (modsNumber & 2) convertedParts.push('EZ'); - // TD - if (modsNumber & 4) convertedParts.push('TD'); - // HD - if (modsNumber & 8) convertedParts.push('HD'); - // HR - if (modsNumber & 16) convertedParts.push('HR'); - // SD - if (modsNumber & 32) convertedParts.push('SD'); - // DT - if (modsNumber & 64) convertedParts.push('DT'); - // RX - if (modsNumber & 128) convertedParts.push('RX'); - // HT - if (modsNumber & 256) convertedParts.push('HT'); - // NC - if (modsNumber & 576) convertedParts.push('NC'); - // FL - if (modsNumber & 1024) convertedParts.push('FL'); - // AT - if (modsNumber & 2048) convertedParts.push('AT'); - // SO - if (modsNumber & 4096) convertedParts.push('SO'); - // AP - if (modsNumber & 8192) convertedParts.push('AP'); - // PF - if (modsNumber & 16416) convertedParts.push('PF'); - // 4K - if (modsNumber & 32768) convertedParts.push('4K'); - // 5K - if (modsNumber & 65536) convertedParts.push('5K'); - // 6K - if (modsNumber & 131072) convertedParts.push('6K'); - // 7K - if (modsNumber & 262144) convertedParts.push('7K'); - // 8K - if (modsNumber & 524288) convertedParts.push('8K'); - // FI - if (modsNumber & 1048576) convertedParts.push('FI'); - // RD - if (modsNumber & 2097152) convertedParts.push('RD'); - // LM - if (modsNumber & 4194304) convertedParts.push('LM'); - // Target - if (modsNumber & 8388608) convertedParts.push('Target'); - // 9K - if (modsNumber & 16777216) convertedParts.push('9K'); - // KeyCoop - if (modsNumber & 33554432) convertedParts.push('KeyCoop'); - // 1K - if (modsNumber & 67108864) convertedParts.push('1K'); - // 3K - if (modsNumber & 134217728) convertedParts.push('3K'); - // 2K - if (modsNumber & 268435456) convertedParts.push('2K'); - // ScoreV2 - if (modsNumber & 536870912) convertedParts.push('ScoreV2'); - // MR - if (modsNumber & 1073741824) convertedParts.push('MR'); - - - if (order) { - convertedParts.sort((a, b) => ModsOrder[a.toLowerCase()] - ModsOrder[b.toLowerCase()]); - }; - - - const converted = convertedParts.join(''); - return converted; -}; - - -export const ModsToName2 = (modsNumber: number, order?: boolean): string => { const convertedParts = []; let bit = 1; @@ -234,14 +125,14 @@ export const ModsToName2 = (modsNumber: number, order?: boolean): string => { // SWITCH STATEMENT CREATED ON PURPOSE BECAUSE IT'S WAY FASTER -export const calculate_mods = (ModsName: string | number): { number: number, name: string } | IError => { +export const calculate_mods = (ModsName: string | number, order?: boolean): { number: number, name: string } | IError => { if (ModsName == null) { return { error: new Error(`Specify mods name (HDDT or 72)`) }; }; if (typeof ModsName == 'number') { - const name = ModsToName(ModsName); + const name = ModsToName(ModsName, order); return { number: ModsName, name: name, From 50d35488e183a6abcc25c37d7d90e00e7b1fa78a Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 27 Apr 2024 12:22:48 +0300 Subject: [PATCH 133/259] accuracy improve --- tools/accuracy.ts | 95 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 71 insertions(+), 24 deletions(-) diff --git a/tools/accuracy.ts b/tools/accuracy.ts index e3239826..6e3042e0 100644 --- a/tools/accuracy.ts +++ b/tools/accuracy.ts @@ -1,33 +1,80 @@ -export interface types { - (hits: { - 300: string, - 100: string, - 50: string, - 0: string, - geki: string, - katu: string - }, mode: 'osu' | 'fruits' | 'taiko' | 'mania'): number; +import { IError } from "../types"; +import { GamemodeEnum } from "../types/enums"; + + +type Hits = { + 300?: any; + 100?: any; + 50?: any; + 0?: any; + geki?: any; + katu?: any; + + perfect?: any; + great?: any; + good?: any; + ok?: any; + meh?: any; + miss?: any; }; +type Responnse = { + accuracy: number; + fc_accuracy: number; +} | IError; + + -const name: types = (hits, mode = 'osu') => { - const h300 = parseInt(hits[300]); - const h100 = parseInt(hits[100]); - const h50 = parseInt(hits[50]); - const h0 = parseInt(hits[0]); - const geki = parseInt(hits.geki); - const katu = parseInt(hits.katu); +export const calculate_accuracy = (hits: Hits, mode: GamemodeEnum): Responnse => { + if (Object.keys(hits).length == 0) { + return { error: new Error('Provide hits (300, 100, 50, etc)') }; + }; + + + const geki = parseInt(hits?.geki || hits.perfect || '0'); + const h300 = parseInt(hits?.[300] || hits.great || '0'); + const katu = parseInt(hits?.katu || hits.good || '0'); + const h100 = parseInt(hits?.[100] || hits.ok || '0'); + const h50 = parseInt(hits?.[50] || hits.meh || '0'); + const h0 = parseInt(hits?.[0] || hits.miss || '0'); + + let accuracy = 0.0; + let fc_accuracy = 0.0; - let acc = 0.0; switch (mode) { - case 'osu': acc = (100.0 * (6 * h300 + 2 * h100 + h50)) / (6 * (h50 + h100 + h300 + h0)); break; - case 'taiko': acc = (100.0 * (2 * h300 + h100)) / (2 * (h300 + h100 + h0)); break; - case 'fruits': acc = (100.0 * (h300 + h100 + h50)) / (h300 + h100 + h50 + katu + h0); break; - case 'mania': acc = (100.0 * (6 * geki + 6 * h300 + 4 * katu + 2 * h100 + h50)) / (6 * (h50 + h100 + h300 + h0 + geki + katu)); break; + case GamemodeEnum.osu: + accuracy = (100.0 * (6 * h300 + 2 * h100 + h50)) / (6 * (h50 + h100 + h300 + h0)); + + fc_accuracy = (100.0 * (6 * (h300 + h0) + 2 * h100 + h50)) / (6 * (h50 + h100 + (h300 + h0) + 0)); + break; + + case GamemodeEnum.taiko: + accuracy = (100.0 * (2 * h300 + h100)) / (2 * (h300 + h100 + h0)); + + fc_accuracy = (100.0 * (2 * (h300 + h0) + h100)) / (2 * ((h300 + h0) + h100 + 0)); + break; + + case GamemodeEnum.fruits: + accuracy = (100.0 * (h300 + h100 + h50)) / (h300 + h100 + h50 + katu + h0); + + fc_accuracy = (100.0 * ((h300 + h0) + h100 + h50)) / ((h300 + h0) + h100 + h50 + katu + 0); + break; + + case GamemodeEnum.mania: + accuracy = (100.0 * (6 * geki + 6 * h300 + 4 * katu + 2 * h100 + h50)) / (6 * (h50 + h100 + h300 + h0 + geki + katu)); + + // IT'S NOT CORRECT PLEASE SOMEONE FIX IT + fc_accuracy = (100.0 * (6 * (geki + h0) + 6 * h300 + 4 * katu + 2 * h100 + h50)) / (6 * (h50 + h100 + h300 + 0 + (geki + h0) + katu)); + break; + + default: + return { error: new Error(`Unsupported gamemode: ${mode}}`) }; }; - return parseFloat(acc.toFixed(2)); -}; -export default name; \ No newline at end of file + return { + accuracy, + fc_accuracy, + }; +}; \ No newline at end of file From 8cc8bc8d88361bf2a566d10f6be5679beda031ea Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 27 Apr 2024 12:39:11 +0300 Subject: [PATCH 134/259] Fix types --- api/v2/assets_backgrounds.ts | 4 ++-- api/v2/assets_dataFiles.ts | 4 ++-- api/v2/beatmaps_actions.ts | 14 ++++++-------- api/v2/beatmaps_details.ts | 4 ++-- api/v2/beatmaps_discussions_list.ts | 2 +- api/v2/beatmaps_discussions_posts.ts | 2 +- api/v2/beatmaps_discussions_votes.ts | 2 +- api/v2/beatmaps_download.ts | 6 +++--- api/v2/beatmaps_events_list.ts | 2 +- api/v2/beatmaps_lookup.ts | 12 ++++++------ api/v2/beatmaps_packs_details.ts | 6 ++++-- api/v2/beatmaps_packs_list.ts | 4 +++- api/v2/changelogs_details.ts | 8 +++++--- api/v2/changelogs_list.ts | 4 ++-- api/v2/chat_actions.ts | 4 ++-- api/v2/chat_channels_actions.ts | 8 ++++---- api/v2/chat_channels_list.ts | 2 +- api/v2/chat_details.ts | 6 ++++-- api/v2/chat_list.ts | 4 +++- api/v2/chat_messages.ts | 6 ++++-- api/v2/chat_updates.ts | 4 +++- api/v2/comments_actions.ts | 10 +++++----- api/v2/comments_details.ts | 6 ++++-- api/v2/comments_list.ts | 4 +++- api/v2/forums_topics_actions.ts | 8 ++++---- api/v2/forums_topics_details.ts | 7 +++++-- api/v2/matches_details.ts | 6 ++++-- api/v2/matches_list.ts | 4 +++- api/v2/me_details.ts | 6 ++++-- api/v2/me_download_quota.ts | 6 ++++-- api/v2/me_friends.ts | 6 ++++-- api/v2/news_details.ts | 6 ++++-- api/v2/news_list.ts | 4 +++- api/v2/notifications_list.ts | 4 +++- api/v2/ranking_list.ts | 10 +++++----- api/v2/rooms_details.ts | 6 ++++-- api/v2/rooms_leaderboard.ts | 6 ++++-- api/v2/rooms_list.ts | 4 +++- api/v2/rooms_scores.ts | 6 +++--- api/v2/scores_details.ts | 6 ++++-- api/v2/scores_download.ts | 6 ++++-- api/v2/scores_list.ts | 16 ++++++++-------- api/v2/search.ts | 8 ++++---- api/v2/session_actions.ts | 6 +++--- api/v2/spotlights_list.ts | 4 +++- api/v2/users_activity.ts | 6 ++++-- api/v2/users_beatmaps.ts | 8 +++++--- api/v2/users_details.ts | 6 ++++-- api/v2/users_events.ts | 8 +++++--- api/v2/users_kudosu.ts | 6 ++++-- api/v2/users_list.ts | 6 ++++-- api/v2/wiki_details.ts | 8 +++++--- index.ts | 16 ++-------------- tools/accuracy.ts | 8 ++++---- tools/download_file.ts | 8 +++----- tools/index.ts | 13 ++----------- tools/mods.ts | 13 ++++++++----- types/tools.ts | 4 ++++ utility/request.ts | 4 ++-- 59 files changed, 211 insertions(+), 166 deletions(-) create mode 100644 types/tools.ts diff --git a/api/v2/assets_backgrounds.ts b/api/v2/assets_backgrounds.ts index bb3dc2a6..c7b5e8a9 100644 --- a/api/v2/assets_backgrounds.ts +++ b/api/v2/assets_backgrounds.ts @@ -12,9 +12,9 @@ type params = ({ type Response = T extends 'seasonal' - ? Promise + ? Promise : T extends 'beatmapset' - ? BeatmapsetBackground | IError + ? BeatmapsetBackground & IError : IError; diff --git a/api/v2/assets_dataFiles.ts b/api/v2/assets_dataFiles.ts index e620dfd3..95606363 100644 --- a/api/v2/assets_dataFiles.ts +++ b/api/v2/assets_dataFiles.ts @@ -2,7 +2,7 @@ import { IError } from "../../types"; import { request } from "../../utility/request"; -type Response = { files: string[] } | IError; +type Response = { files: string[] } & IError; export const assets_dataFiles = async (): Promise => { @@ -22,5 +22,5 @@ export const assets_dataFiles = async (): Promise => { .filter((r: string) => r != null); - return { files: array }; + return { files: array } as Response; }; \ No newline at end of file diff --git a/api/v2/beatmaps_actions.ts b/api/v2/beatmaps_actions.ts index 9ac7cd97..9ea1a0dc 100644 --- a/api/v2/beatmaps_actions.ts +++ b/api/v2/beatmaps_actions.ts @@ -1,6 +1,6 @@ import { request } from "../../utility/request"; import { IDefaultParams, IError } from "../../types"; -import { postDataObject } from "../../tools"; +// import { postDataObject } from "../../tools"; type params = ({ @@ -13,16 +13,14 @@ type params = ({ type Response = T extends 'difficulty' - ? any + ? any & IError : T extends 'difficulties' - ? any - : never; + ? any & IError + : IError; // FIX -const name = async (params: T, addons?: IDefaultParams): Promise | IError> => { - return { - error: new Error('TEMPORARY NOT WORKING, have no clue why'), - }; +const name = async (params: T, addons?: IDefaultParams): Promise> => { + return { error: new Error('TEMPORARY NOT WORKING, have no clue why') } as Response; // if (params.type == null) // return { // error: 'Type not specified', diff --git a/api/v2/beatmaps_details.ts b/api/v2/beatmaps_details.ts index f78b2251..ed4e809b 100644 --- a/api/v2/beatmaps_details.ts +++ b/api/v2/beatmaps_details.ts @@ -15,9 +15,9 @@ type params = ({ type Response = T extends 'difficulty' - ? BeamapsDetailsDifficulty | IError + ? BeamapsDetailsDifficulty & IError : T extends 'set' - ? BeamapsDetailsSet | IError + ? BeamapsDetailsSet & IError : IError; diff --git a/api/v2/beatmaps_discussions_list.ts b/api/v2/beatmaps_discussions_list.ts index da8c0bda..d22cbdcb 100644 --- a/api/v2/beatmaps_discussions_list.ts +++ b/api/v2/beatmaps_discussions_list.ts @@ -14,7 +14,7 @@ export const beatmaps_discussions_list = async (params: { limit?: number; sort?: 'id_desc' | 'id_asc'; cursor_string?: string; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/beatmapsets/discussions`, { method: 'GET', params, diff --git a/api/v2/beatmaps_discussions_posts.ts b/api/v2/beatmaps_discussions_posts.ts index 72be60a3..0cc47170 100644 --- a/api/v2/beatmaps_discussions_posts.ts +++ b/api/v2/beatmaps_discussions_posts.ts @@ -12,7 +12,7 @@ export const beatmaps_discussions_posts = async (params: { limit?: number; cursor_string?: string; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { if (params.discussion_id) { // @ts-ignore params.beatmapset_discussion_id = params.discussion_id; diff --git a/api/v2/beatmaps_discussions_votes.ts b/api/v2/beatmaps_discussions_votes.ts index 560d2cac..6c6780c2 100644 --- a/api/v2/beatmaps_discussions_votes.ts +++ b/api/v2/beatmaps_discussions_votes.ts @@ -14,7 +14,7 @@ export const beatmaps_discussions_votes = async (params: { limit?: number; cursor_string?: string; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { if (params.discussion_id) { // @ts-ignore params.beatmapset_discussion_id = params.discussion_id; diff --git a/api/v2/beatmaps_download.ts b/api/v2/beatmaps_download.ts index b5834bd0..8f6d294d 100644 --- a/api/v2/beatmaps_download.ts +++ b/api/v2/beatmaps_download.ts @@ -36,7 +36,7 @@ type Response = { * Time in milliseconds */ elapsed_time?: number -} | IError; +} & IError; export const beatmaps_download = async (params: T, addons?: IDefaultParams): Promise => { @@ -45,7 +45,7 @@ export const beatmaps_download = async (params: T, addons?: ID if (fs.existsSync(params.file_path) && params.overwrite != true) { - return { status: 'exists' }; + return { status: 'exists' } as Response; }; @@ -155,5 +155,5 @@ export const beatmaps_download = async (params: T, addons?: ID }; - return { error: new Error(`Unsupported type: ${(params as any).type}`) }; + return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; }; \ No newline at end of file diff --git a/api/v2/beatmaps_events_list.ts b/api/v2/beatmaps_events_list.ts index 62ba558b..40357b69 100644 --- a/api/v2/beatmaps_events_list.ts +++ b/api/v2/beatmaps_events_list.ts @@ -9,7 +9,7 @@ export const beatmaps_events_list = async (obj: { types: (beatmap_events_types)[]; min_date: string; max_date: string; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { let url = 'https://osu.ppy.sh/api/v2/beatmapsets/events'; diff --git a/api/v2/beatmaps_lookup.ts b/api/v2/beatmaps_lookup.ts index 304e6f83..32d2a9c2 100644 --- a/api/v2/beatmaps_lookup.ts +++ b/api/v2/beatmaps_lookup.ts @@ -1,7 +1,7 @@ import { BeatmapsLookupAttributes } from "../../types/v2/beatmaps_lookup_attributes"; import { BeatmapsLookupDifficulty } from "../../types/v2/beatmaps_lookup_difficulty"; import { BeatmapsLookupSet } from "../../types/v2/beatmaps_lookup_set"; -import { Modes_enums } from "../../types/enums"; +import { GamemodeEnum } from "../../types/enums"; import { request } from "../../utility/request"; import { IDefaultParams, IError, Modes_names } from "../../types"; import { BeatmapsLookupDifficultiesResponse } from "../../types/v2/beatmaps_lookup_difficulties"; @@ -28,13 +28,13 @@ type params = ({ type Response = T extends 'difficulty' - ? BeatmapsLookupDifficulty | IError + ? BeatmapsLookupDifficulty & IError : T extends 'set' - ? BeatmapsLookupSet | IError + ? BeatmapsLookupSet & IError : T extends 'attributes' - ? BeatmapsLookupAttributes | IError + ? BeatmapsLookupAttributes & IError : T extends 'difficulties' - ? BeatmapsLookupDifficultiesResponse[] | IError + ? BeatmapsLookupDifficultiesResponse[] & IError : IError; @@ -80,7 +80,7 @@ export const beatmaps_lookup = async (params: T, addons?: IDef object.mods = params.mods; if (typeof params.mode == 'string') object.ruleset = params.mode; - else if (typeof params.mode == 'number') object.ruleset_id = Modes_enums[params.mode]; + else if (typeof params.mode == 'number') object.ruleset_id = GamemodeEnum[params.mode]; break; diff --git a/api/v2/beatmaps_packs_details.ts b/api/v2/beatmaps_packs_details.ts index 3d1d0762..5e358d6b 100644 --- a/api/v2/beatmaps_packs_details.ts +++ b/api/v2/beatmaps_packs_details.ts @@ -3,10 +3,12 @@ import { BeatmapsPacksDetailsResponse } from "../../types/v2/beatmaps_packs_deta import { request } from "../../utility/request"; +type Response = BeatmapsPacksDetailsResponse & IError; -export const beatmap_packs_details = async (pack_tag: string, addons?: IDefaultParams): Promise => { + +export const beatmap_packs_details = async (pack_tag: string, addons?: IDefaultParams): Promise => { if (pack_tag == null) { - return { error: new Error('Specify beatmap pack tag') }; + return { error: new Error('Specify beatmap pack tag') } as Response; }; diff --git a/api/v2/beatmaps_packs_list.ts b/api/v2/beatmaps_packs_list.ts index 454363e2..064802cb 100644 --- a/api/v2/beatmaps_packs_list.ts +++ b/api/v2/beatmaps_packs_list.ts @@ -3,11 +3,13 @@ import { BeatmapsPacksListResponse } from "../../types/v2/beatmaps_packs_list"; import { request } from "../../utility/request"; +type Response = BeatmapsPacksListResponse & IError; + export const beatmaps_packs_list = async (params: { type: IBeatmapPackType; cursor_string?: string; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/beatmaps/packs`, { method: 'GET', params, diff --git a/api/v2/changelogs_details.ts b/api/v2/changelogs_details.ts index 697888ca..4ea60489 100644 --- a/api/v2/changelogs_details.ts +++ b/api/v2/changelogs_details.ts @@ -3,17 +3,19 @@ import { changelogsDetailsResponse } from "../../types/v2/changelogs_details"; import { request } from "../../utility/request"; +type Response = changelogsDetailsResponse[] & IError; + export const changelogs_details = async (params: { stream_name: string; build_version: string; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { if (params.stream_name == null) { - return { error: new Error(`Specify stream name`) }; + return { error: new Error(`Specify stream name`) } as Response; }; if (params.build_version == null) { - return { error: new Error(`Specify build version`) }; + return { error: new Error(`Specify build version`) } as Response; }; diff --git a/api/v2/changelogs_list.ts b/api/v2/changelogs_list.ts index 168e0483..6022ef7f 100644 --- a/api/v2/changelogs_list.ts +++ b/api/v2/changelogs_list.ts @@ -24,9 +24,9 @@ type params = ({ type Response = T extends 'all' - ? ChangelogsListAllResponse | IError + ? ChangelogsListAllResponse & IError : T extends 'lookup' - ? ChangelogsListLookupResponse | IError + ? ChangelogsListLookupResponse & IError : IError; diff --git a/api/v2/chat_actions.ts b/api/v2/chat_actions.ts index de906f3b..76bc8e72 100644 --- a/api/v2/chat_actions.ts +++ b/api/v2/chat_actions.ts @@ -23,9 +23,9 @@ type params = ({ type Response = T extends 'new' - ? ChatActionsNewResponse | IError + ? ChatActionsNewResponse & IError : T extends 'keepalive' - ? ChatActionsKeepaliveResponse | IError + ? ChatActionsKeepaliveResponse & IError : IError; diff --git a/api/v2/chat_channels_actions.ts b/api/v2/chat_channels_actions.ts index bbe009b9..927aebcc 100644 --- a/api/v2/chat_channels_actions.ts +++ b/api/v2/chat_channels_actions.ts @@ -26,13 +26,13 @@ type params = ({ type Response = T extends 'send' - ? chatChannelsActionsSendResponse | IError + ? chatChannelsActionsSendResponse & IError : T extends 'join' - ? chatChannelsActionsJoinResponse | IError + ? chatChannelsActionsJoinResponse & IError : T extends 'leave' - ? "" | IError + ? "" & IError : T extends 'readed' - ? "" | IError + ? "" & IError : IError; diff --git a/api/v2/chat_channels_list.ts b/api/v2/chat_channels_list.ts index 80ff53e9..8be2b052 100644 --- a/api/v2/chat_channels_list.ts +++ b/api/v2/chat_channels_list.ts @@ -4,7 +4,7 @@ import { request } from "../../utility/request"; -export const chat_channels_list = async (): Promise => { +export const chat_channels_list = async (): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/chat/channels`, { method: 'GET', }); diff --git a/api/v2/chat_details.ts b/api/v2/chat_details.ts index 8ace4276..bd564a96 100644 --- a/api/v2/chat_details.ts +++ b/api/v2/chat_details.ts @@ -3,10 +3,12 @@ import { ChatDetailsResponse } from "../../types/v2/chat_details"; import { request } from "../../utility/request"; +type Response = ChatDetailsResponse & IError; -export const chat_details = async (channel_id: number, addons?: IDefaultParams): Promise => { + +export const chat_details = async (channel_id: number, addons?: IDefaultParams): Promise => { if (channel_id == null) { - return { error: new Error(`Specify channel id`) }; + return { error: new Error(`Specify channel id`) } as Response; }; diff --git a/api/v2/chat_list.ts b/api/v2/chat_list.ts index e406e3ad..d2a7e71a 100644 --- a/api/v2/chat_list.ts +++ b/api/v2/chat_list.ts @@ -3,11 +3,13 @@ import { ChatListResponse } from "../../types/v2/chat_list"; import { request } from "../../utility/request"; +type Response = ChatListResponse[] & IError; + export const chat_list = async (params: { unreaded?: boolean; sort?: 'date_desc' | 'date_asc'; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { let data = await request(`https://osu.ppy.sh/api/v2/chat/presence/`, { method: 'GET', addons diff --git a/api/v2/chat_messages.ts b/api/v2/chat_messages.ts index c7838005..eadaaca1 100644 --- a/api/v2/chat_messages.ts +++ b/api/v2/chat_messages.ts @@ -3,6 +3,8 @@ import { ChatMessagesResponse } from "../../types/v2/chat_messages"; import { request } from "../../utility/request"; +type Response = ChatMessagesResponse & IError; + export const chat_messages = async (params: { id: number; @@ -10,9 +12,9 @@ export const chat_messages = async (params: { since?: number; until?: number; return_object?: boolean; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { if (params.id == null) { - return { error: new Error(`Specify channel id`) }; + return { error: new Error(`Specify channel id`) } as Response; }; diff --git a/api/v2/chat_updates.ts b/api/v2/chat_updates.ts index 58770da2..d51850a3 100644 --- a/api/v2/chat_updates.ts +++ b/api/v2/chat_updates.ts @@ -3,12 +3,14 @@ import { ChatUpdatesResponse } from "../../types/v2/chat_updates"; import { request } from "../../utility/request"; +type Response = ChatUpdatesResponse & IError; + export const chat_updates = async (params: { after_id: number; includes: ('presence' | 'silences' | 'messages')[]; history_since: number; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/chat/updates`, { method: 'GET', params: { diff --git a/api/v2/comments_actions.ts b/api/v2/comments_actions.ts index 6faaa5ed..92511bc4 100644 --- a/api/v2/comments_actions.ts +++ b/api/v2/comments_actions.ts @@ -37,15 +37,15 @@ type params = ({ type Response = T extends 'new' - ? CommentsActionsNewResponse | IError + ? CommentsActionsNewResponse & IError : T extends 'edit' - ? CommentsActionsEditResponse | IError + ? CommentsActionsEditResponse & IError : T extends 'delete' - ? CommentsActionsDeleteResponse | IError + ? CommentsActionsDeleteResponse & IError : T extends 'vote' - ? CommentsActionsVoteResponse | IError + ? CommentsActionsVoteResponse & IError : T extends 'unvote' - ? CommentsActionsUnvoteResponse | IError + ? CommentsActionsUnvoteResponse & IError : IError; diff --git a/api/v2/comments_details.ts b/api/v2/comments_details.ts index c12d11d9..4c43508b 100644 --- a/api/v2/comments_details.ts +++ b/api/v2/comments_details.ts @@ -3,10 +3,12 @@ import { CommentsDetailsResponse } from "../../types/v2/comments_details"; import { request } from "../../utility/request"; +type Response = CommentsDetailsResponse & IError; -export const comments_details = async (comment_id: string, addons?: IDefaultParams): Promise => { + +export const comments_details = async (comment_id: string, addons?: IDefaultParams): Promise => { if (comment_id == null) { - return { error: new Error(`Specify comment id`) }; + return { error: new Error(`Specify comment id`) } as Response; }; diff --git a/api/v2/comments_list.ts b/api/v2/comments_list.ts index d4d69bab..bb940f4d 100644 --- a/api/v2/comments_list.ts +++ b/api/v2/comments_list.ts @@ -3,6 +3,8 @@ import { CommentsListResponse } from "../../types/v2/comments_list"; import { request } from "../../utility/request"; +type Response = CommentsListResponse & IError; + export const comments_list = async (params: { type?: 'news_post' | 'beatmapset' | 'Build'; @@ -16,7 +18,7 @@ export const comments_list = async (params: { created_at: string; }; sort?: 'new' | 'old' | 'top'; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/comments`, { method: 'GET', params: { diff --git a/api/v2/forums_topics_actions.ts b/api/v2/forums_topics_actions.ts index 29a50894..a07d7fd1 100644 --- a/api/v2/forums_topics_actions.ts +++ b/api/v2/forums_topics_actions.ts @@ -47,13 +47,13 @@ type params = ({ type Response = T extends 'create' - ? ForumsTopicsActionsCreateResponse | IError + ? ForumsTopicsActionsCreateResponse & IError : T extends 'reply' - ? ForumsTopicsActionsReplyResponse | IError + ? ForumsTopicsActionsReplyResponse & IError : T extends 'edit_post' - ? ForumsTopicsActionsEditPostResponse | IError + ? ForumsTopicsActionsEditPostResponse & IError : T extends 'edit_topic' - ? ForumsTopicsActionsEditTopicResponse | IError + ? ForumsTopicsActionsEditTopicResponse & IError : IError; diff --git a/api/v2/forums_topics_details.ts b/api/v2/forums_topics_details.ts index 743464e0..6ba4a772 100644 --- a/api/v2/forums_topics_details.ts +++ b/api/v2/forums_topics_details.ts @@ -3,6 +3,9 @@ import { IDefaultParams, IError } from "../../types"; import { ForumsTopicsDetailsResponse } from "../../types/v2/forums_topics_details"; +type Response = ForumsTopicsDetailsResponse & IError; + + export const forums_topics_details = async (params: { id: number @@ -13,9 +16,9 @@ export const forums_topics_details = async (params: { sort?: 'id_asc' | 'id_desc', cursor_string?: string, -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { if (params.id == null) { - return { error: new Error(`Specify topic id`) }; + return { error: new Error(`Specify topic id`) } as Response }; diff --git a/api/v2/matches_details.ts b/api/v2/matches_details.ts index 80768f53..1607a158 100644 --- a/api/v2/matches_details.ts +++ b/api/v2/matches_details.ts @@ -3,10 +3,12 @@ import { MatchesDetailsResponse } from "../../types/v2/matches_detaIls"; import { request } from "../../utility/request"; +type Response = MatchesDetailsResponse & IError; -export const matches_details = async (match_id: number, addons?: IDefaultParams): Promise => { + +export const matches_details = async (match_id: number, addons?: IDefaultParams): Promise => { if (match_id == null) { - return { error: new Error(`Specify match id`) }; + return { error: new Error(`Specify match id`) } as Response; }; diff --git a/api/v2/matches_list.ts b/api/v2/matches_list.ts index a5b641b8..9227d27b 100644 --- a/api/v2/matches_list.ts +++ b/api/v2/matches_list.ts @@ -3,6 +3,8 @@ import { MatchesListResponse } from "../../types/v2/matches_list"; import { request } from "../../utility/request"; +type Response = MatchesListResponse & IError; + export const matches_list = async (params: { limit: number; @@ -11,7 +13,7 @@ export const matches_list = async (params: { * Use cursor.match_id */ after_id: number; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/matches`, { method: 'GET', params: { diff --git a/api/v2/me_details.ts b/api/v2/me_details.ts index 08c833ef..2943fc3b 100644 --- a/api/v2/me_details.ts +++ b/api/v2/me_details.ts @@ -4,10 +4,12 @@ import { MeDetailsResponse } from "../../types/v2/me_details"; import { request } from "../../utility/request"; +type Response = MeDetailsResponse & IError; -export const me_details = async (addons?: IDefaultParams & { mode: Modes_names }): Promise => { + +export const me_details = async (addons?: IDefaultParams & { mode: Modes_names }): Promise => { if (credentials.method != 'lazer') { - return { error: new Error(`Login via lazer to use this endpoint`) }; + return { error: new Error(`Login via lazer to use this endpoint`) } as Response }; diff --git a/api/v2/me_download_quota.ts b/api/v2/me_download_quota.ts index f7b44a1b..452eb6f9 100644 --- a/api/v2/me_download_quota.ts +++ b/api/v2/me_download_quota.ts @@ -4,10 +4,12 @@ import { MedownloadquotaResponse } from "../../types/v2/me_download_quota"; import { request } from "../../utility/request"; +type Response = MedownloadquotaResponse & IError; -export const me_download_quota = async (): Promise => { + +export const me_download_quota = async (): Promise => { if (credentials.method != 'lazer') { - return { error: new Error(`Login via lazer to use this endpoint`) }; + return { error: new Error(`Login via lazer to use this endpoint`) } as Response }; diff --git a/api/v2/me_friends.ts b/api/v2/me_friends.ts index da24d9d9..f2580860 100644 --- a/api/v2/me_friends.ts +++ b/api/v2/me_friends.ts @@ -4,10 +4,12 @@ import { request } from "../../utility/request"; import { MeFriendsResponse } from "../../types/v2/me_friends"; +type Response = MeFriendsResponse & IError; -export const me_friends = async (addons?: IDefaultParams): Promise => { + +export const me_friends = async (addons?: IDefaultParams): Promise => { if (credentials.method != 'lazer') { - return { error: new Error(`Login via lazer to use this endpoint`) }; + return { error: new Error(`Login via lazer to use this endpoint`) } as Response }; diff --git a/api/v2/news_details.ts b/api/v2/news_details.ts index 73a88e54..edec6220 100644 --- a/api/v2/news_details.ts +++ b/api/v2/news_details.ts @@ -3,13 +3,15 @@ import { NewsDetailsResponse } from "../../types/v2/news_details"; import { request } from "../../utility/request"; +type Response = NewsDetailsResponse & IError; + export const news_details = async (params: { news_id: string; key?: 'id' | null; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { if (params.news_id == null) { - return { error: new Error(`Specify news id`) }; + return { error: new Error(`Specify news id`) } as Response }; diff --git a/api/v2/news_list.ts b/api/v2/news_list.ts index 299e0c4c..5077e4a3 100644 --- a/api/v2/news_list.ts +++ b/api/v2/news_list.ts @@ -3,12 +3,14 @@ import { NewsListResponse } from "../../types/v2/news_list"; import { request } from "../../utility/request"; +type Response = NewsListResponse & IError; + export const news_list = async (params: { from_year?: string; limit?: string; cursor_string?: string; -} = {}, addons?: IDefaultParams): Promise => { +} = {}, addons?: IDefaultParams): Promise => { const object: any = { year: params.from_year, limit: params.limit, diff --git a/api/v2/notifications_list.ts b/api/v2/notifications_list.ts index 1589eea1..05f08cc4 100644 --- a/api/v2/notifications_list.ts +++ b/api/v2/notifications_list.ts @@ -3,11 +3,13 @@ import { NotificationsListResponse } from "../../types/v2/notifications_list"; import { request } from "../../utility/request"; +type Response = NotificationsListResponse & IError; + export const notifications_list = async (params: { max_id: string; unreaded_only: boolean; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/notifications`, { method: 'GET', params: { diff --git a/api/v2/ranking_list.ts b/api/v2/ranking_list.ts index 464ba5a2..07b074ae 100644 --- a/api/v2/ranking_list.ts +++ b/api/v2/ranking_list.ts @@ -41,15 +41,15 @@ type params = { type Response = T extends 'charts' - ? RankingListChartsResponse | IError + ? RankingListChartsResponse & IError : T extends 'country' - ? RankingListCountryResponse | IError + ? RankingListCountryResponse & IError : T extends 'performance' - ? RankingListPerformanceResponse | IError + ? RankingListPerformanceResponse & IError : T extends 'score' - ? RankingListScoreResponse | IError + ? RankingListScoreResponse & IError : T extends 'kudosu' - ? RankingListKudosuResponse | IError + ? RankingListKudosuResponse & IError : IError; diff --git a/api/v2/rooms_details.ts b/api/v2/rooms_details.ts index b7f77071..d36ef827 100644 --- a/api/v2/rooms_details.ts +++ b/api/v2/rooms_details.ts @@ -3,10 +3,12 @@ import { RoomsDetailsResponse } from "../../types/v2/rooms_details"; import { request } from "../../utility/request"; +type Response = RoomsDetailsResponse & IError; -export const rooms_details = async (id: number | 'latest', addons?: IDefaultParams): Promise => { + +export const rooms_details = async (id: number | 'latest', addons?: IDefaultParams): Promise => { if (id == null) { - return { error: new Error(`Specify room id`) }; + return { error: new Error(`Specify room id`) } as Response; }; diff --git a/api/v2/rooms_leaderboard.ts b/api/v2/rooms_leaderboard.ts index 4f15e7aa..9686077e 100644 --- a/api/v2/rooms_leaderboard.ts +++ b/api/v2/rooms_leaderboard.ts @@ -3,13 +3,15 @@ import { RoomsLeaderboardResponse } from "../../types/v2/rooms_leaderboard"; import { request } from "../../utility/request"; +type Response = RoomsLeaderboardResponse & IError; + export const rooms_leaderboard = async (params: { id: number; limit?: number; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { if (params.id == null) { - return { error: new Error(`Specify room id`) }; + return { error: new Error(`Specify room id`) } as Response; }; diff --git a/api/v2/rooms_list.ts b/api/v2/rooms_list.ts index 82f05e64..407c76de 100644 --- a/api/v2/rooms_list.ts +++ b/api/v2/rooms_list.ts @@ -3,6 +3,8 @@ import { RoomsListResponse } from "../../types/v2/rooms_list"; import { request } from "../../utility/request"; +type Response = RoomsListResponse & IError; + export const rooms_list = async (params: { type?: 'playlists' | 'realtime'; @@ -14,7 +16,7 @@ export const rooms_list = async (params: { sort?: 'ended' | 'created'; cursor_string?: string; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { if (addons == null) addons = { apiVersion: '99999999' } diff --git a/api/v2/rooms_scores.ts b/api/v2/rooms_scores.ts index 103e1d17..2de2b6de 100644 --- a/api/v2/rooms_scores.ts +++ b/api/v2/rooms_scores.ts @@ -32,11 +32,11 @@ type params = ({ type Response = T extends 'all' - ? RoomsScoresAllResponse | IError + ? RoomsScoresAllResponse & IError : T extends 'single' - ? RoomsScoresSingleResponse | IError + ? RoomsScoresSingleResponse & IError : T extends 'user_highest' - ? RoomScoresUserHighestResponse | IError + ? RoomScoresUserHighestResponse & IError : IError; diff --git a/api/v2/scores_details.ts b/api/v2/scores_details.ts index 73d06040..532e8b51 100644 --- a/api/v2/scores_details.ts +++ b/api/v2/scores_details.ts @@ -3,13 +3,15 @@ import { ScoresDetailsResponse } from "../../types/v2/scores_details"; import { request } from "../../utility/request"; +type Response = ScoresDetailsResponse & IError; + export const scores_details = async (params: { id: number; mode?: Modes_names; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { if (params.id == null) { - return { error: new Error(`Specify score id`) }; + return { error: new Error(`Specify score id`) } as Response; }; diff --git a/api/v2/scores_download.ts b/api/v2/scores_download.ts index 3e186f8d..2bdf6e9b 100644 --- a/api/v2/scores_download.ts +++ b/api/v2/scores_download.ts @@ -3,14 +3,16 @@ import { ScoresDownloadResponse } from "../../types/v2/scores_download"; import { download } from "../../utility/request"; +type Response = ScoresDownloadResponse & IError; + export const scores_download = async (params: { id: number; mode?: Modes_names; file_path?: string; -}): Promise => { +}): Promise => { if (params.id == null) { - return { error: new Error(`Specify score id`) }; + return { error: new Error(`Specify score id`) } as Response; }; diff --git a/api/v2/scores_list.ts b/api/v2/scores_list.ts index 9ea1722b..7838cb85 100644 --- a/api/v2/scores_list.ts +++ b/api/v2/scores_list.ts @@ -43,21 +43,21 @@ type params = { type Response = T extends 'leaderboard' - ? ScoresListLeaderboardResponse | IError + ? ScoresListLeaderboardResponse[] & IError : T extends 'solo_scores' - ? ScoresListSoloScoresResponse | IError + ? ScoresListSoloScoresResponse[] & IError : T extends 'beatmap_best' - ? ScoresListBeatmapBestResponse | IError + ? ScoresListBeatmapBestResponse[] & IError : T extends 'beatmap_all' - ? ScoresListBeatmapAllResponse | IError + ? ScoresListBeatmapAllResponse[] & IError : T extends 'user_best' - ? ScoresListUserBestResponse | IError + ? ScoresListUserBestResponse[] & IError : T extends 'user_firsts' - ? ScoresListUserFirstsResponse | IError + ? ScoresListUserFirstsResponse[] & IError : T extends 'user_recent' - ? ScoresListUserRecentResponse | IError + ? ScoresListUserRecentResponse[] & IError : T extends 'user_pinned' - ? ScoresListUserPinnedResponse | IError + ? ScoresListUserPinnedResponse[] & IError : IError; diff --git a/api/v2/search.ts b/api/v2/search.ts index 1fff951f..d0c9fdb1 100644 --- a/api/v2/search.ts +++ b/api/v2/search.ts @@ -1,5 +1,5 @@ import { beatmap_category, beatmap_sorting, beatmap_statuses, Modes_names, beatmap_genres, beatmap_languages, beatmap_ranks, beatmap_extra, IDefaultParams, IError } from "../../types"; -import { Genres_enum, Languages_enum, Modes_enums } from "../../types/enums"; +import { Genres_enum, Languages_enum, GamemodeEnum } from "../../types/enums"; import { SearchBeatmaps, SearchWiki } from '../../types/v2/search_all'; import { request } from "../../utility/request"; @@ -32,9 +32,9 @@ type params = ({ type Response = T extends 'site' - ? SearchWiki | IError + ? SearchWiki & IError : T extends 'beatmaps' - ? SearchBeatmaps | IError + ? SearchBeatmaps & IError : IError; @@ -60,7 +60,7 @@ export const search_all = async (params: T, addons?: IDefaultP if (params._nsfw != null) object.nsfw = params._nsfw; if (params.query != null) object.q = params.query; - if (params.mode != null) object.m = typeof params.mode == 'number' ? params.mode : Modes_enums[params.mode]; + if (params.mode != null) object.m = typeof params.mode == 'number' ? params.mode : GamemodeEnum[params.mode]; if (params.status != null) object.s = params.status; if (params.category != null) object.c = params.category.join('.'); diff --git a/api/v2/session_actions.ts b/api/v2/session_actions.ts index 6f24dfa4..1905f643 100644 --- a/api/v2/session_actions.ts +++ b/api/v2/session_actions.ts @@ -13,11 +13,11 @@ type params = ({ type Response = T extends 'verify' - ? any | IError + ? any & IError : T extends 'reissue' - ? any | IError + ? any & IError : T extends 'delete' - ? any | IError + ? any & IError : IError; diff --git a/api/v2/spotlights_list.ts b/api/v2/spotlights_list.ts index f665000d..318a2795 100644 --- a/api/v2/spotlights_list.ts +++ b/api/v2/spotlights_list.ts @@ -3,8 +3,10 @@ import { SpotlightsListResponse } from "../../types/v2/spotlights_list"; import { request } from "../../utility/request"; +type Response = SpotlightsListResponse & IError; -export const spotlights_list = async (addons?: IDefaultParams): Promise => { + +export const spotlights_list = async (addons?: IDefaultParams): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/spotlights`, { method: 'GET', addons, diff --git a/api/v2/users_activity.ts b/api/v2/users_activity.ts index fbd3ecd3..a9b6f1ef 100644 --- a/api/v2/users_activity.ts +++ b/api/v2/users_activity.ts @@ -3,14 +3,16 @@ import { UsersActivityResponse } from "../../types/v2/users_activity"; import { request } from "../../utility/request"; +type Response = UsersActivityResponse & IError; + export const users_activity = async (params: { id: number; limit?: number; offset?: number; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { if (params.id == null) { - return { error: new Error(`Specify activity id`) }; + return { error: new Error(`Specify activity id`) } as Response; }; diff --git a/api/v2/users_beatmaps.ts b/api/v2/users_beatmaps.ts index 47dbf88c..845092e1 100644 --- a/api/v2/users_beatmaps.ts +++ b/api/v2/users_beatmaps.ts @@ -3,6 +3,8 @@ import { UsersBeatmapsResponse } from "../../types/v2/users_beatmaps"; import { request } from "../../utility/request"; +type Response = UsersBeatmapsResponse & IError; + export const users_beatmaps = async (params: { type: 'favourite' | 'graveyard' | 'guest' | 'loved' | 'most_played' | 'nominated' | 'pending' | 'ranked'; @@ -10,13 +12,13 @@ export const users_beatmaps = async (params: { limit?: number; offset?: number; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { if (params.id == null) { - return { error: new Error(`Specify user id`) }; + return { error: new Error(`Specify user id`) } as Response; }; if (params.type == null) { - return { error: new Error(`Specify beatmaps type`) }; + return { error: new Error(`Specify beatmaps type`) } as Response; }; diff --git a/api/v2/users_details.ts b/api/v2/users_details.ts index 03df8b1c..effb2196 100644 --- a/api/v2/users_details.ts +++ b/api/v2/users_details.ts @@ -3,14 +3,16 @@ import { UsersDetailsResponse } from "../../types/v2/users_details"; import { request } from "../../utility/request"; +type Response = UsersDetailsResponse & IError; + export const users_details = async (params: { id: number; mode?: Modes_names; key?: 'id' | 'username'; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { if (params.id == null) { - return { error: new Error(`Specify user id`) }; + return { error: new Error(`Specify user id`) } as Response; }; diff --git a/api/v2/users_events.ts b/api/v2/users_events.ts index ba2d4aac..085002c9 100644 --- a/api/v2/users_events.ts +++ b/api/v2/users_events.ts @@ -3,12 +3,14 @@ import { UsersEventsResponse } from '../../types/v2/users_events'; import { IDefaultParams, IError } from "../../types"; +type Response = UsersEventsResponse & IError; + export const users_events = async ({ sort, cursor_string, type }: { type?: ('achievement' | 'beatmapPlaycount' | 'beatmapsetApprove' | 'beatmapsetDelete' | 'beatmapsetRevive' | 'beatmapsetUpdate' | 'beatmapsetUpload' | 'rank' | 'userSupportAgain' | 'userSupportFirst' | 'userSupportGift' | 'usernameChange')[] sort?: 'id_desc' | 'id_asc', cursor_string?: string; -} = {}, addons?: IDefaultParams): Promise => { +} = {}, addons?: IDefaultParams): Promise => { const data: any = await request(`https://osu.ppy.sh/api/v2/events`, { method: 'GET', params: { sort: sort, cursor_string: cursor_string }, @@ -18,8 +20,8 @@ export const users_events = async ({ sort, cursor_string, type }: { if (data.error) return data.error; - if (!Array.isArray(type)) { - return { error: new Error(`Events Type must be an Array of types. Example: ['achievement', 'rank']`) }; + if (type != null && !Array.isArray(type)) { + return { error: new Error(`Events Type must be an Array of types. Example: ['achievement', 'rank']`) } as Response; }; diff --git a/api/v2/users_kudosu.ts b/api/v2/users_kudosu.ts index 96f33088..f1049a3d 100644 --- a/api/v2/users_kudosu.ts +++ b/api/v2/users_kudosu.ts @@ -3,14 +3,16 @@ import { UsersKudosuResponse } from "../../types/v2/users_kudosu"; import { request } from "../../utility/request"; +type Response = UsersKudosuResponse & IError; + export const users_kudosu = async (params: { id: number; limit?: number; offset?: number; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { if (params.id == null) { - return { error: new Error(`Specify user id`) }; + return { error: new Error(`Specify user id`) } as Response; }; diff --git a/api/v2/users_list.ts b/api/v2/users_list.ts index caaef394..2087803f 100644 --- a/api/v2/users_list.ts +++ b/api/v2/users_list.ts @@ -3,10 +3,12 @@ import { IDefaultParams, IError } from "../../types"; import { UsersLisResponse } from "../../types/v2/users_list"; +type Response = UsersLisResponse[] & IError; -export const users_list = async (ids: number[], addons?: IDefaultParams): Promise => { + +export const users_list = async (ids: number[], addons?: IDefaultParams): Promise => { if ((ids || [])?.length == 0) { - return { error: new Error(`Specify at least one user id`) }; + return { error: new Error(`Specify at least one user id`) } as Response; }; diff --git a/api/v2/wiki_details.ts b/api/v2/wiki_details.ts index 7d6b198f..46ac4000 100644 --- a/api/v2/wiki_details.ts +++ b/api/v2/wiki_details.ts @@ -3,17 +3,19 @@ import { WikiDetailsResponse } from "../../types/v2/wiki_details"; import { request } from "../../utility/request"; +type Response = WikiDetailsResponse[] & IError; + export const wiki_details = async (params: { locale: string; path_name: string; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { if (params.locale == null) { - return { error: new Error(`Specify locale code. Example: en`) }; + return { error: new Error(`Specify locale code. Example: en`) } as Response; }; if (params.path_name == null) { - return { error: new Error(`Specify wiki page path`) }; + return { error: new Error(`Specify wiki page path`) } as Response; }; diff --git a/index.ts b/index.ts index 9465e099..44a65c5b 100644 --- a/index.ts +++ b/index.ts @@ -1,19 +1,7 @@ -import download_file from './tools/download_file'; -import accuracy from './tools/accuracy'; +export * as v2 from "./routes/v2"; -export const tools = { - accuracy: accuracy, - download: { - difficulty: download_file - }, -}; - -export * as country from './tools/country'; -export * as mods from './tools/mods'; export * as auth from './utility/auth'; -export * as Enums from './types/enums'; - -export * as v2 from "./routes/v2"; \ No newline at end of file +export * as tools from './tools/index'; \ No newline at end of file diff --git a/tools/accuracy.ts b/tools/accuracy.ts index 6e3042e0..0dc47024 100644 --- a/tools/accuracy.ts +++ b/tools/accuracy.ts @@ -21,13 +21,13 @@ type Hits = { type Responnse = { accuracy: number; fc_accuracy: number; -} | IError; +} & IError; export const calculate_accuracy = (hits: Hits, mode: GamemodeEnum): Responnse => { if (Object.keys(hits).length == 0) { - return { error: new Error('Provide hits (300, 100, 50, etc)') }; + return { error: new Error('Provide hits (300, 100, 50, etc)') } as Responnse; }; @@ -69,12 +69,12 @@ export const calculate_accuracy = (hits: Hits, mode: GamemodeEnum): Responnse => break; default: - return { error: new Error(`Unsupported gamemode: ${mode}}`) }; + return { error: new Error(`Unsupported gamemode: ${mode}}`) } as Responnse; }; return { accuracy, fc_accuracy, - }; + } as Responnse; }; \ No newline at end of file diff --git a/tools/download_file.ts b/tools/download_file.ts index e88fcead..2541a7ee 100644 --- a/tools/download_file.ts +++ b/tools/download_file.ts @@ -7,8 +7,8 @@ export interface types { (difficulty_id: number, file_path: string, overwrite?: boolean): Promise<{ type: 'created' | 'exists' | 'rate-limit', path?: string }>; }; - -const name: types = (difficulty_id, file_path, overwrite) => new Promise(async (resolve, reject) => { +// FIXME +export const download_file: types = (difficulty_id, file_path, overwrite) => new Promise(async (resolve, reject) => { const { dir } = path.parse(file_path); if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); @@ -35,6 +35,4 @@ const name: types = (difficulty_id, file_path, overwrite) => new Promise(async ( path: file_path, }); }); -}); - -export default name; \ No newline at end of file +}); \ No newline at end of file diff --git a/tools/index.ts b/tools/index.ts index a834e560..d4303bc7 100644 --- a/tools/index.ts +++ b/tools/index.ts @@ -1,14 +1,5 @@ -import { calculate_accuracy } from "./accuracy"; -import { calculate_mods } from "./mods"; - - -export const calculate = { - accuracy: calculate_accuracy, - /** - * Hello world - */ - mods: calculate_mods, -}; +export { calculate_accuracy } from "./accuracy"; +export { calculate_mods } from "./mods"; diff --git a/tools/mods.ts b/tools/mods.ts index 47939adf..f8b977af 100644 --- a/tools/mods.ts +++ b/tools/mods.ts @@ -1,5 +1,6 @@ import { IError } from "../types"; import { ModsOrder } from "../types/enums"; +import { ModsResponse } from "../types/tools"; @@ -123,11 +124,13 @@ export const ModsToName = (modsNumber: number, order?: boolean): string => { }; +type Response = ModsResponse & IError; + // SWITCH STATEMENT CREATED ON PURPOSE BECAUSE IT'S WAY FASTER -export const calculate_mods = (ModsName: string | number, order?: boolean): { number: number, name: string } | IError => { +export const calculate_mods = (ModsName: string | number, order?: boolean): Response => { if (ModsName == null) { - return { error: new Error(`Specify mods name (HDDT or 72)`) }; + return { error: new Error(`Specify mods name (HDDT or 72)`) } as Response; }; @@ -136,7 +139,7 @@ export const calculate_mods = (ModsName: string | number, order?: boolean): { nu return { number: ModsName, name: name, - }; + } as any; }; @@ -144,7 +147,7 @@ export const calculate_mods = (ModsName: string | number, order?: boolean): { nu const ModsArray = ModsName.toLowerCase().match(/.{1,2}/g); if (!Array.isArray(ModsArray)) { - return { error: new Error(`Can't convert mods (${ModsName}) to array of mods`) }; + return { error: new Error(`Can't convert mods (${ModsName}) to array of mods`) } as Response; }; @@ -251,5 +254,5 @@ export const calculate_mods = (ModsName: string | number, order?: boolean): { nu return { number: mods_id, name: ModsName, - }; + } as Response; }; \ No newline at end of file diff --git a/types/tools.ts b/types/tools.ts new file mode 100644 index 00000000..a9894489 --- /dev/null +++ b/types/tools.ts @@ -0,0 +1,4 @@ +export interface ModsResponse { + number: number; + name: string; +}; \ No newline at end of file diff --git a/utility/request.ts b/utility/request.ts index 18957083..77f0dbf4 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -17,7 +17,7 @@ export interface RequestType { headers?: { [key: string]: string }, params?: { [key: string]: any }; addons?: IDefaultParams; - }): Promise; + }): Promise; }; @@ -192,7 +192,7 @@ export const download = (url: string, dest: string, { _callback, headers = {}, d params?: any; addons?: IDefaultParams; callback?: Function; -}): Promise => { +}): Promise => { return new Promise((resolve, reject) => { const start_time = performance.now(); if (url.includes('https://osu.ppy.sh/api/v2')) headers['Authorization'] = `Bearer ${params?.v2 || auth.cache.v2}`; From a58d0be30a4bbfe0cbfcd99d44ad4870e04241e7 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 27 Apr 2024 12:59:10 +0300 Subject: [PATCH 135/259] array types fix --- api/v2/assets_dataFiles.ts | 3 ++- api/v2/chat_actions.ts | 3 ++- api/v2/chat_channels_list.ts | 2 +- api/v2/chat_messages.ts | 2 +- api/v2/me_friends.ts | 2 +- api/v2/notification_actions.ts | 2 +- api/v2/ranking_list.ts | 2 +- api/v2/spotlights_list.ts | 2 +- api/v2/users_activity.ts | 2 +- api/v2/users_beatmaps.ts | 2 +- api/v2/users_events.ts | 2 +- api/v2/users_kudosu.ts | 2 +- api/v2/wiki_details.ts | 2 +- types/v2/assets_datafiles.ts | 3 +++ types/v2/chat_actions_keepalive.ts | 8 ++++---- types/v2/chat_updates.ts | 8 +++++++- 16 files changed, 29 insertions(+), 18 deletions(-) create mode 100644 types/v2/assets_datafiles.ts diff --git a/api/v2/assets_dataFiles.ts b/api/v2/assets_dataFiles.ts index 95606363..6a4a8b68 100644 --- a/api/v2/assets_dataFiles.ts +++ b/api/v2/assets_dataFiles.ts @@ -1,8 +1,9 @@ import { IError } from "../../types"; +import { AssetsDatafilesResponse } from "../../types/v2/assets_datafiles"; import { request } from "../../utility/request"; -type Response = { files: string[] } & IError; +type Response = AssetsDatafilesResponse & IError; export const assets_dataFiles = async (): Promise => { diff --git a/api/v2/chat_actions.ts b/api/v2/chat_actions.ts index 76bc8e72..1042edf3 100644 --- a/api/v2/chat_actions.ts +++ b/api/v2/chat_actions.ts @@ -25,7 +25,7 @@ type Response = T extends 'new' ? ChatActionsNewResponse & IError : T extends 'keepalive' - ? ChatActionsKeepaliveResponse & IError + ? ChatActionsKeepaliveResponse[] & IError : IError; @@ -71,5 +71,6 @@ export const chat_actions = async (params: T, addons?: IDefaul }); + if (params.type == 'keepalive') return data.silences as Response; return data as Response; }; \ No newline at end of file diff --git a/api/v2/chat_channels_list.ts b/api/v2/chat_channels_list.ts index 8be2b052..ffa2cf97 100644 --- a/api/v2/chat_channels_list.ts +++ b/api/v2/chat_channels_list.ts @@ -4,7 +4,7 @@ import { request } from "../../utility/request"; -export const chat_channels_list = async (): Promise => { +export const chat_channels_list = async (): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/chat/channels`, { method: 'GET', }); diff --git a/api/v2/chat_messages.ts b/api/v2/chat_messages.ts index eadaaca1..f1c54e24 100644 --- a/api/v2/chat_messages.ts +++ b/api/v2/chat_messages.ts @@ -3,7 +3,7 @@ import { ChatMessagesResponse } from "../../types/v2/chat_messages"; import { request } from "../../utility/request"; -type Response = ChatMessagesResponse & IError; +type Response = ChatMessagesResponse[] & IError; export const chat_messages = async (params: { diff --git a/api/v2/me_friends.ts b/api/v2/me_friends.ts index f2580860..97e99e37 100644 --- a/api/v2/me_friends.ts +++ b/api/v2/me_friends.ts @@ -4,7 +4,7 @@ import { request } from "../../utility/request"; import { MeFriendsResponse } from "../../types/v2/me_friends"; -type Response = MeFriendsResponse & IError; +type Response = MeFriendsResponse[] & IError; export const me_friends = async (addons?: IDefaultParams): Promise => { diff --git a/api/v2/notification_actions.ts b/api/v2/notification_actions.ts index 0cb3dc2b..33610669 100644 --- a/api/v2/notification_actions.ts +++ b/api/v2/notification_actions.ts @@ -24,7 +24,7 @@ type params = ({ type Response = T extends 'mark_as_readed' - ? "" + ? "" & IError : IError; diff --git a/api/v2/ranking_list.ts b/api/v2/ranking_list.ts index 07b074ae..6ebce32a 100644 --- a/api/v2/ranking_list.ts +++ b/api/v2/ranking_list.ts @@ -49,7 +49,7 @@ type Response = : T extends 'score' ? RankingListScoreResponse & IError : T extends 'kudosu' - ? RankingListKudosuResponse & IError + ? RankingListKudosuResponse[] & IError : IError; diff --git a/api/v2/spotlights_list.ts b/api/v2/spotlights_list.ts index 318a2795..bc8a668b 100644 --- a/api/v2/spotlights_list.ts +++ b/api/v2/spotlights_list.ts @@ -3,7 +3,7 @@ import { SpotlightsListResponse } from "../../types/v2/spotlights_list"; import { request } from "../../utility/request"; -type Response = SpotlightsListResponse & IError; +type Response = SpotlightsListResponse[] & IError; export const spotlights_list = async (addons?: IDefaultParams): Promise => { diff --git a/api/v2/users_activity.ts b/api/v2/users_activity.ts index a9b6f1ef..15347027 100644 --- a/api/v2/users_activity.ts +++ b/api/v2/users_activity.ts @@ -3,7 +3,7 @@ import { UsersActivityResponse } from "../../types/v2/users_activity"; import { request } from "../../utility/request"; -type Response = UsersActivityResponse & IError; +type Response = UsersActivityResponse[] & IError; export const users_activity = async (params: { diff --git a/api/v2/users_beatmaps.ts b/api/v2/users_beatmaps.ts index 845092e1..e66c2ac9 100644 --- a/api/v2/users_beatmaps.ts +++ b/api/v2/users_beatmaps.ts @@ -3,7 +3,7 @@ import { UsersBeatmapsResponse } from "../../types/v2/users_beatmaps"; import { request } from "../../utility/request"; -type Response = UsersBeatmapsResponse & IError; +type Response = UsersBeatmapsResponse[] & IError; export const users_beatmaps = async (params: { diff --git a/api/v2/users_events.ts b/api/v2/users_events.ts index 085002c9..e29bdbce 100644 --- a/api/v2/users_events.ts +++ b/api/v2/users_events.ts @@ -3,7 +3,7 @@ import { UsersEventsResponse } from '../../types/v2/users_events'; import { IDefaultParams, IError } from "../../types"; -type Response = UsersEventsResponse & IError; +type Response = UsersEventsResponse[] & IError; export const users_events = async ({ sort, cursor_string, type }: { diff --git a/api/v2/users_kudosu.ts b/api/v2/users_kudosu.ts index f1049a3d..584bfd46 100644 --- a/api/v2/users_kudosu.ts +++ b/api/v2/users_kudosu.ts @@ -3,7 +3,7 @@ import { UsersKudosuResponse } from "../../types/v2/users_kudosu"; import { request } from "../../utility/request"; -type Response = UsersKudosuResponse & IError; +type Response = UsersKudosuResponse[] & IError; export const users_kudosu = async (params: { diff --git a/api/v2/wiki_details.ts b/api/v2/wiki_details.ts index 46ac4000..66792c38 100644 --- a/api/v2/wiki_details.ts +++ b/api/v2/wiki_details.ts @@ -3,7 +3,7 @@ import { WikiDetailsResponse } from "../../types/v2/wiki_details"; import { request } from "../../utility/request"; -type Response = WikiDetailsResponse[] & IError; +type Response = WikiDetailsResponse & IError; export const wiki_details = async (params: { diff --git a/types/v2/assets_datafiles.ts b/types/v2/assets_datafiles.ts new file mode 100644 index 00000000..b85e3e1f --- /dev/null +++ b/types/v2/assets_datafiles.ts @@ -0,0 +1,3 @@ +export interface AssetsDatafilesResponse { + files: string[] +}; \ No newline at end of file diff --git a/types/v2/chat_actions_keepalive.ts b/types/v2/chat_actions_keepalive.ts index 05bd979f..b703c47b 100644 --- a/types/v2/chat_actions_keepalive.ts +++ b/types/v2/chat_actions_keepalive.ts @@ -1,8 +1,8 @@ -export interface ChatActionsKeepaliveResponse { - silences: Silence[] -} +// export interface ChatActionsKeepaliveResponse { +// silences: Silence[] +// } -export interface Silence { +export interface ChatActionsKeepaliveResponse { id: number user_id: number } diff --git a/types/v2/chat_updates.ts b/types/v2/chat_updates.ts index a4b79ddf..5b2128d5 100644 --- a/types/v2/chat_updates.ts +++ b/types/v2/chat_updates.ts @@ -1,8 +1,14 @@ export interface ChatUpdatesResponse { presence: Presence[] - silences: any[] + silences: Silence[] } +export interface Silence { + id: number + user_id: number +} + + export interface Presence { channel_id: number description: string From 38d4343148df39bccb6dedd08648070bb4cf0fcc Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 27 Apr 2024 13:24:34 +0300 Subject: [PATCH 136/259] country function fix --- api/v2/beatmaps_download.ts | 12 +- index.ts | 8 +- tools/country.ts | 352 ++++-------------------------------- tools/download_file.ts | 38 ---- tools/index.ts | 7 +- types/enums.ts | 317 ++++++++++++++++++++++++++++++++ types/tools.ts | 5 + utility/request.ts | 14 +- 8 files changed, 380 insertions(+), 373 deletions(-) delete mode 100644 tools/download_file.ts diff --git a/api/v2/beatmaps_download.ts b/api/v2/beatmaps_download.ts index 8f6d294d..3079b20f 100644 --- a/api/v2/beatmaps_download.ts +++ b/api/v2/beatmaps_download.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { download } from "../../utility/request"; +import { cache } from "../../utility/auth"; import path from "path"; import fs from "fs"; @@ -45,7 +46,7 @@ export const beatmaps_download = async (params: T, addons?: ID if (fs.existsSync(params.file_path) && params.overwrite != true) { - return { status: 'exists' } as Response; + return { status: 'File already exists' } as Response; }; @@ -107,10 +108,17 @@ export const beatmaps_download = async (params: T, addons?: ID break; case 'osu': - default: + if ((addons.authKey || cache.v2) == null) { + return { error: new Error('osu is not authorized') } as Response; + }; + + url = `https://osu.ppy.sh/api/v2/beatmapsets/${params.id}/download${params.no_video ? '?noVideo=1' : ''}`; headers['Referer'] = 'https://osu.ppy.sh/'; break; + + default: + return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; }; diff --git a/index.ts b/index.ts index 44a65c5b..1bf8475e 100644 --- a/index.ts +++ b/index.ts @@ -1,7 +1,7 @@ -export * as v2 from "./routes/v2"; - +export * as auth from './utility/auth'; +export * as v2 from "./routes/v2"; -export * as auth from './utility/auth'; -export * as tools from './tools/index'; \ No newline at end of file +export * as tools from './tools/index'; +export * as enums from './types/enums'; diff --git a/tools/country.ts b/tools/country.ts index dee6e9a2..914befdb 100644 --- a/tools/country.ts +++ b/tools/country.ts @@ -1,315 +1,39 @@ -export const names = { - US: "United States", - RU: "Russian Federation", - DE: "Germany", - PL: "Poland", - FR: "France", - JP: "Japan", - CA: "Canada", - BR: "Brazil", - GB: "United Kingdom", - TW: "Taiwan", - KR: "South Korea", - CN: "China", - AU: "Australia", - ID: "Indonesia", - UA: "Ukraine", - PH: "Philippines", - CL: "Chile", - FI: "Finland", - AR: "Argentina", - NL: "Netherlands", - SE: "Sweden", - SG: "Singapore", - MX: "Mexico", - MY: "Malaysia", - ES: "Spain", - IT: "Italy", - HK: "Hong Kong", - TH: "Thailand", - VN: "Vietnam", - NO: "Norway", - CZ: "Czech Republic", - TR: "Turkey", - BY: "Belarus", - AT: "Austria", - BE: "Belgium", - PT: "Portugal", - RO: "Romania", - HU: "Hungary", - DK: "Denmark", - LT: "Lithuania", - KZ: "Kazakhstan", - NZ: "New Zealand", - PE: "Peru", - CH: "Switzerland", - CO: "Colombia", - IL: "Israel", - EE: "Estonia", - BG: "Bulgaria", - SK: "Slovakia", - GR: "Greece", - LV: "Latvia", - VE: "Venezuela", - RS: "Serbia", - IE: "Ireland", - HR: "Croatia", - SA: "Saudi Arabia", - UY: "Uruguay", - ZA: "South Africa", - AE: "United Arab Emirates", - SI: "Slovenia", - IN: "India", - EC: "Ecuador", - MA: "Morocco", - CR: "Costa Rica", - MD: "Moldova", - DO: "Dominican Republic", - BN: "Brunei", - EG: "Egypt", - RE: "Reunion", - MO: "Macau", - TN: "Tunisia", - PA: "Panama", - DZ: "Algeria", - MN: "Mongolia", - PY: "Paraguay", - KW: "Kuwait", - PR: "Puerto Rico", - GE: "Georgia", - BO: "Bolivia", - SV: "El Salvador", - QA: "Qatar", - GT: "Guatemala", - LU: "Luxembourg", - UZ: "Uzbekistan", - KG: "Kyrgyzstan", - MK: "North Macedonia", - KH: "Cambodia", - BA: "Bosnia and Herzegovina", - IS: "Iceland", - JO: "Jordan", - PK: "Pakistan", - TT: "Trinidad and Tobago", - CY: "Cyprus", - HN: "Honduras", - NI: "Nicaragua", - BH: "Bahrain", - MV: "Maldives", - BD: "Bangladesh", - PF: "French Polynesia", - LB: "Lebanon", - NP: "Nepal", - IQ: "Iraq", - GU: "Guam", - AZ: "Azerbaijan", - AL: "Albania", - MT: "Malta", - MM: "Myanmar", - NC: "New Caledonia", - OM: "Oman", - IR: "Iran, Islamic Republic of", - AM: "Armenia", - GP: "Guadeloupe", - MQ: "Martinique", - JM: "Jamaica", - LA: "Lao People's Democratic Republic", - LK: "Sri Lanka", - PS: "Palestinian Territory Occupied", - MU: "Mauritius", - SY: "Syrian Arab Republic", - ME: "Montenegro", - FO: "Faroe Islands", - JE: "Jersey", - GF: "French Guiana", - MP: "Northern Mariana Islands", - IM: "Isle of Man", - SR: "Suriname", - BZ: "Belize", - BB: "Barbados", - AW: "Aruba", - LY: "Libya", - AX: "Aland Islands", - GG: "Guernsey", - MG: "Madagascar", - SD: "Sudan", - LI: "Liechtenstein", - BS: "Bahamas", - KE: "Kenya", - GL: "Greenland", - BM: "Bermuda", - EU: "Europe", - CI: "Cote D'Ivoire", - GY: "Guyana", - GI: "Gibraltar", - VI: "Virgin Islands, U.S.", - AD: "Andorra", - LC: "Saint Lucia", - TJ: "Tajikistan", - AG: "Antigua and Barbuda", - SN: "Senegal", - PM: "Saint Pierre and Miquelon", - CK: "Cook Islands", - AQ: "Antarctica", - CF: "Central African Republic", - LR: "Liberia", - ER: "Eritrea", -}; +import { IError } from "../types"; +import { CountryCodes, CountryNames } from "../types/enums"; +import { CountryResponse } from "../types/tools"; -export const code = { - "United States": 'US', - "Russian Federation": 'RU', - "Germany": 'DE', - "Poland": 'PL', - "France": 'FR', - "Japan": 'JP', - "Canada": 'CA', - "Brazil": 'BR', - "United Kingdom": 'GB', - "Taiwan": 'TW', - "South Korea": 'KR', - "China": 'CN', - "Australia": 'AU', - "Indonesia": 'ID', - "Ukraine": 'UA', - "Philippines": 'PH', - "Chile": 'CL', - "Finland": 'FI', - "Argentina": 'AR', - "Netherlands": 'NL', - "Sweden": 'SE', - "Singapore": 'SG', - "Mexico": 'MX', - "Malaysia": 'MY', - "Spain": 'ES', - "Italy": 'IT', - "Hong Kong": 'HK', - "Thailand": 'TH', - "Vietnam": 'VN', - "Norway": 'NO', - "Czech Republic": 'CZ', - "Turkey": 'TR', - "Belarus": 'BY', - "Austria": 'AT', - "Belgium": 'BE', - "Portugal": 'PT', - "Romania": 'RO', - "Hungary": 'HU', - "Denmark": 'DK', - "Lithuania": 'LT', - "Kazakhstan": 'KZ', - "New Zealand": 'NZ', - "Peru": 'PE', - "Switzerland": 'CH', - "Colombia": 'CO', - "Israel": 'IL', - "Estonia": 'EE', - "Bulgaria": 'BG', - "Slovakia": 'SK', - "Greece": 'GR', - "Latvia": 'LV', - "Venezuela": 'VE', - "Serbia": 'RS', - "Ireland": 'IE', - "Croatia": 'HR', - "Saudi Arabia": 'SA', - "Uruguay": 'UY', - "South Africa": 'ZA', - "United Arab Emirates": 'AE', - "Slovenia": 'SI', - "India": 'IN', - "Ecuador": 'EC', - "Morocco": 'MA', - "Costa Rica": 'CR', - "Moldova": 'MD', - "Dominican Republic": 'DO', - "Brunei": 'BN', - "Egypt": 'EG', - "Reunion": 'RE', - "Macau": 'MO', - "Tunisia": 'TN', - "Panama": 'PA', - "Algeria": 'DZ', - "Mongolia": 'MN', - "Paraguay": 'PY', - "Kuwait": 'KW', - "Puerto Rico": 'PR', - "Georgia": 'GE', - "Bolivia": 'BO', - "El Salvador": 'SV', - "Qatar": 'QA', - "Guatemala": 'GT', - "Luxembourg": 'LU', - "Uzbekistan": 'UZ', - "Kyrgyzstan": 'KG', - "North Macedonia": 'MK', - "Cambodia": 'KH', - "Bosnia and Herzegovina": 'BA', - "Iceland": 'IS', - "Jordan": 'JO', - "Pakistan": 'PK', - "Trinidad and Tobago": 'TT', - "Cyprus": 'CY', - "Honduras": 'HN', - "Nicaragua": 'NI', - "Bahrain": 'BH', - "Maldives": 'MV', - "Bangladesh": 'BD', - "French Polynesia": 'PF', - "Lebanon": 'LB', - "Nepal": 'NP', - "Iraq": 'IQ', - "Guam": 'GU', - "Azerbaijan": 'AZ', - "Albania": 'AL', - "Malta": 'MT', - "Myanmar": 'MM', - "New Caledonia": 'NC', - "Oman": 'OM', - "Iran, Islamic Republic of": 'IR', - "Armenia": 'AM', - "Guadeloupe": 'GP', - "Martinique": 'MQ', - "Jamaica": 'JM', - "Lao People's Democratic Republic": 'LA', - "Sri Lanka": 'LK', - "Palestinian Territory Occupied": 'PS', - "Mauritius": 'MU', - "Syrian Arab Republic": 'SY', - "Montenegro": 'ME', - "Faroe Islands": 'FO', - "Jersey": 'JE', - "French Guiana": 'GF', - "Northern Mariana Islands": 'MP', - "Isle of Man": 'IM', - "Suriname": 'SR', - "Belize": 'BZ', - "Barbados": 'BB', - "Aruba": 'AW', - "Libya": 'LY', - "Aland Islands": 'AX', - "Guernsey": 'GG', - "Madagascar": 'MG', - "Sudan": 'SD', - "Liechtenstein": 'LI', - "Bahamas": 'BS', - "Kenya": 'KE', - "Greenland": 'GL', - "Bermuda": 'BM', - "Europe": 'EU', - "Cote D ' Ivoire": 'CI', - "Guyana": 'GY', - "Gibraltar": 'GI', - "Virgin Islands, U.S.": 'VI', - "Andorra": 'AD', - "Saint Lucia": 'LC', - "Tajikistan": 'TJ', - "Antigua and Barbuda": 'AG', - "Senegal": 'SN', - "Saint Pierre and Miquelon": 'PM', - "Cook Islands": 'CK', - "Antarctica": 'AQ', - "Central African Republic": 'CF', - "Liberia": 'LR', - "Eritrea": 'ER', -} \ No newline at end of file + +type Response = CountryResponse & IError; + + +export const country_details = (name: string): Response => { + if (name == null || name == '') { + return { error: new Error('Specify country code or country name') } as Response; + }; + + + if (name.length == 2) { + const find = (CountryNames as any)[name.toUpperCase()]; + if (find == null) { + return { error: new Error('Country not found') } as Response; + }; + + + return { + code: name.toUpperCase(), + name: find, + } as Response; + }; + + + const find = (CountryCodes as any)[name]; + if (find == null) { + return { error: new Error('Country not found') } as Response; + }; + + + return { + code: name, + name: find, + } as Response; +}; \ No newline at end of file diff --git a/tools/download_file.ts b/tools/download_file.ts deleted file mode 100644 index 2541a7ee..00000000 --- a/tools/download_file.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { request } from "../utility/request"; -import path from "path"; -import fs from "fs"; - - -export interface types { - (difficulty_id: number, file_path: string, overwrite?: boolean): Promise<{ type: 'created' | 'exists' | 'rate-limit', path?: string }>; -}; - -// FIXME -export const download_file: types = (difficulty_id, file_path, overwrite) => new Promise(async (resolve, reject) => { - const { dir } = path.parse(file_path); - if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); - - - if (fs.existsSync(file_path) && overwrite != true) { - resolve({ - type: 'exists', - path: file_path, - }); - return; - }; - - - const data = await request(`https://osu.ppy.sh/osu/${difficulty_id}`, { method: "GET" }); - fs.writeFile(file_path, data, 'utf8', (err) => { - if (err) { - reject(err); - return; - }; - - - resolve({ - type: data.includes('429 Too Many Requests') ? 'rate-limit' : 'created', - path: file_path, - }); - }); -}); \ No newline at end of file diff --git a/tools/index.ts b/tools/index.ts index d4303bc7..871972ff 100644 --- a/tools/index.ts +++ b/tools/index.ts @@ -1,10 +1,7 @@ +export { beatmaps_download } from "../api/v2/beatmaps_download"; export { calculate_accuracy } from "./accuracy"; export { calculate_mods } from "./mods"; - - - - - +export { country_details } from "./country"; diff --git a/types/enums.ts b/types/enums.ts index 61e4c8b5..cc1c6bd8 100644 --- a/types/enums.ts +++ b/types/enums.ts @@ -131,4 +131,321 @@ export const ModsOrder: { pf: 5, fl: 6, td: 7, +}; + + +export const CountryNames = { + US: "United States", + RU: "Russian Federation", + DE: "Germany", + PL: "Poland", + FR: "France", + JP: "Japan", + CA: "Canada", + BR: "Brazil", + GB: "United Kingdom", + TW: "Taiwan", + KR: "South Korea", + CN: "China", + AU: "Australia", + ID: "Indonesia", + UA: "Ukraine", + PH: "Philippines", + CL: "Chile", + FI: "Finland", + AR: "Argentina", + NL: "Netherlands", + SE: "Sweden", + SG: "Singapore", + MX: "Mexico", + MY: "Malaysia", + ES: "Spain", + IT: "Italy", + HK: "Hong Kong", + TH: "Thailand", + VN: "Vietnam", + NO: "Norway", + CZ: "Czech Republic", + TR: "Turkey", + BY: "Belarus", + AT: "Austria", + BE: "Belgium", + PT: "Portugal", + RO: "Romania", + HU: "Hungary", + DK: "Denmark", + LT: "Lithuania", + KZ: "Kazakhstan", + NZ: "New Zealand", + PE: "Peru", + CH: "Switzerland", + CO: "Colombia", + IL: "Israel", + EE: "Estonia", + BG: "Bulgaria", + SK: "Slovakia", + GR: "Greece", + LV: "Latvia", + VE: "Venezuela", + RS: "Serbia", + IE: "Ireland", + HR: "Croatia", + SA: "Saudi Arabia", + UY: "Uruguay", + ZA: "South Africa", + AE: "United Arab Emirates", + SI: "Slovenia", + IN: "India", + EC: "Ecuador", + MA: "Morocco", + CR: "Costa Rica", + MD: "Moldova", + DO: "Dominican Republic", + BN: "Brunei", + EG: "Egypt", + RE: "Reunion", + MO: "Macau", + TN: "Tunisia", + PA: "Panama", + DZ: "Algeria", + MN: "Mongolia", + PY: "Paraguay", + KW: "Kuwait", + PR: "Puerto Rico", + GE: "Georgia", + BO: "Bolivia", + SV: "El Salvador", + QA: "Qatar", + GT: "Guatemala", + LU: "Luxembourg", + UZ: "Uzbekistan", + KG: "Kyrgyzstan", + MK: "North Macedonia", + KH: "Cambodia", + BA: "Bosnia and Herzegovina", + IS: "Iceland", + JO: "Jordan", + PK: "Pakistan", + TT: "Trinidad and Tobago", + CY: "Cyprus", + HN: "Honduras", + NI: "Nicaragua", + BH: "Bahrain", + MV: "Maldives", + BD: "Bangladesh", + PF: "French Polynesia", + LB: "Lebanon", + NP: "Nepal", + IQ: "Iraq", + GU: "Guam", + AZ: "Azerbaijan", + AL: "Albania", + MT: "Malta", + MM: "Myanmar", + NC: "New Caledonia", + OM: "Oman", + IR: "Iran, Islamic Republic of", + AM: "Armenia", + GP: "Guadeloupe", + MQ: "Martinique", + JM: "Jamaica", + LA: "Lao People's Democratic Republic", + LK: "Sri Lanka", + PS: "Palestinian Territory Occupied", + MU: "Mauritius", + SY: "Syrian Arab Republic", + ME: "Montenegro", + FO: "Faroe Islands", + JE: "Jersey", + GF: "French Guiana", + MP: "Northern Mariana Islands", + IM: "Isle of Man", + SR: "Suriname", + BZ: "Belize", + BB: "Barbados", + AW: "Aruba", + LY: "Libya", + AX: "Aland Islands", + GG: "Guernsey", + MG: "Madagascar", + SD: "Sudan", + LI: "Liechtenstein", + BS: "Bahamas", + KE: "Kenya", + GL: "Greenland", + BM: "Bermuda", + EU: "Europe", + CI: "Cote D'Ivoire", + GY: "Guyana", + GI: "Gibraltar", + VI: "Virgin Islands, U.S.", + AD: "Andorra", + LC: "Saint Lucia", + TJ: "Tajikistan", + AG: "Antigua and Barbuda", + SN: "Senegal", + PM: "Saint Pierre and Miquelon", + CK: "Cook Islands", + AQ: "Antarctica", + CF: "Central African Republic", + LR: "Liberia", + ER: "Eritrea", +}; + +export const CountryCodes = { + "United States": 'US', + "Russian Federation": 'RU', + "Germany": 'DE', + "Poland": 'PL', + "France": 'FR', + "Japan": 'JP', + "Canada": 'CA', + "Brazil": 'BR', + "United Kingdom": 'GB', + "Taiwan": 'TW', + "South Korea": 'KR', + "China": 'CN', + "Australia": 'AU', + "Indonesia": 'ID', + "Ukraine": 'UA', + "Philippines": 'PH', + "Chile": 'CL', + "Finland": 'FI', + "Argentina": 'AR', + "Netherlands": 'NL', + "Sweden": 'SE', + "Singapore": 'SG', + "Mexico": 'MX', + "Malaysia": 'MY', + "Spain": 'ES', + "Italy": 'IT', + "Hong Kong": 'HK', + "Thailand": 'TH', + "Vietnam": 'VN', + "Norway": 'NO', + "Czech Republic": 'CZ', + "Turkey": 'TR', + "Belarus": 'BY', + "Austria": 'AT', + "Belgium": 'BE', + "Portugal": 'PT', + "Romania": 'RO', + "Hungary": 'HU', + "Denmark": 'DK', + "Lithuania": 'LT', + "Kazakhstan": 'KZ', + "New Zealand": 'NZ', + "Peru": 'PE', + "Switzerland": 'CH', + "Colombia": 'CO', + "Israel": 'IL', + "Estonia": 'EE', + "Bulgaria": 'BG', + "Slovakia": 'SK', + "Greece": 'GR', + "Latvia": 'LV', + "Venezuela": 'VE', + "Serbia": 'RS', + "Ireland": 'IE', + "Croatia": 'HR', + "Saudi Arabia": 'SA', + "Uruguay": 'UY', + "South Africa": 'ZA', + "United Arab Emirates": 'AE', + "Slovenia": 'SI', + "India": 'IN', + "Ecuador": 'EC', + "Morocco": 'MA', + "Costa Rica": 'CR', + "Moldova": 'MD', + "Dominican Republic": 'DO', + "Brunei": 'BN', + "Egypt": 'EG', + "Reunion": 'RE', + "Macau": 'MO', + "Tunisia": 'TN', + "Panama": 'PA', + "Algeria": 'DZ', + "Mongolia": 'MN', + "Paraguay": 'PY', + "Kuwait": 'KW', + "Puerto Rico": 'PR', + "Georgia": 'GE', + "Bolivia": 'BO', + "El Salvador": 'SV', + "Qatar": 'QA', + "Guatemala": 'GT', + "Luxembourg": 'LU', + "Uzbekistan": 'UZ', + "Kyrgyzstan": 'KG', + "North Macedonia": 'MK', + "Cambodia": 'KH', + "Bosnia and Herzegovina": 'BA', + "Iceland": 'IS', + "Jordan": 'JO', + "Pakistan": 'PK', + "Trinidad and Tobago": 'TT', + "Cyprus": 'CY', + "Honduras": 'HN', + "Nicaragua": 'NI', + "Bahrain": 'BH', + "Maldives": 'MV', + "Bangladesh": 'BD', + "French Polynesia": 'PF', + "Lebanon": 'LB', + "Nepal": 'NP', + "Iraq": 'IQ', + "Guam": 'GU', + "Azerbaijan": 'AZ', + "Albania": 'AL', + "Malta": 'MT', + "Myanmar": 'MM', + "New Caledonia": 'NC', + "Oman": 'OM', + "Iran, Islamic Republic of": 'IR', + "Armenia": 'AM', + "Guadeloupe": 'GP', + "Martinique": 'MQ', + "Jamaica": 'JM', + "Lao People's Democratic Republic": 'LA', + "Sri Lanka": 'LK', + "Palestinian Territory Occupied": 'PS', + "Mauritius": 'MU', + "Syrian Arab Republic": 'SY', + "Montenegro": 'ME', + "Faroe Islands": 'FO', + "Jersey": 'JE', + "French Guiana": 'GF', + "Northern Mariana Islands": 'MP', + "Isle of Man": 'IM', + "Suriname": 'SR', + "Belize": 'BZ', + "Barbados": 'BB', + "Aruba": 'AW', + "Libya": 'LY', + "Aland Islands": 'AX', + "Guernsey": 'GG', + "Madagascar": 'MG', + "Sudan": 'SD', + "Liechtenstein": 'LI', + "Bahamas": 'BS', + "Kenya": 'KE', + "Greenland": 'GL', + "Bermuda": 'BM', + "Europe": 'EU', + "Cote D ' Ivoire": 'CI', + "Guyana": 'GY', + "Gibraltar": 'GI', + "Virgin Islands, U.S.": 'VI', + "Andorra": 'AD', + "Saint Lucia": 'LC', + "Tajikistan": 'TJ', + "Antigua and Barbuda": 'AG', + "Senegal": 'SN', + "Saint Pierre and Miquelon": 'PM', + "Cook Islands": 'CK', + "Antarctica": 'AQ', + "Central African Republic": 'CF', + "Liberia": 'LR', + "Eritrea": 'ER', }; \ No newline at end of file diff --git a/types/tools.ts b/types/tools.ts index a9894489..d37ced5a 100644 --- a/types/tools.ts +++ b/types/tools.ts @@ -1,4 +1,9 @@ export interface ModsResponse { number: number; name: string; +}; + +export interface CountryResponse { + code: string; + name: string; }; \ No newline at end of file diff --git a/utility/request.ts b/utility/request.ts index 77f0dbf4..032e9416 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -72,7 +72,7 @@ export const request: RequestType = (url, { method, headers, data, params = {}, headers['x-api-version'] = addons.apiVersion == '' ? null : addons.apiVersion || '20240130'; if ((addons.authKey || auth.cache.v2) == null) { - return resolve({ error: new Error('v2 not authorized'), }); + return resolve({ error: new Error('v2 not authorized') }); }; }; @@ -221,14 +221,14 @@ export const download = (url: string, dest: string, { _callback, headers = {}, d }; - if (response.headers['content-type'] == 'application/json') { + if (response.headers['content-type'] == 'application/json' || (response.headers['content-type'] == null && +(response.headers['content-length'] || 0) < 150)) { const chunks: any[] = []; response.on('data', (chunk: any) => chunks.push(chunk)); response.on('end', async () => { + const data = Buffer.concat(chunks).toString(); try { - const data = Buffer.concat(chunks).toString(); const json = JSON.parse(data); @@ -239,7 +239,7 @@ export const download = (url: string, dest: string, { _callback, headers = {}, d return resolve(json); } catch (error) { - return resolve({ error: error }); + return resolve({ error: new Error(`Unable to download file: ${data} (${url})`) }); }; }); @@ -248,12 +248,6 @@ export const download = (url: string, dest: string, { _callback, headers = {}, d }; - if (response.headers['content-type'] == null && +(response.headers['content-length'] || 0) < 100) { - - return resolve({ error: new Error(`Unnable to download from: ${url}`) }); - }; - - const file = fs.createWriteStream(dest, { encoding: 'utf8' }); file.on('error', error => { From ffbb9196d803af5b62b03752a1d9b88aa90812cc Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 27 Apr 2024 13:46:07 +0300 Subject: [PATCH 137/259] calculate rank --- src/utility/tools/routes/accuracy.ts | 84 -- src/utility/tools/routes/country.ts | 1047 ----------------- .../tools/routes/download/difficulty.ts | 60 - tools/accuracy.ts | 18 +- tools/index.ts | 1 + tools/rank.ts | 126 ++ types/enums.ts | 34 + types/tools.ts | 9 + 8 files changed, 180 insertions(+), 1199 deletions(-) delete mode 100644 src/utility/tools/routes/accuracy.ts delete mode 100644 src/utility/tools/routes/country.ts delete mode 100644 src/utility/tools/routes/download/difficulty.ts create mode 100644 tools/rank.ts diff --git a/src/utility/tools/routes/accuracy.ts b/src/utility/tools/routes/accuracy.ts deleted file mode 100644 index a2e57131..00000000 --- a/src/utility/tools/routes/accuracy.ts +++ /dev/null @@ -1,84 +0,0 @@ -export const description: any = { - auth: 4, - title: __filename, - method: 'GET', - description: 'Return accuracy from hits object', - params: [ - { - type: 'string | number', - name: '300', - optional: false, - description: 'Amount of 300', - }, - { - type: 'string | number', - name: 'geki', - optional: false, - description: 'Amount of geki (300g)', - }, - { - type: 'string | number', - name: '100', - optional: false, - description: 'Amount of 100', - }, - { - type: 'string | number', - name: 'katu', - optional: false, - description: 'Amount of katu (100k)', - }, - { - type: 'string | number', - name: '50', - optional: false, - description: 'Amount of 50', - }, - { - type: 'string | number', - name: '0', - optional: false, - description: 'Amount of misses', - }, - { - type: 'string | number', - name: 'mode', - optional: false, - description: '\`\`\`osu\`\`\` or \`\`\`fruits\`\`\` or \`\`\`mania\`\`\` or \`\`\`taiko\`\`\`', - }, - ], -}; - -export interface types { - (hits: { - 300: string, - 100: string, - 50: string, - 0: string, - geki: string, - katu: string - }, mode: 'osu' | 'fruits' | 'taiko' | 'mania'): number; -}; - - -const name: types = (hits, mode = 'osu') => { - const h300 = parseInt(hits[300]); - const h100 = parseInt(hits[100]); - const h50 = parseInt(hits[50]); - const h0 = parseInt(hits[0]); - const geki = parseInt(hits.geki); - const katu = parseInt(hits.katu); - - let acc = 0.0; - - switch (mode) { - case 'osu': acc = (100.0 * (6 * h300 + 2 * h100 + h50)) / (6 * (h50 + h100 + h300 + h0)); break; - case 'taiko': acc = (100.0 * (2 * h300 + h100)) / (2 * (h300 + h100 + h0)); break; - case 'fruits': acc = (100.0 * (h300 + h100 + h50)) / (h300 + h100 + h50 + katu + h0); break; - case 'mania': acc = (100.0 * (6 * geki + 6 * h300 + 4 * katu + 2 * h100 + h50)) / (6 * (h50 + h100 + h300 + h0 + geki + katu)); break; - }; - - return parseFloat(acc.toFixed(2)); -}; - -export default name; \ No newline at end of file diff --git a/src/utility/tools/routes/country.ts b/src/utility/tools/routes/country.ts deleted file mode 100644 index 699e8837..00000000 --- a/src/utility/tools/routes/country.ts +++ /dev/null @@ -1,1047 +0,0 @@ -const flags: { - flag: string, - country: string, -}[] = [ - { - flag: "A1", - country: "Anonymous Proxy", - }, - { - flag: "A2", - country: "Satellite Provider", - }, - { - flag: "AD", - country: "Andorra", - }, - { - flag: "AE", - country: "United Arab Emirates", - }, - { - flag: "AF", - country: "Afghanistan", - }, - { - flag: "AG", - country: "Antigua and Barbuda", - }, - { - flag: "AI", - country: "Anguilla", - }, - { - flag: "AL", - country: "Albania", - }, - { - flag: "AM", - country: "Armenia", - }, - { - flag: "AN", - country: "Netherlands Antilles", - }, - { - flag: "AO", - country: "Angola", - }, - { - flag: "AP", - country: "Asia/Pacific Region", - }, - { - flag: "AQ", - country: "Antarctica", - }, - { - flag: "AR", - country: "Argentina", - }, - { - flag: "AS", - country: "American Samoa", - }, - { - flag: "AT", - country: "Austria", - }, - { - flag: "AU", - country: "Australia", - }, - { - flag: "AW", - country: "Aruba", - }, - { - flag: "AX", - country: "Aland Islands", - }, - { - flag: "AZ", - country: "Azerbaijan", - }, - { - flag: "BA", - country: "Bosnia and Herzegovina", - }, - { - flag: "BB", - country: "Barbados", - }, - { - flag: "BD", - country: "Bangladesh", - }, - { - flag: "BE", - country: "Belgium", - }, - { - flag: "BF", - country: "Burkina Faso", - }, - { - flag: "BG", - country: "Bulgaria", - }, - { - flag: "BH", - country: "Bahrain", - }, - { - flag: "BI", - country: "Burundi", - }, - { - flag: "BJ", - country: "Benin", - }, - { - flag: "BL", - country: "Saint Barthelemy", - }, - { - flag: "BM", - country: "Bermuda", - }, - { - flag: "BN", - country: "Brunei", - }, - { - flag: "BO", - country: "Bolivia", - }, - { - flag: "BR", - country: "Brazil", - }, - { - flag: "BS", - country: "Bahamas", - }, - { - flag: "BT", - country: "Bhutan", - }, - { - flag: "BV", - country: "Bouvet Island", - }, - { - flag: "BW", - country: "Botswana", - }, - { - flag: "BY", - country: "Belarus", - }, - { - flag: "BZ", - country: "Belize", - }, - { - flag: "CA", - country: "Canada", - }, - { - flag: "CC", - country: "Cocos (Keeling) Islands", - }, - { - flag: "CD", - country: "Congo, The Democratic Republic of the", - }, - { - flag: "CF", - country: "Central African Republic", - }, - { - flag: "CG", - country: "Congo", - }, - { - flag: "CH", - country: "Switzerland", - }, - { - flag: "CI", - country: "Cote D'Ivoire", - }, - { - flag: "CK", - country: "Cook Islands", - }, - { - flag: "CL", - country: "Chile", - }, - { - flag: "CM", - country: "Cameroon", - }, - { - flag: "CN", - country: "China", - }, - { - flag: "CO", - country: "Colombia", - }, - { - flag: "CR", - country: "Costa Rica", - }, - { - flag: "CU", - country: "Cuba", - }, - { - flag: "CV", - country: "Cabo Verde", - }, - { - flag: "CX", - country: "Christmas Island", - }, - { - flag: "CY", - country: "Cyprus", - }, - { - flag: "CZ", - country: "Czechia", - }, - { - flag: "DE", - country: "Germany", - }, - { - flag: "DJ", - country: "Djibouti", - }, - { - flag: "DK", - country: "Denmark", - }, - { - flag: "DM", - country: "Dominica", - }, - { - flag: "DO", - country: "Dominican Republic", - }, - { - flag: "DZ", - country: "Algeria", - }, - { - flag: "EC", - country: "Ecuador", - }, - { - flag: "EE", - country: "Estonia", - }, - { - flag: "EG", - country: "Egypt", - }, - { - flag: "EH", - country: "Western Sahara", - }, - { - flag: "ER", - country: "Eritrea", - }, - { - flag: "ES", - country: "Spain", - }, - { - flag: "ET", - country: "Ethiopia", - }, - { - flag: "EU", - country: "Europe", - }, - { - flag: "FI", - country: "Finland", - }, - { - flag: "FJ", - country: "Fiji", - }, - { - flag: "FK", - country: "Falkland Islands (Malvinas)", - }, - { - flag: "FM", - country: "Micronesia, Federated States of", - }, - { - flag: "FO", - country: "Faroe Islands", - }, - { - flag: "FR", - country: "France", - }, - { - flag: "FX", - country: "France, Metropolitan", - }, - { - flag: "GA", - country: "Gabon", - }, - { - flag: "GB", - country: "United Kingdom", - }, - { - flag: "GD", - country: "Grenada", - }, - { - flag: "GE", - country: "Georgia", - }, - { - flag: "GF", - country: "French Guiana", - }, - { - flag: "GG", - country: "Guernsey", - }, - { - flag: "GH", - country: "Ghana", - }, - { - flag: "GI", - country: "Gibraltar", - }, - { - flag: "GL", - country: "Greenland", - }, - { - flag: "GM", - country: "Gambia", - }, - { - flag: "GN", - country: "Guinea", - }, - { - flag: "GP", - country: "Guadeloupe", - }, - { - flag: "GQ", - country: "Equatorial Guinea", - }, - { - flag: "GR", - country: "Greece", - }, - { - flag: "GS", - country: "South Georgia and the South Sandwich Islands", - }, - { - flag: "GT", - country: "Guatemala", - }, - { - flag: "GU", - country: "Guam", - }, - { - flag: "GW", - country: "Guinea-Bissau", - }, - { - flag: "GY", - country: "Guyana", - }, - { - flag: "HK", - country: "Hong Kong", - }, - { - flag: "HM", - country: "Heard Island and McDonald Islands", - }, - { - flag: "HN", - country: "Honduras", - }, - { - flag: "HR", - country: "Croatia", - }, - { - flag: "HT", - country: "Haiti", - }, - { - flag: "HU", - country: "Hungary", - }, - { - flag: "ID", - country: "Indonesia", - }, - { - flag: "IE", - country: "Ireland", - }, - { - flag: "IL", - country: "Israel", - }, - { - flag: "IM", - country: "Isle of Man", - }, - { - flag: "IN", - country: "India", - }, - { - flag: "IO", - country: "British Indian Ocean Territory", - }, - { - flag: "IQ", - country: "Iraq", - }, - { - flag: "IR", - country: "Iran, Islamic Republic of", - }, - { - flag: "IS", - country: "Iceland", - }, - { - flag: "IT", - country: "Italy", - }, - { - flag: "JE", - country: "Jersey", - }, - { - flag: "JM", - country: "Jamaica", - }, - { - flag: "JO", - country: "Jordan", - }, - { - flag: "JP", - country: "Japan", - }, - { - flag: "KE", - country: "Kenya", - }, - { - flag: "KG", - country: "Kyrgyzstan", - }, - { - flag: "KH", - country: "Cambodia", - }, - { - flag: "KI", - country: "Kiribati", - }, - { - flag: "KM", - country: "Comoros", - }, - { - flag: "KN", - country: "Saint Kitts and Nevis", - }, - { - flag: "KP", - country: "Korea, Democratic People's Republic of", - }, - { - flag: "KR", - country: "South Korea", - }, - { - flag: "KW", - country: "Kuwait", - }, - { - flag: "KY", - country: "Cayman Islands", - }, - { - flag: "KZ", - country: "Kazakhstan", - }, - { - flag: "LA", - country: "Lao People's Democratic Republic", - }, - { - flag: "LB", - country: "Lebanon", - }, - { - flag: "LC", - country: "Saint Lucia", - }, - { - flag: "LI", - country: "Liechtenstein", - }, - { - flag: "LK", - country: "Sri Lanka", - }, - { - flag: "LR", - country: "Liberia", - }, - { - flag: "LS", - country: "Lesotho", - }, - { - flag: "LT", - country: "Lithuania", - }, - { - flag: "LU", - country: "Luxembourg", - }, - { - flag: "LV", - country: "Latvia", - }, - { - flag: "LY", - country: "Libya", - }, - { - flag: "MA", - country: "Morocco", - }, - { - flag: "MC", - country: "Monaco", - }, - { - flag: "MD", - country: "Moldova", - }, - { - flag: "ME", - country: "Montenegro", - }, - { - flag: "MF", - country: "Saint Martin", - }, - { - flag: "MG", - country: "Madagascar", - }, - { - flag: "MH", - country: "Marshall Islands", - }, - { - flag: "MK", - country: "North Macedonia", - }, - { - flag: "ML", - country: "Mali", - }, - { - flag: "MM", - country: "Myanmar", - }, - { - flag: "MN", - country: "Mongolia", - }, - { - flag: "MO", - country: "Macau", - }, - { - flag: "MP", - country: "Northern Mariana Islands", - }, - { - flag: "MQ", - country: "Martinique", - }, - { - flag: "MR", - country: "Mauritania", - }, - { - flag: "MS", - country: "Montserrat", - }, - { - flag: "MT", - country: "Malta", - }, - { - flag: "MU", - country: "Mauritius", - }, - { - flag: "MV", - country: "Maldives", - }, - { - flag: "MW", - country: "Malawi", - }, - { - flag: "MX", - country: "Mexico", - }, - { - flag: "MY", - country: "Malaysia", - }, - { - flag: "MZ", - country: "Mozambique", - }, - { - flag: "NA", - country: "Namibia", - }, - { - flag: "NC", - country: "New Caledonia", - }, - { - flag: "NE", - country: "Niger", - }, - { - flag: "NF", - country: "Norfolk Island", - }, - { - flag: "NG", - country: "Nigeria", - }, - { - flag: "NI", - country: "Nicaragua", - }, - { - flag: "NL", - country: "Netherlands", - }, - { - flag: "NO", - country: "Norway", - }, - { - flag: "NP", - country: "Nepal", - }, - { - flag: "NR", - country: "Nauru", - }, - { - flag: "NU", - country: "Niue", - }, - { - flag: "NZ", - country: "New Zealand", - }, - { - flag: "O1", - country: "Other", - }, - { - flag: "OM", - country: "Oman", - }, - { - flag: "PA", - country: "Panama", - }, - { - flag: "PE", - country: "Peru", - }, - { - flag: "PF", - country: "French Polynesia", - }, - { - flag: "PG", - country: "Papua New Guinea", - }, - { - flag: "PH", - country: "Philippines", - }, - { - flag: "PK", - country: "Pakistan", - }, - { - flag: "PL", - country: "Poland", - }, - { - flag: "PM", - country: "Saint Pierre and Miquelon", - }, - { - flag: "PN", - country: "Pitcairn", - }, - { - flag: "PR", - country: "Puerto Rico", - }, - { - flag: "PS", - country: "Palestine, State of", - }, - { - flag: "PT", - country: "Portugal", - }, - { - flag: "PW", - country: "Palau", - }, - { - flag: "PY", - country: "Paraguay", - }, - { - flag: "QA", - country: "Qatar", - }, - { - flag: "RE", - country: "Reunion", - }, - { - flag: "RO", - country: "Romania", - }, - { - flag: "RS", - country: "Serbia", - }, - { - flag: "RU", - country: "Russian Federation", - }, - { - flag: "RW", - country: "Rwanda", - }, - { - flag: "SA", - country: "Saudi Arabia", - }, - { - flag: "SB", - country: "Solomon Islands", - }, - { - flag: "SC", - country: "Seychelles", - }, - { - flag: "SD", - country: "Sudan", - }, - { - flag: "SE", - country: "Sweden", - }, - { - flag: "SG", - country: "Singapore", - }, - { - flag: "SH", - country: "Saint Helena", - }, - { - flag: "SI", - country: "Slovenia", - }, - { - flag: "SJ", - country: "Svalbard and Jan Mayen", - }, - { - flag: "SK", - country: "Slovakia", - }, - { - flag: "SL", - country: "Sierra Leone", - }, - { - flag: "SM", - country: "San Marino", - }, - { - flag: "SN", - country: "Senegal", - }, - { - flag: "SO", - country: "Somalia", - }, - { - flag: "SR", - country: "Suriname", - }, - { - flag: "ST", - country: "Sao Tome and Principe", - }, - { - flag: "SV", - country: "El Salvador", - }, - { - flag: "SY", - country: "Syrian Arab Republic", - }, - { - flag: "SZ", - country: "Eswatini", - }, - { - flag: "TC", - country: "Turks and Caicos Islands", - }, - { - flag: "TD", - country: "Chad", - }, - { - flag: "TF", - country: "French Southern Territories", - }, - { - flag: "TG", - country: "Togo", - }, - { - flag: "TH", - country: "Thailand", - }, - { - flag: "TJ", - country: "Tajikistan", - }, - { - flag: "TK", - country: "Tokelau", - }, - { - flag: "TL", - country: "Timor-Leste", - }, - { - flag: "TM", - country: "Turkmenistan", - }, - { - flag: "TN", - country: "Tunisia", - }, - { - flag: "TO", - country: "Tonga", - }, - { - flag: "TR", - country: "Türkiye", - }, - { - flag: "TT", - country: "Trinidad and Tobago", - }, - { - flag: "TV", - country: "Tuvalu", - }, - { - flag: "TW", - country: "Taiwan", - }, - { - flag: "TZ", - country: "Tanzania, United Republic of", - }, - { - flag: "UA", - country: "Ukraine", - }, - { - flag: "UG", - country: "Uganda", - }, - { - flag: "UM", - country: "United States Minor Outlying Islands", - }, - { - flag: "US", - country: "United States", - }, - { - flag: "UY", - country: "Uruguay", - }, - { - flag: "UZ", - country: "Uzbekistan", - }, - { - flag: "VA", - country: "Holy See (Vatican City State)", - }, - { - flag: "VC", - country: "Saint Vincent and the Grenadines", - }, - { - flag: "VE", - country: "Venezuela", - }, - { - flag: "VG", - country: "Virgin Islands, British", - }, - { - flag: "VI", - country: "Virgin Islands, U.S.", - }, - { - flag: "VN", - country: "Vietnam", - }, - { - flag: "VU", - country: "Vanuatu", - }, - { - flag: "WF", - country: "Wallis and Futuna", - }, - { - flag: "WS", - country: "Samoa", - }, - { - flag: "XX", - country: "", - }, - { - flag: "YE", - country: "Yemen", - }, - { - flag: "YT", - country: "Mayotte", - }, - { - flag: "ZA", - country: "South Africa", - }, - { - flag: "ZM", - country: "Zambia", - }, - { - flag: "ZW", - country: "Zimbabwe", - }, -]; - -export const description: any = { - auth: 4, - title: __filename, - method: 'GET', - description: 'Return country name from country code', - params: [ - { - type: 'string', - name: 'flag', - optional: false, - description: 'country code', - }, - ], -}; - -/** -* -* @param flag Country code -* @returns {string} Fullname of country -*/ -const name = (flag: string): string => { - const find = flags.find(r => r.flag.toLowerCase() == flag.toLowerCase()); - - if (!find) return null; - - return find.country; -}; - -export default name; diff --git a/src/utility/tools/routes/download/difficulty.ts b/src/utility/tools/routes/download/difficulty.ts deleted file mode 100644 index 9cc35c22..00000000 --- a/src/utility/tools/routes/download/difficulty.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { request } from "../../../request"; -import fs from "fs"; - - -export const description: any = { - auth: 4, - title: __filename, - method: 'GET', - description: 'Download \`\`\`.osu\`\`\` file', - params: [ - { - type: 'number', - name: 'diff_id', - optional: false, - description: 'id of the beatmap', - }, - { - type: 'number', - name: 'path', - optional: false, - description: 'Folder path', - }, - { - type: 'string', - name: 'name', - optional: false, - description: 'File name (without extension)', - }, - { - type: 'boolean', - name: 'overwrite', - optional: true, - description: 'Overwrite file', - }, - ], -}; - -export interface types { - (diff_id: number, path: string, name: string | number, overwrite?: boolean): Promise; -}; - - -const name: types = async (diff_id, path, name, overwrite) => { - if (!fs.existsSync(path)) fs.mkdirSync(path, { recursive: true }); - - let file = ''; - if (name === undefined) name = diff_id; - if (path !== undefined) file = `${path}/${name}.osu`; - else file = `${name}.osu`; - - if (fs.existsSync(file) && overwrite != true) return file; - - const data = await request(`https://osu.ppy.sh/osu/${diff_id}`, { method: "GET" }); - if (!data.includes('osu file format v')) return null; - - fs.writeFileSync(file, data, 'utf-8'); - return file; -}; - -export default name; \ No newline at end of file diff --git a/tools/accuracy.ts b/tools/accuracy.ts index 0dc47024..267f28c4 100644 --- a/tools/accuracy.ts +++ b/tools/accuracy.ts @@ -1,5 +1,6 @@ import { IError } from "../types"; import { GamemodeEnum } from "../types/enums"; +import { AccuracyResponse } from "../types/tools"; type Hits = { @@ -18,16 +19,13 @@ type Hits = { miss?: any; }; -type Responnse = { - accuracy: number; - fc_accuracy: number; -} & IError; +type Response = AccuracyResponse & IError; -export const calculate_accuracy = (hits: Hits, mode: GamemodeEnum): Responnse => { +export const calculate_accuracy = (hits: Hits, mode: GamemodeEnum | string | number): Response => { if (Object.keys(hits).length == 0) { - return { error: new Error('Provide hits (300, 100, 50, etc)') } as Responnse; + return { error: new Error('Provide hits (300, 100, 50, etc)') } as Response; }; @@ -43,24 +41,28 @@ export const calculate_accuracy = (hits: Hits, mode: GamemodeEnum): Responnse => switch (mode) { + case 'osu': case GamemodeEnum.osu: accuracy = (100.0 * (6 * h300 + 2 * h100 + h50)) / (6 * (h50 + h100 + h300 + h0)); fc_accuracy = (100.0 * (6 * (h300 + h0) + 2 * h100 + h50)) / (6 * (h50 + h100 + (h300 + h0) + 0)); break; + case 'taiko': case GamemodeEnum.taiko: accuracy = (100.0 * (2 * h300 + h100)) / (2 * (h300 + h100 + h0)); fc_accuracy = (100.0 * (2 * (h300 + h0) + h100)) / (2 * ((h300 + h0) + h100 + 0)); break; + case 'fruits': case GamemodeEnum.fruits: accuracy = (100.0 * (h300 + h100 + h50)) / (h300 + h100 + h50 + katu + h0); fc_accuracy = (100.0 * ((h300 + h0) + h100 + h50)) / ((h300 + h0) + h100 + h50 + katu + 0); break; + case 'mania': case GamemodeEnum.mania: accuracy = (100.0 * (6 * geki + 6 * h300 + 4 * katu + 2 * h100 + h50)) / (6 * (h50 + h100 + h300 + h0 + geki + katu)); @@ -69,12 +71,12 @@ export const calculate_accuracy = (hits: Hits, mode: GamemodeEnum): Responnse => break; default: - return { error: new Error(`Unsupported gamemode: ${mode}}`) } as Responnse; + return { error: new Error(`Unsupported gamemode: ${mode}}`) } as Response; }; return { accuracy, fc_accuracy, - } as Responnse; + } as Response; }; \ No newline at end of file diff --git a/tools/index.ts b/tools/index.ts index 871972ff..e41b02f1 100644 --- a/tools/index.ts +++ b/tools/index.ts @@ -2,6 +2,7 @@ export { beatmaps_download } from "../api/v2/beatmaps_download"; export { calculate_accuracy } from "./accuracy"; export { calculate_mods } from "./mods"; export { country_details } from "./country"; +export { calculate_rank } from "./rank"; diff --git a/tools/rank.ts b/tools/rank.ts new file mode 100644 index 00000000..88bf4ccd --- /dev/null +++ b/tools/rank.ts @@ -0,0 +1,126 @@ +import { IError } from "../types"; +import { GamemodeEnum, ModsBitwise, ModsEnum } from "../types/enums"; +import { RankResponse } from "../types/tools"; +import { calculate_accuracy } from "./accuracy"; +import { calculate_mods } from "./mods"; + + +type Hits = { + 300?: any; + 100?: any; + 50?: any; + 0?: any; + geki?: any; + katu?: any; + + perfect?: any; + great?: any; + good?: any; + ok?: any; + meh?: any; + miss?: any; +}; + +type Response = RankResponse & IError; + + + +export const calculate_rank = (hits: Hits, mods: string | number = 0, mode: GamemodeEnum | string | number): Response => { + if (Object.keys(hits).length == 0) { + return { error: new Error('Provide hits (300, 100, 50, etc)') } as Response; + }; + + + const { name: modsName } = calculate_mods(mods);; + const { accuracy } = calculate_accuracy(hits, mode); + + const geki = parseInt(hits?.geki || hits.perfect || '0'); + const h300 = parseInt(hits?.[300] || hits.great || '0'); + const katu = parseInt(hits?.katu || hits.good || '0'); + const h100 = parseInt(hits?.[100] || hits.ok || '0'); + const h50 = parseInt(hits?.[50] || hits.meh || '0'); + const h0 = parseInt(hits?.[0] || hits.miss || '0'); + + const is_silver = /hd|fl/i.test(modsName); + + + let total = 0; + + let r300 = 0; + let r50 = 0; + + let rank = ''; + + + switch (mode) { + case 'osu': + case GamemodeEnum.osu: + total = +h300 + +h100 + +h50 + +h0; + + r300 = +h300 / total; + r50 = +h50 / total; + + if (r300 === 1) rank = is_silver ? 'XH' : 'X'; + else if (r300 > 0.9 && r50 < 0.01 && h0 === 0) rank = is_silver ? 'SH' : 'S'; + else if ((r300 > 0.8 && h0 === 0) || r300 > 0.9) rank = 'A'; + else if ((r300 > 0.7 && h0 === 0) || r300 > 0.8) rank = 'B'; + else if (r300 > 0.6) rank = 'C'; + else rank = 'D'; + + break; + + case 'taiko': + case GamemodeEnum.taiko: + total = +h300 + +h100 + +h50 + +h0; + + r300 = +h300 / total; + r50 = +h50 / total; + + if (r300 === 1) rank = is_silver ? 'XH' : 'X'; + else if (r300 > 0.9 && r50 < 0.01 && h0 === 0) rank = is_silver ? 'SH' : 'S'; + else if ((r300 > 0.8 && h0 === 0) || r300 > 0.9) rank = 'A'; + else if ((r300 > 0.7 && h0 === 0) || r300 > 0.8) rank = 'B'; + else if (r300 > 0.6) rank = 'C'; + else rank = 'D'; + + break; + + case 'fruits': + case GamemodeEnum.fruits: + total = +h300 + +h100 + +h50 + +h0 + +katu; + + r300 = +h300 / total; + r50 = +h50 / total; + + if (accuracy === 1) rank = is_silver ? 'XH' : 'X'; + else if (accuracy > 0.98) rank = is_silver ? 'SH' : 'S'; + else if (accuracy > 0.94) rank = 'A'; + else if (accuracy > 0.9) rank = 'B'; + else if (accuracy > 0.85) rank = 'C'; + else rank = 'D'; + + break; + + case 'mania': + case GamemodeEnum.mania: + total = +h300 + +h100 + +h50 + +h0 + +geki + +katu; + + r300 = +h300 / total; + r50 = +h50 / total; + + if (accuracy === 1) rank = is_silver ? 'XH' : 'X'; + else if (accuracy > 0.95) rank = is_silver ? 'SH' : 'S'; + else if (accuracy > 0.9) rank = 'A'; + else if (accuracy > 0.8) rank = 'B'; + else if (accuracy > 0.7) rank = 'C'; + else rank = 'D'; + + break; + }; + + console.log(mode, rank, is_silver, accuracy); + + return { + rank, + } as Response; +}; \ No newline at end of file diff --git a/types/enums.ts b/types/enums.ts index cc1c6bd8..34c45164 100644 --- a/types/enums.ts +++ b/types/enums.ts @@ -78,6 +78,40 @@ export const ModsCodes: { 1073741824: 'MR', }; +export enum ModsEnum { + 'NF' = 1, + 'EZ' = 2, + 'TD' = 4, + 'HD' = 8, + 'HR' = 16, + 'SD' = 32, + 'DT' = 64, + 'RX' = 128, + 'HT' = 256, + 'NC' = 576, + 'FL' = 1024, + 'AT' = 2048, + 'SO' = 4096, + 'AP' = 8192, + 'PF' = 16416, + '4K' = 32768, + '5K' = 65536, + '6K' = 131072, + '7K' = 262144, + '8K' = 524288, + 'FI' = 1048576, + 'RD' = 2097152, + 'LM' = 4194304, + 'Target' = 8388608, + '9K' = 16777216, + 'KeyCoop' = 33554432, + '1K' = 67108864, + '3K' = 134217728, + '2K' = 268435456, + 'ScoreV2' = 536870912, + 'MR' = 1073741824, +}; + export const ModsBitwise = { None: 0, diff --git a/types/tools.ts b/types/tools.ts index d37ced5a..6880ab12 100644 --- a/types/tools.ts +++ b/types/tools.ts @@ -6,4 +6,13 @@ export interface ModsResponse { export interface CountryResponse { code: string; name: string; +}; + +export interface AccuracyResponse { + accuracy: number; + fc_accuracy: number; +}; + +export interface RankResponse { + rank: string; }; \ No newline at end of file From 5c0b3cd50e88c6266f528d06808fd7c901b454df Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 27 Apr 2024 13:53:22 +0300 Subject: [PATCH 138/259] total objects and pp --- src/index.ts | 2 - src/utility/mods.ts | 156 ------------------- src/utility/tools/index.ts | 43 ------ src/utility/tools/routes/pp/calculate.ts | 174 ---------------------- src/utility/tools/routes/rank.ts | 159 -------------------- src/utility/tools/routes/total_objects.ts | 92 ------------ tools/index.ts | 5 +- tools/objects.ts | 72 +++++++++ tools/rank.ts | 1 - types/tools.ts | 5 + 10 files changed, 81 insertions(+), 628 deletions(-) delete mode 100644 src/index.ts delete mode 100644 src/utility/mods.ts delete mode 100644 src/utility/tools/index.ts delete mode 100644 src/utility/tools/routes/pp/calculate.ts delete mode 100644 src/utility/tools/routes/rank.ts delete mode 100644 src/utility/tools/routes/total_objects.ts create mode 100644 tools/objects.ts diff --git a/src/index.ts b/src/index.ts deleted file mode 100644 index e87145bf..00000000 --- a/src/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * as mods from './utility/mods'; -export * as tools from './utility/tools/index'; \ No newline at end of file diff --git a/src/utility/mods.ts b/src/utility/mods.ts deleted file mode 100644 index 575cbb24..00000000 --- a/src/utility/mods.ts +++ /dev/null @@ -1,156 +0,0 @@ -const num_codes: { [key: string]: string } = { - 1: 'NF', - 2: 'EZ', - 4: 'TD', - 8: 'HD', - 16: 'HR', - 32: 'SD', - 64: 'DT', - 128: 'RX', - 256: 'HT', - 576: 'NC', - 1024: 'FL', - 2048: 'AT', - 4096: 'SO', - 8192: 'AP', - 16416: 'PF', - 32768: '4K', - 65536: '5K', - 131072: '6K', - 262144: '7K', - 524288: '8K', - 1048576: 'FI', - 2097152: 'RD', - 4194304: 'LM', - 8388608: 'Target', - 16777216: '9K', - 33554432: 'KeyCoop', - 67108864: '1K', - 134217728: '3K', - 268435456: '2K', - 536870912: 'ScoreV2', - 1073741824: 'MR', -}; - -export const enums = { - None: 0, - NoFail: 1, - Easy: 1 << 1, - TouchDevice: 1 << 2, - Hidden: 1 << 3, - HardRock: 1 << 4, - SuddenDeath: 1 << 5, - DoubleTime: 1 << 6, - Relax: 1 << 7, - HalfTime: 1 << 8, - Nightcore: 1 << 9, // DoubleTime mod - Flashlight: 1 << 10, - Autoplay: 1 << 11, - SpunOut: 1 << 12, - Relax2: 1 << 13, // Autopilot - Perfect: 1 << 14, // SuddenDeath mod - Key4: 1 << 15, - Key5: 1 << 16, - Key6: 1 << 17, - Key7: 1 << 18, - Key8: 1 << 19, - FadeIn: 1 << 20, - Random: 1 << 21, - Cinema: 1 << 22, - Target: 1 << 23, - Key9: 1 << 24, - KeyCoop: 1 << 25, - Key1: 1 << 26, - Key3: 1 << 27, - Key2: 1 << 28, - KeyMod: 521109504, - FreeModAllowed: 522171579, - ScoreIncreaseMods: 1049662 -}; - -const mods_order: { [key: string]: number } = { - nf: 0, - ez: 1, - hd: 2, - dt: 3, - nc: 3, - ht: 3, - hr: 4, - so: 5, - sd: 5, - pf: 5, - fl: 6, - td: 7, -}; - - -export const description: any = { - auth: 4, - title: __filename, - method: 'GET', - description: 'Return number or name of the mods', - params: [ - { - type: 'string/number', - name: 'mods', - optional: false, - description: '\`\`\`HDDT\`\`\` or \`\`\`72\`\`\`', - }, - ], -}; - - -/** - * - * @param mods Mods number - * @returns {string} Mods name - */ -const name = (mods: number): string => { - let enabled = []; - let _mods = mods; - let converted = ''; - - const values = Object.keys(num_codes).map(a => Number(a)); - - for (let i = values.length - 1; i >= 0; i--) { - const v = values[i]; - if (_mods >= v) { - const mode = num_codes[v]; - enabled.push({ i: mods_order[mode.toLowerCase()], n: mode }); - _mods -= v; - }; - }; - - enabled = enabled.sort((a, b) => (a.i > b.i ? 1 : b.i > a.i ? -1 : 0)); - enabled.filter(r => converted += r.n); - - - // if (converted === '') return 'NM'; - return converted; -}; - -/** - * - * @param mods Mods name - * @returns {string | undefined} Mods number - */ -const id = (mods: string | number): number | undefined => { - if (!mods) return undefined; - if (typeof mods == 'number') return mods; - - let _mods = 0; - const name = mods.match(/.{1,2}/g); - if (name == null) return undefined; - - const values: string[] = Object.keys(num_codes).map((a) => a); - for (let i = 0; i < name.length; i++) { - const find = values.find((v) => num_codes[v].toLowerCase() === name[i].toLowerCase()); - _mods += parseInt(find); - }; - - return _mods; -}; - -export { id, name }; - -export const desc: object = description; \ No newline at end of file diff --git a/src/utility/tools/index.ts b/src/utility/tools/index.ts deleted file mode 100644 index 0096315e..00000000 --- a/src/utility/tools/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -import _rank, { description as _rank_desc } from "./routes/rank"; -import _country, { description as _country_desc } from "./routes/country"; -import _accuracy, { description as _accuracy_desc } from "./routes/accuracy"; -import _total_objects, { description as _total_objects_desc } from "./routes/total_objects"; -import _download_difficulty, { description as _download_difficulty_desc } from "./routes/download/difficulty"; -import _pp_calculate, { description as _pp_calculate_desc } from "./routes/pp/calculate"; - - -export const rank = _rank; -export const country = _country -export const accuracy = _accuracy -export const total_objects = _total_objects; -export const download = { - difficulty: _download_difficulty -}; -export const pp = { - calculate: _pp_calculate -}; - - -export const desc: { - rank: object, - country: object, - accuracy: object, - total_objects: object, - download: { - difficulty: object, - }, - pp: { - calculate: object, - }, -} = { - rank: _rank_desc, - country: _country_desc, - accuracy: _accuracy_desc, - total_objects: _total_objects_desc, - download: { - difficulty: _download_difficulty_desc, - }, - pp: { - calculate: _pp_calculate_desc, - }, -} \ No newline at end of file diff --git a/src/utility/tools/routes/pp/calculate.ts b/src/utility/tools/routes/pp/calculate.ts deleted file mode 100644 index 0e4171b1..00000000 --- a/src/utility/tools/routes/pp/calculate.ts +++ /dev/null @@ -1,174 +0,0 @@ -import { request } from "../../../request"; - -export const description: any = { - auth: 4, - title: __filename, - method: 'GET', - description: 'Return pp and details about beatmap', - params: [ - { - type: 'string', - name: 'id', - optional: false, - description: 'id of the beatmap', - }, - { - type: 'string/number', - name: 'mods', - optional: true, - description: 'Name of the mods \`\`\`HDDT\`\`\` or mods number \`\`\`72\`\`\`', - }, - { - type: 'string/number', - name: 'combo', - optional: true, - description: 'Max combo of the play', - }, - { - type: 'number', - name: 'miss', - optional: true, - description: 'Amount of misses', - }, - { - type: 'number', - name: 'acc', - optional: true, - description: 'Amount of accuracy', - }, - ], -}; - -export interface types { - (id: number, mods?: number, combo?: number, miss?: number, acc?: number): Promise; -}; - -export interface response { - id: { - set: number; - diff: number; - }; - mods: { - id: number; - name: string; - }; - status: { - id: number; - name: string; - }; - stats: { - star: { - pure: number; - aim: number; - speed: number; - }; - ar: number; - od: number; - cs: number; - hp: number; - bpm: { - api: number; - min: number; - max: number; - }; - combo: number; - time: { - full: number; - drain: number; - }; - }; - pp: { - current: number; - fc: number; - acc: { - 80: number; - 81: number; - 82: number; - 83: number; - 84: number; - 85: number; - 86: number; - 87: number; - 88: number; - 89: number; - 90: number; - 91: number; - 92: number; - 93: number; - 94: number; - 95: number; - 96: number; - 97: number; - 98: number; - 99: number; - 100: number; - }; - }; - data: { - artist: string; - title: string; - creator: { - id: number; - name: string; - }; - favs: number; - rating: number; - source: string; - genre_id: { - id: number; - name: string; - }; - language_id: { - id: number; - name: string; - }; - tags: string; - diff: string; - }; - other: { - download_unavailable: boolean; - audio_unavailable: boolean; - storyboard: boolean; - video: boolean; - packs: string; - bg: { - full: string; - raw: string; - slim: { - 1: string; - 2: string; - }; - cover: { - 1: string; - 2: string; - }; - card: { - 1: string; - 2: string; - }; - list: { - 1: string; - 2: string; - }; - }; - }; - req: { - id: number; - combo: number; - mods: number; - acc: number; - miss: number; - }; -} - - -const name: types = async (id, mods, combo, miss, acc) => { - const data = await request('https://pp.osuck.net/pp', { method: 'GET', params: { id, mods, combo, miss, acc } }); - if (!data.id) return null; - - return data; -}; - -export default name; - -export const desc: object = description; \ No newline at end of file diff --git a/src/utility/tools/routes/rank.ts b/src/utility/tools/routes/rank.ts deleted file mode 100644 index 448dbf3c..00000000 --- a/src/utility/tools/routes/rank.ts +++ /dev/null @@ -1,159 +0,0 @@ -import { name as mods_name } from "../../mods"; - -export const description: any = { - auth: 4, - title: __filename, - method: 'GET', - description: 'Return rank letter from hits', - params: [ - { - type: 'string', - name: '300', - optional: false, - description: 'Amount of 300', - }, - { - type: 'string', - name: 'geki', - optional: false, - description: 'Amount of geki (300g)', - }, - { - type: 'string', - name: '100', - optional: false, - description: 'Amount of 100', - }, - { - type: 'string', - name: 'katu', - optional: false, - description: 'Amount of katu (100k)', - }, - { - type: 'string', - name: '50', - optional: false, - description: 'Amount of 50', - }, - { - type: 'string', - name: '0', - optional: false, - description: 'Amount of misses', - }, - { - type: 'string', - name: 'mods', - optional: false, - description: 'Name of the mods \`\`\`HDDT\`\`\` or mods number \`\`\`72\`\`\`', - }, - { - type: 'string', - name: 'mode', - optional: false, - description: '\`\`\`osu\`\`\` or \`\`\`fruits\`\`\` or \`\`\`mania\`\`\` or \`\`\`taiko\`\`\`', - }, - ], -}; - -export interface types { - (hits: { - 300: string, - 100: string, - 50: string, - 0: string, - geki: string, - katu: string - }, mods: any, mode: 'osu' | 'fruits' | 'taiko' | 'mania'): string; -}; - -const name: types = (hits, mods, mode = 'osu'): string => { - const h300 = parseInt(hits[300]); - const h100 = parseInt(hits[100]); - const h50 = parseInt(hits[50]); - const h0 = parseInt(hits[0]); - const geki = parseInt(hits.geki); - const katu = parseInt(hits.katu); - - if (!isNaN(mods)) mods = mods_name(mods); - const silver = mods.toLowerCase().indexOf('hd') > -1 ? true : mods.toLowerCase().indexOf('fl') > -1 ? true : false; - - let total = 0; - let acc = 0.0; - - let r300 = 0; - let r50 = 0; - - let rank = ''; - - switch (mode) { - case 'osu': - total = +h300 + +h100 + +h50 + +h0; - acc = total > 0 ? (+h50 * 50 + +h100 * 100 + +h300 * 300) / (total * 300) : 1; - - r300 = +h300 / total; - r50 = +h50 / total; - - if (r300 === 1) rank = silver ? 'XH' : 'X'; - else if (r300 > 0.9 && r50 < 0.01 && h0 === 0) rank = silver ? 'SH' : 'S'; - else if ((r300 > 0.8 && h0 === 0) || r300 > 0.9) rank = 'A'; - else if ((r300 > 0.7 && h0 === 0) || r300 > 0.8) rank = 'B'; - else if (r300 > 0.6) rank = 'C'; - else rank = 'D'; - - break; - - case 'taiko': - total = +h300 + +h100 + +h50 + +h0; - acc = total > 0 ? (+h100 * 150 + +h300 * 300) / (total * 300) : 1; - - r300 = +h300 / total; - r50 = +h50 / total; - - if (r300 === 1) rank = silver ? 'XH' : 'X'; - else if (r300 > 0.9 && r50 < 0.01 && h0 === 0) rank = silver ? 'SH' : 'S'; - else if ((r300 > 0.8 && h0 === 0) || r300 > 0.9) rank = 'A'; - else if ((r300 > 0.7 && h0 === 0) || r300 > 0.8) rank = 'B'; - else if (r300 > 0.6) rank = 'C'; - else rank = 'D'; - - break; - - case 'fruits': - total = +h300 + +h100 + +h50 + +h0 + +katu; - acc = total > 0 ? (+h50 + +h100 + +h300) / total : 1; - - r300 = +h300 / total; - r50 = +h50 / total; - - if (acc === 1) rank = silver ? 'XH' : 'X'; - else if (acc > 0.98) rank = silver ? 'SH' : 'S'; - else if (acc > 0.94) rank = 'A'; - else if (acc > 0.9) rank = 'B'; - else if (acc > 0.85) rank = 'C'; - else rank = 'D'; - - break; - - case 'mania': - total = +h300 + +h100 + +h50 + +h0 + +geki + +katu; - acc = total > 0 ? (+h50 * 50 + +h100 * 100 + +katu * 200 + (+h300 + +geki) * 300) / (total * 300) : 1; - - r300 = +h300 / total; - r50 = +h50 / total; - - if (acc === 1) rank = silver ? 'XH' : 'X'; - else if (acc > 0.95) rank = silver ? 'SH' : 'S'; - else if (acc > 0.9) rank = 'A'; - else if (acc > 0.8) rank = 'B'; - else if (acc > 0.7) rank = 'C'; - else rank = 'D'; - - break; - }; - - return rank; -}; - -export default name; \ No newline at end of file diff --git a/src/utility/tools/routes/total_objects.ts b/src/utility/tools/routes/total_objects.ts deleted file mode 100644 index 83085ba6..00000000 --- a/src/utility/tools/routes/total_objects.ts +++ /dev/null @@ -1,92 +0,0 @@ -export const description: any = { - auth: 4, - title: __filename, - method: 'GET', - description: 'Return total object count based on mode and hits count', - params: [ - { - type: 'string', - name: '300', - optional: false, - description: 'Amount of 300', - }, - { - type: 'string', - name: 'geki', - optional: false, - description: 'Amount of geki (300g)', - }, - { - type: 'string', - name: '100', - optional: false, - description: 'Amount of 100', - }, - { - type: 'string', - name: 'katu', - optional: false, - description: 'Amount of katu (100k)', - }, - { - type: 'string', - name: '50', - optional: false, - description: 'Amount of 50', - }, - { - type: 'string', - name: '0', - optional: false, - description: 'Amount of misses', - }, - { - type: 'string', - name: 'mode', - optional: false, - description: '\`\`\`osu\`\`\` or \`\`\`fruits\`\`\` or \`\`\`mania\`\`\` or \`\`\`taiko\`\`\`', - }, - ], -}; - -export interface types { - (hits: { - 300: string, - 100: string, - 50: string, - 0: string, - geki: string, - katu: string - }, mode: 'osu' | 'fruits' | 'taiko' | 'mania'): number; -}; - - -const name: types = (hits, mode = 'osu') => { - const h300 = parseInt(hits[300]); - const h100 = parseInt(hits[100]); - const h50 = parseInt(hits[50]); - const h0 = parseInt(hits[0]); - const geki = parseInt(hits.geki); - const katu = parseInt(hits.katu); - - let total_objects = 0; - - switch (mode) { - case 'osu': - total_objects = h300 + h100 + h50 + h0; - break; - case 'taiko': - total_objects = h300 + h100 + h0; - break; - case 'fruits': - total_objects = h300 + h100 + katu + h50 + h0; - break; - case 'mania': - total_objects = h300 + geki + h100 + katu + h50 + h0; - break; - }; - - return total_objects; -}; - -export default name; \ No newline at end of file diff --git a/tools/index.ts b/tools/index.ts index e41b02f1..a59e216f 100644 --- a/tools/index.ts +++ b/tools/index.ts @@ -3,10 +3,13 @@ export { calculate_accuracy } from "./accuracy"; export { calculate_mods } from "./mods"; export { country_details } from "./country"; export { calculate_rank } from "./rank"; +export { calculate_total_objects } from "./objects"; - +export const calculate_pp = () => { + return new Error('Use rosu-pp-js instead'); +}; diff --git a/tools/objects.ts b/tools/objects.ts new file mode 100644 index 00000000..bb1b5ff6 --- /dev/null +++ b/tools/objects.ts @@ -0,0 +1,72 @@ +import { IError } from "../types"; +import { GamemodeEnum } from "../types/enums"; +import { TotalObjectsResponse } from "../types/tools"; + + +type Hits = { + 300?: any; + 100?: any; + 50?: any; + 0?: any; + geki?: any; + katu?: any; + + perfect?: any; + great?: any; + good?: any; + ok?: any; + meh?: any; + miss?: any; +}; + +type Response = TotalObjectsResponse & IError; + + + +export const calculate_total_objects = (hits: Hits, mode: GamemodeEnum | string | number): Response => { + if (Object.keys(hits).length == 0) { + return { error: new Error('Provide hits (300, 100, 50, etc)') } as Response; + }; + + + const geki = parseInt(hits?.geki || hits.perfect || '0'); + const h300 = parseInt(hits?.[300] || hits.great || '0'); + const katu = parseInt(hits?.katu || hits.good || '0'); + const h100 = parseInt(hits?.[100] || hits.ok || '0'); + const h50 = parseInt(hits?.[50] || hits.meh || '0'); + const h0 = parseInt(hits?.[0] || hits.miss || '0'); + + + let total_objects = 0; + + switch (mode) { + case 'osu': + case GamemodeEnum.osu: + total_objects = h300 + h100 + h50 + h0; + break; + + case 'taiko': + case GamemodeEnum.taiko: + total_objects = h300 + h100 + h0; + break; + + case 'fruits': + case GamemodeEnum.fruits: + total_objects = h300 + h100 + katu + h50 + h0; + break; + + case 'mania': + case GamemodeEnum.mania: + total_objects = h300 + geki + h100 + katu + h50 + h0; + break; + + default: + return { error: new Error(`Unsupported gamemode: ${mode}}`) } as Response; + }; + + + return { + amount: total_objects, + mode: mode, + } as Response; +}; \ No newline at end of file diff --git a/tools/rank.ts b/tools/rank.ts index 88bf4ccd..de84b24f 100644 --- a/tools/rank.ts +++ b/tools/rank.ts @@ -118,7 +118,6 @@ export const calculate_rank = (hits: Hits, mods: string | number = 0, mode: Game break; }; - console.log(mode, rank, is_silver, accuracy); return { rank, diff --git a/types/tools.ts b/types/tools.ts index 6880ab12..6f1e979f 100644 --- a/types/tools.ts +++ b/types/tools.ts @@ -15,4 +15,9 @@ export interface AccuracyResponse { export interface RankResponse { rank: string; +}; + +export type TotalObjectsResponse = { + amount: number; + mode: string; }; \ No newline at end of file From 649e3e810685a20028a7adfd683902ed7139e6c8 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 27 Apr 2024 16:16:33 +0300 Subject: [PATCH 139/259] v1 migrate (temporary) --- api/v1/form/beatmap/scores.ts | 8 +- api/v1/form/match.ts | 9 +- api/v1/form/replays.ts | 39 -------- api/v1/form/user/best.ts | 7 +- api/v1/form/user/details.ts | 5 +- api/v1/form/user/recent.ts | 7 +- api/v1/pre | 37 -------- api/v1/routes/beatmap/creator.ts | 14 +-- api/v1/routes/beatmap/diff.ts | 18 ++-- api/v1/routes/beatmap/scores.ts | 14 +-- api/v1/routes/beatmap/set.ts | 14 +-- api/v1/routes/match.ts | 19 ++-- api/v1/routes/replay.ts | 131 -------------------------- api/v1/routes/user/details.ts | 17 ++-- api/v1/routes/user/scores-category.ts | 13 +-- index.ts | 4 + api/v1/index.ts => routes/v1.ts | 24 ++--- utility/auth.ts | 11 +-- 18 files changed, 98 insertions(+), 293 deletions(-) delete mode 100644 api/v1/form/replays.ts delete mode 100644 api/v1/pre delete mode 100644 api/v1/routes/replay.ts rename api/v1/index.ts => routes/v1.ts (68%) diff --git a/api/v1/form/beatmap/scores.ts b/api/v1/form/beatmap/scores.ts index 3bd4ee5e..5166b4cf 100644 --- a/api/v1/form/beatmap/scores.ts +++ b/api/v1/form/beatmap/scores.ts @@ -1,12 +1,10 @@ -import { name as mods_name } from "../../../../utility/mods"; -import { accuracy } from "../../../../utility/tools/index"; +import { calculate_accuracy, calculate_mods } from "../../../../tools/index"; const name = (data: any, mode: any) => { const info = []; for (let i = 0; i < data.length; i++) { const d = data[i]; - console.log(d); const score: any = { date: d.date, @@ -33,14 +31,14 @@ const name = (data: any, mode: any) => { }, mods: { id: +d.enabled_mods, - name: mods_name(+d.enabled_mods), + name: calculate_mods(+d.enabled_mods).name || '', }, accuracy: 0, pp: parseFloat(d.pp), replay: +d.replay_available, }; - score.accuracy = accuracy(score.hits, mode); + score.accuracy = calculate_accuracy(score.hits, mode).accuracy || 0; info.push(score); diff --git a/api/v1/form/match.ts b/api/v1/form/match.ts index ccdee3b7..fd62a869 100644 --- a/api/v1/form/match.ts +++ b/api/v1/form/match.ts @@ -1,11 +1,12 @@ -import { name as mods_name } from "../../../utility/mods"; +import { calculate_mods } from "../../../tools/index"; + const modes = ['std', 'taiko', 'ctb', 'mania']; const scoring = ['Score', 'Accuracy', 'Combo', 'Score v2']; const team = ['Head to head', 'Tag Co-op', 'Team vs', 'Tag Team vs']; const teams = ['no team', 'blue', 'red']; -const name = (data: any) => { +const name = (data: any) => { const match: any = { match: { id: +data.match.match_id, @@ -44,7 +45,7 @@ const name = (data: any) => { }, mods: { id: +g.mods, - name: mods_name(+g.mods), + name: calculate_mods(+g.mods).name || '', }, scores: [], }; @@ -76,7 +77,7 @@ const name = (data: any) => { }, mods: { id: +ss.enabled_mods, - name: mods_name(+ss.enabled_mods), + name: calculate_mods(+ss.enabled_mods).name || '', }, rank: g.rank, pass: g.pass, diff --git a/api/v1/form/replays.ts b/api/v1/form/replays.ts deleted file mode 100644 index af7a46bb..00000000 --- a/api/v1/form/replays.ts +++ /dev/null @@ -1,39 +0,0 @@ -import fs from "fs"; - -declare const Buffer: any; - -const lzma = require('lzma-native'); -const osr = require('node-osr'); - - -const name = (data: any, map: any, score: any, id: any, mods: any, file: string) => { - const decode = Buffer.from(data.content, data.encoding); - const replay = new osr.Replay(); - - replay.replay_data = lzma.decompress(decode); - - let hash = ''; - if (map) hash = map.difficulties.find((r: any) => r.id === id).file_md5; - - replay.beatmapMD5 = hash; - replay.playerName = score[0].user.name; - replay.number_300s = score[0].hits[300]; - replay.number_100s = score[0].hits[100]; - replay.number_50s = score[0].hits[50]; - replay.gekis = score[0].hits.geki; - replay.katus = score[0].hits.katu; - replay.misses = score[0].hits[0]; - replay.score = score[0].score.total; - replay.max_combo = score[0].combo.max; - replay.perfect_combo = score[0].combo.full; - replay.mods = mods; - replay.timestamp = new Date(score[0].date); - - const replayFile = replay.serializeSync(); - fs.writeFileSync(file, replayFile, data.encoding); - - return file; -}; - - -export default name; \ No newline at end of file diff --git a/api/v1/form/user/best.ts b/api/v1/form/user/best.ts index 1559f643..604df5e2 100644 --- a/api/v1/form/user/best.ts +++ b/api/v1/form/user/best.ts @@ -1,5 +1,4 @@ -import { accuracy } from "../../../../utility/tools/index"; -import { name as mods_name } from "../../../../utility/mods"; +import { calculate_accuracy, calculate_mods } from "../../../../tools/index"; const name = (data: any, mode: any) => { @@ -33,14 +32,14 @@ const name = (data: any, mode: any) => { }, mods: { id: +d.enabled_mods, - name: mods_name(+d.enabled_mods), + name: calculate_mods(+d.enabled_mods).name || '', }, accuracy: 0, pp: parseFloat(d.pp), replay: +d.replay_available, }; - score.accuracy = accuracy(score.hits, mode); + score.accuracy = calculate_accuracy(score.hits, mode).accuracy || 0; info.push(score); }; diff --git a/api/v1/form/user/details.ts b/api/v1/form/user/details.ts index ceccda88..0a52bbc4 100644 --- a/api/v1/form/user/details.ts +++ b/api/v1/form/user/details.ts @@ -1,4 +1,5 @@ -import { country } from "../../../../utility/tools/index"; +import { country_details } from "../../../../tools/index"; + const parse = (num: string | number, amount: number) => parseFloat(Number(num).toFixed(amount)) @@ -28,7 +29,7 @@ const name = (data: any) => { country: { flag: `https://osu.ppy.sh/images/flags/${data[0].country}.png`, short: data[0].country, - full: country(data[0].country), + full: country_details(data[0].country).name || '', }, play: { count: +data[0].playcount, diff --git a/api/v1/form/user/recent.ts b/api/v1/form/user/recent.ts index 44cea18a..60d9e5eb 100644 --- a/api/v1/form/user/recent.ts +++ b/api/v1/form/user/recent.ts @@ -1,5 +1,4 @@ -import { accuracy } from "../../../../utility/tools/index"; -import { name as mods_name } from "../../../../utility/mods"; +import { calculate_accuracy, calculate_mods } from "../../../../tools/index"; const name = (data: any, mode: any) => { @@ -32,12 +31,12 @@ const name = (data: any, mode: any) => { }, mods: { id: +d.enabled_mods, - name: mods_name(+d.enabled_mods), + name: calculate_mods(+d.enabled_mods).name || '', }, accuracy: 0, }; - score.accuracy = accuracy(score.hits, mode); + score.accuracy = calculate_accuracy(score.hits, mode).accuracy || 0; info.push(score); }; diff --git a/api/v1/pre b/api/v1/pre deleted file mode 100644 index 455d3b47..00000000 --- a/api/v1/pre +++ /dev/null @@ -1,37 +0,0 @@ -import { namespace, RequestNamespace } from "../../../../utility/request"; -import { id as mods_id } from "../../../../utility/mods"; -import form from "../../form/beatmap/set"; - -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/'); - -const _mode = [ - 'osu', - 'taiko', - 'fruits', - 'mania', -]; - - -export interface types { - (): Promise<{}>; -}; - - -const name: types = async (id, obj = {}) => { - const params = { - - }; - - const data = await request(``, { - method: 'GET', - params: params, - }); - - if (data.length == 0) return null; - - const format = form(data); - return format; -}; - - -export default name; \ No newline at end of file diff --git a/api/v1/routes/beatmap/creator.ts b/api/v1/routes/beatmap/creator.ts index 3131ea62..fae3c9d0 100644 --- a/api/v1/routes/beatmap/creator.ts +++ b/api/v1/routes/beatmap/creator.ts @@ -1,8 +1,8 @@ -import { namespace, RequestNamespace } from "../../../../utility/request"; -import { id as mods_id } from "../../../../utility/mods"; +import { request } from "../../../../utility/request"; +import { calculate_mods } from "../../../../tools/index"; + import form from "../../form/beatmap/creator"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/'); const _mode = [ 'osu', @@ -188,16 +188,18 @@ const name: types = async (user_id, obj = {}) => { a: obj.converted, h: obj.hash, since: obj.since, - mods: mods_id(obj.mods), + mods: calculate_mods(obj.mods).number, limit: obj.limit, }; + if (params.m == -1) delete params.m; + - const data = await request(`get_beatmaps`, { + const data = await request(`https://osu.ppy.sh/api/get_beatmaps`, { method: 'GET', params: params, }); - if (data.length == 0) return null; + if (data.length == 0) return []; const format = form(data); return format; diff --git a/api/v1/routes/beatmap/diff.ts b/api/v1/routes/beatmap/diff.ts index 2a75f4eb..7d69b753 100644 --- a/api/v1/routes/beatmap/diff.ts +++ b/api/v1/routes/beatmap/diff.ts @@ -1,8 +1,8 @@ -import { namespace, RequestNamespace } from "../../../../utility/request"; -import { id as mods_id } from "../../../../utility/mods"; -import form from "../../form/beatmap/category"; +import { request } from "../../../../utility/request"; +import { calculate_mods } from "../../../../tools/index"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/'); +import form from "../../form/beatmap/category"; +import { IError } from "../../../../types"; const _mode = [ 'osu', @@ -71,7 +71,7 @@ export interface types { limit?: number, mods?: string | number, since?: string, - }): Promise; + }): Promise; }; export interface response { @@ -188,16 +188,18 @@ const name: types = async (id, obj = {}) => { a: obj.converted, h: obj.hash, since: obj.since, - mods: mods_id(obj.mods), + mods: calculate_mods(obj.mods).number, limit: obj.limit, }; + if (params.m == -1) delete params.m; + - const data = await request(`get_beatmaps`, { + const data = await request(`https://osu.ppy.sh/api/get_beatmaps`, { method: 'GET', params: params, }); - if (data.length == 0) return null; + if (data.length == 0) return { error: new Error('Beatmap not found') }; const format = form(data); return format; diff --git a/api/v1/routes/beatmap/scores.ts b/api/v1/routes/beatmap/scores.ts index 6b016111..f28b0f92 100644 --- a/api/v1/routes/beatmap/scores.ts +++ b/api/v1/routes/beatmap/scores.ts @@ -1,8 +1,7 @@ -import { namespace, RequestNamespace } from "../../../../utility/request"; -import { id as mods_id } from "../../../../utility/mods"; -import form from "../../form/beatmap/scores"; +import { request } from "../../../../utility/request"; +import { calculate_mods } from "../../../../tools/index"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/'); +import form from "../../form/beatmap/scores"; const _mode = [ 'osu', @@ -104,17 +103,18 @@ const name: types = async (id, obj = {}) => { b: id, u: obj.user, m: _mode.indexOf(obj.mode), - mods: mods_id(obj.mods), + mods: calculate_mods(obj.mods).number, type: obj.type, limit: obj.limit, }; + if (params.m == -1) delete params.m; - const data = await request(`get_scores`, { + const data = await request(`https://osu.ppy.sh/api/get_scores`, { method: 'GET', params: params, }); - if (data.length == 0) return null; + if (data.length == 0) return []; const format = form(data, obj.mode); return format; diff --git a/api/v1/routes/beatmap/set.ts b/api/v1/routes/beatmap/set.ts index 21205245..ede6a4e5 100644 --- a/api/v1/routes/beatmap/set.ts +++ b/api/v1/routes/beatmap/set.ts @@ -1,8 +1,7 @@ -import { namespace, RequestNamespace } from "../../../../utility/request"; -import { id as mods_id } from "../../../../utility/mods"; -import form from "../../form/beatmap/category"; +import { request } from "../../../../utility/request"; +import { calculate_mods } from "../../../../tools/index"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/'); +import form from "../../form/beatmap/category"; const _mode = [ 'osu', @@ -188,16 +187,17 @@ const name: types = async (id, obj = {}) => { a: obj.converted, h: obj.hash, since: obj.since, - mods: mods_id(obj.mods), + mods: calculate_mods(obj.mods).number, limit: obj.limit, }; + if (params.m == -1) delete params.m; - const data = await request(`get_beatmaps`, { + const data = await request(`https://osu.ppy.sh/api/get_beatmaps`, { method: 'GET', params: params, }); - if (data.length == 0) return null; + if (data.length == 0) return []; const format = form(data); return format; diff --git a/api/v1/routes/match.ts b/api/v1/routes/match.ts index 1700deaf..8d11b3ee 100644 --- a/api/v1/routes/match.ts +++ b/api/v1/routes/match.ts @@ -1,8 +1,7 @@ -import { namespace, RequestNamespace } from "../../../utility/request"; -import { id as mods_id } from "../../../utility/mods"; +import { IError } from "../../../types"; +import { request } from "../../../utility/request"; import form from "../form/match"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/'); export const description: any = { @@ -20,8 +19,10 @@ export const description: any = { ], }; +type Response = response & IError; + export interface types { - (id: number): Promise; + (id: number): Promise; }; export interface response { @@ -89,15 +90,17 @@ export interface response { const name: types = async (id) => { const params = { mp: id }; - const data = await request(`get_match`, { + const data = await request(`https://osu.ppy.sh/api/get_match`, { method: 'GET', params: params, }); - if (data.match == 0 || !data.match) return null; + if (data.match == 0 || !data.match) { + return { error: new Error('Match not found') } as Response; + } - const format = form(data); - return format; + const format: response = form(data); + return format as Response; }; diff --git a/api/v1/routes/replay.ts b/api/v1/routes/replay.ts deleted file mode 100644 index 06686f88..00000000 --- a/api/v1/routes/replay.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { namespace, RequestNamespace } from "../../../utility/request"; -// import { id as mods_id } from "../../../../utility/mods"; -// import path from "path"; -import fs from "fs"; - -import scores from "./beatmap/scores"; -import diff from "./beatmap/diff"; - -import form from "../form/replays"; - -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/'); - -const _mode = [ - 'osu', - 'taiko', - 'fruits', - 'mania', -]; - - -export const description: any = { - auth: 2, - title: __filename, - method: 'GET', - description: 'Download replay file for specified score', - params: [ - { - type: 'number', - name: 'id', - optional: true, - description: 'id of the beatmap', - }, - { - type: 'number', - name: 'user', - optional: true, - description: 'id of the user', - }, - { - type: 'string', - name: 'mode', - optional: true, - description: '\`\`\`osu\`\`\` or \`\`\`fruits\`\`\` or \`\`\`mania\`\`\` or \`\`\`taiko\`\`\`', - }, - { - type: 'number', - name: 'score_id', - optional: true, - description: 'id of the score', - }, - { - type: 'string/number', - name: 'mods', - optional: true, - description: 'Name of the mods \`\`\`HDDT\`\`\` or mods number \`\`\`72\`\`\`', - }, - { - type: 'string', - name: 'type', - optional: true, - description: '\`\`\`u\`\`\` is a user_id or a username. Use string for usernames or \`\`\`id\`\`\` for user_ids', - }, - { - type: 'string', - name: 'dest', - optional: false, - description: 'Path to the folder', - }, - { - type: 'string', - name: 'file', - optional: false, - description: 'File name (without extension)', - }, - ], -}; - -export interface types { - (obj: { - id?: number, - user?: string | number, - mode?: 'osu' | 'fruits' | 'mania' | 'taiko', - score_id?: number, - mods?: string | number, - type?: 'u' | 'id', - }, dest: string, file: string): Promise; -}; - -export interface response { } - - -const name: types = async (obj = {}, dest, file) => { - let _file = ''; - - if (dest) _file = `${dest}${dest.endsWith('/') ? '' : '/'}${file ? `${file}.osr` : 'replay.osr'}`; - else _file = file ? `${file}.osr` : 'replay.osr'; - - if (fs.existsSync(_file)) throw new Error(`Replay ${_file} already exists`); - - const params = { - b: obj.id, - u: obj.user, - m: _mode.indexOf(obj.mode), - s: obj.score_id, - type: obj.type, - mods: obj.mods, - }; - - const data = await request(`get_replay`, { - method: 'GET', - params: params, - }); - - const score = await scores(obj.id, { - user: obj.user, - mode: obj.mode, - mods: obj.mods, - type: obj.type, - }); - - if (!score) throw new Error(`Score not founded. Check your params: ${JSON.stringify(obj)}`); - - const map = await diff(obj.id); - if (!map) throw new Error(`Beatmap not founded. Check your beatmap id: ${obj.id}`); - - const format = form(data, map, score, obj.id, obj.mods, _file); - return format; -}; - - -export default name; \ No newline at end of file diff --git a/api/v1/routes/user/details.ts b/api/v1/routes/user/details.ts index 2b13f2b1..662b2c5e 100644 --- a/api/v1/routes/user/details.ts +++ b/api/v1/routes/user/details.ts @@ -1,8 +1,7 @@ -import { namespace, RequestNamespace } from "../../../../utility/request"; -import { id as mods_id } from "../../../../utility/mods"; +import { IError } from "../../../../types"; +import { request } from "../../../../utility/request"; import form from "../../form/user/details"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/'); const _mode = [ 'osu', @@ -45,12 +44,14 @@ export const description: any = { ], }; +type Response = response[] & IError; + export interface types { (user: string | number, obj?: { mode?: 'osu' | 'fruits' | 'mania' | 'taiko', type?: 'u' | 'id', event_days?: number - }): Promise; + }): Promise; }; export interface response { @@ -100,7 +101,7 @@ export interface response { }; date: string; epicfactor: number; - }[]; + }; } @@ -112,13 +113,15 @@ const name: types = async (user, obj = {}) => { type: obj.type, event_days: obj.event_days, }; + if (params.m == -1) delete params.m; + - const data = await request(`get_user`, { + const data = await request(`https://osu.ppy.sh/api/get_user`, { method: 'GET', params: params, }); - if (data.length == 0) return null; + if (data.length == 0) return { error: new Error('User not found') }; const format = form(data); return format; diff --git a/api/v1/routes/user/scores-category.ts b/api/v1/routes/user/scores-category.ts index cb4a9a9e..ca1db2b6 100644 --- a/api/v1/routes/user/scores-category.ts +++ b/api/v1/routes/user/scores-category.ts @@ -1,9 +1,7 @@ -import { namespace, RequestNamespace } from "../../../../utility/request"; -import { id as mods_id } from "../../../../utility/mods"; +import { request } from "../../../../utility/request"; import form_best from "../../form/user/best"; import form_recent from "../../form/user/recent"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/'); const _mode = [ 'osu', @@ -46,12 +44,14 @@ export const description: any = { ], }; +type Reponse = response[]; + export interface types { (user: string | number, type: 'best' | 'recent', obj?: { mode?: 'osu' | 'fruits' | 'mania' | 'taiko', type?: 'u' | 'id', limit?: number, - }): Promise; + }): Promise; }; export interface response { @@ -88,13 +88,14 @@ const name: types = async (user, type, obj = {}) => { type: obj.type, limit: obj.limit, }; + if (params.m == -1) delete params.m; - const data = await request(`get_user_${type}`, { + const data = await request(`https://osu.ppy.sh/api/get_user_${type}`, { method: 'GET', params: params, }); - if (data.length == 0) return null; + if (data.length == 0) return []; if (type == 'best') { const format = form_best(data, obj.mode); diff --git a/index.ts b/index.ts index 1bf8475e..029bb184 100644 --- a/index.ts +++ b/index.ts @@ -1,7 +1,11 @@ export * as auth from './utility/auth'; export * as v2 from "./routes/v2"; +export * as v1 from "./routes/v1"; export * as tools from './tools/index'; export * as enums from './types/enums'; + + +export { request, download } from './utility/request'; \ No newline at end of file diff --git a/api/v1/index.ts b/routes/v1.ts similarity index 68% rename from api/v1/index.ts rename to routes/v1.ts index 35a8a5ac..0db0e96b 100644 --- a/api/v1/index.ts +++ b/routes/v1.ts @@ -1,7 +1,7 @@ -import beatmap_set, { types as beatmap_set_type, description as beatmap_set_desc } from "./routes/beatmap/set"; -import beatmap_diff, { types as beatmap_diff_type, description as beatmap_diff_desc } from "./routes/beatmap/diff"; -import beatmap_creator, { types as beatmap_creator_type, description as beatmap_creator_desc } from "./routes/beatmap/creator"; -import beatmap_scores, { types as beatmap_scores_type, description as beatmap_scores_desc } from "./routes/beatmap/scores"; +import beatmap_set, { types as beatmap_set_type, description as beatmap_set_desc } from "../api/v1/routes/beatmap/set"; +import beatmap_diff, { types as beatmap_diff_type, description as beatmap_diff_desc } from "../api/v1/routes/beatmap/diff"; +import beatmap_creator, { types as beatmap_creator_type, description as beatmap_creator_desc } from "../api/v1/routes/beatmap/creator"; +import beatmap_scores, { types as beatmap_scores_type, description as beatmap_scores_desc } from "../api/v1/routes/beatmap/scores"; export const beatmap: { set: beatmap_set_type, @@ -16,8 +16,8 @@ export const beatmap: { }; -import user_details, { types as user_details_type, description as user_details_desc } from "./routes/user/details"; -import user_scores_category, { types as user_scores_category_type, description as user_scores_category_desc } from "./routes/user/scores-category"; +import user_details, { types as user_details_type, description as user_details_desc } from "../api/v1/routes/user/details"; +import user_scores_category, { types as user_scores_category_type, description as user_scores_category_desc } from "../api/v1/routes/user/scores-category"; export const user: { details: user_details_type, @@ -32,12 +32,16 @@ export const user: { }; -import match_details, { types as match_details_type, description as match_details_desc } from "./routes/match"; +import match_details, { types as match_details_type, description as match_details_desc } from "../api/v1/routes/match"; export const match: match_details_type = match_details; -import replay_download, { types as replay_download_type, description as replay_download_desc } from "./routes/replay"; -export const replay: replay_download_type = replay_download; +/** + * @deprecated + */ +export const replay = () => { + return 'USE API V2' +}; export const desc: { @@ -48,7 +52,6 @@ export const desc: { user_details: object, user_scores_category: object, match: object, - replay: object, } = { beatmap_set: beatmap_set_desc, beatmap_diff: beatmap_diff_desc, @@ -57,5 +60,4 @@ export const desc: { user_details: user_details_desc, user_scores_category: user_scores_category_desc, match: match_details_desc, - replay: replay_download_desc, }; \ No newline at end of file diff --git a/utility/auth.ts b/utility/auth.ts index 1cfa7d07..e3ad054c 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -54,7 +54,7 @@ export const cache = { -export const login = async (params: auth_params) => { +export const login = (params: auth_params) => { credentials.method = params.method; @@ -71,8 +71,7 @@ export const login = async (params: auth_params) => { credentials.client_secret = params.client_secret; if (params.scopes) credentials.scopes = params.scopes; - const authorize = await client_login(params.client_id, params.client_secret, params.scopes || ['public']); - return authorize; + return client_login(params.client_id, params.client_secret, params.scopes || ['public']); }; @@ -80,8 +79,7 @@ export const login = async (params: auth_params) => { credentials.login = params.login; credentials.password = params.password; - const authorize = await lazer_login(params.login, params.password); - return authorize; + return lazer_login(params.login, params.password); }; @@ -93,8 +91,7 @@ export const login = async (params: auth_params) => { credentials.redirect_url = params.redirect_url; credentials.state = params.state; - const authorize = await authorize_cli(params.client_id, params.client_secret, params.redirect_url, params.scopes || ['public'], params.state); - return authorize; + return authorize_cli(params.client_id, params.client_secret, params.redirect_url, params.scopes || ['public'], params.state); }; From 3407c7001b5158bda10656bce0f7c13d5c936c92 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 27 Apr 2024 17:24:18 +0300 Subject: [PATCH 140/259] throw errors, or just return new Error --- api/v1/routes/beatmap/creator.ts | 4 ++ api/v1/routes/beatmap/diff.ts | 4 +- api/v1/routes/beatmap/scores.ts | 4 ++ api/v1/routes/beatmap/set.ts | 4 ++ api/v1/routes/match.ts | 7 ++- api/v1/routes/user/details.ts | 4 +- api/v1/routes/user/scores-category.ts | 4 ++ api/v2/assets_backgrounds.ts | 5 +- api/v2/assets_dataFiles.ts | 3 +- api/v2/beatmaps_actions.ts | 5 +- api/v2/beatmaps_details.ts | 7 ++- api/v2/beatmaps_discussions_list.ts | 4 ++ api/v2/beatmaps_discussions_posts.ts | 3 ++ api/v2/beatmaps_discussions_votes.ts | 3 ++ api/v2/beatmaps_download.ts | 11 +++-- api/v2/beatmaps_events_list.ts | 3 ++ api/v2/beatmaps_lookup.ts | 13 +++-- api/v2/beatmaps_packs_details.ts | 4 +- api/v2/beatmaps_packs_list.ts | 2 + api/v2/changelogs_details.ts | 6 ++- api/v2/changelogs_list.ts | 7 ++- api/v2/chat_actions.ts | 7 ++- api/v2/chat_channels_actions.ts | 13 +++-- api/v2/chat_channels_list.ts | 2 + api/v2/chat_details.ts | 4 +- api/v2/chat_list.ts | 3 ++ api/v2/chat_messages.ts | 4 +- api/v2/chat_updates.ts | 2 + api/v2/comments_actions.ts | 21 ++++---- api/v2/comments_details.ts | 5 +- api/v2/comments_list.ts | 2 + api/v2/forums_topics_actions.ts | 30 +++++++----- api/v2/forums_topics_details.ts | 5 +- api/v2/matches_details.ts | 5 +- api/v2/matches_list.ts | 3 ++ api/v2/me_details.ts | 5 +- api/v2/me_download_quota.ts | 4 +- api/v2/me_friends.ts | 4 +- api/v2/news_details.ts | 4 +- api/v2/news_list.ts | 3 ++ api/v2/notification_actions.ts | 7 ++- api/v2/notifications_list.ts | 3 ++ api/v2/ranking_list.ts | 12 ++--- api/v2/rooms_details.ts | 5 +- api/v2/rooms_leaderboard.ts | 5 +- api/v2/rooms_list.ts | 3 ++ api/v2/rooms_scores.ts | 9 ++-- api/v2/scores_details.ts | 5 +- api/v2/scores_download.ts | 5 +- api/v2/scores_list.ts | 22 ++++----- api/v2/search.ts | 3 ++ api/v2/session_actions.ts | 3 ++ api/v2/spotlights_list.ts | 3 ++ api/v2/users_activity.ts | 5 +- api/v2/users_beatmaps.ts | 7 ++- api/v2/users_details.ts | 4 +- api/v2/users_events.ts | 5 +- api/v2/users_kudosu.ts | 5 +- api/v2/users_list.ts | 5 +- api/v2/wiki_details.ts | 7 ++- tools/accuracy.ts | 5 +- tools/country.ts | 7 +-- tools/index.ts | 4 +- tools/mods.ts | 5 +- tools/objects.ts | 5 +- tools/rank.ts | 5 +- types/index.ts | 8 +++- utility/auth.ts | 69 +++++++++++++++++++-------- utility/handleErrors.ts | 11 +++++ utility/request.ts | 34 ++++++------- 70 files changed, 358 insertions(+), 151 deletions(-) create mode 100644 utility/handleErrors.ts diff --git a/api/v1/routes/beatmap/creator.ts b/api/v1/routes/beatmap/creator.ts index fae3c9d0..ff899974 100644 --- a/api/v1/routes/beatmap/creator.ts +++ b/api/v1/routes/beatmap/creator.ts @@ -2,6 +2,7 @@ import { request } from "../../../../utility/request"; import { calculate_mods } from "../../../../tools/index"; import form from "../../form/beatmap/creator"; +import { handleErrors } from "../../../../utility/handleErrors"; const _mode = [ @@ -199,6 +200,9 @@ const name: types = async (user_id, obj = {}) => { params: params, }); + if (data.error) return handleErrors(data.error); + + if (data.length == 0) return []; const format = form(data); diff --git a/api/v1/routes/beatmap/diff.ts b/api/v1/routes/beatmap/diff.ts index 7d69b753..4a99243e 100644 --- a/api/v1/routes/beatmap/diff.ts +++ b/api/v1/routes/beatmap/diff.ts @@ -3,6 +3,7 @@ import { calculate_mods } from "../../../../tools/index"; import form from "../../form/beatmap/category"; import { IError } from "../../../../types"; +import { handleErrors } from "../../../../utility/handleErrors"; const _mode = [ 'osu', @@ -198,8 +199,9 @@ const name: types = async (id, obj = {}) => { method: 'GET', params: params, }); + if (data.error) return handleErrors(data.error) as Response; - if (data.length == 0) return { error: new Error('Beatmap not found') }; + if (data.length == 0) return handleErrors('Beatmap not found') as Response; const format = form(data); return format; diff --git a/api/v1/routes/beatmap/scores.ts b/api/v1/routes/beatmap/scores.ts index f28b0f92..875268e3 100644 --- a/api/v1/routes/beatmap/scores.ts +++ b/api/v1/routes/beatmap/scores.ts @@ -2,6 +2,7 @@ import { request } from "../../../../utility/request"; import { calculate_mods } from "../../../../tools/index"; import form from "../../form/beatmap/scores"; +import { handleErrors } from "../../../../utility/handleErrors"; const _mode = [ 'osu', @@ -114,6 +115,9 @@ const name: types = async (id, obj = {}) => { params: params, }); + if (data.error) return handleErrors(data.error); + + if (data.length == 0) return []; const format = form(data, obj.mode); diff --git a/api/v1/routes/beatmap/set.ts b/api/v1/routes/beatmap/set.ts index ede6a4e5..0552b9d8 100644 --- a/api/v1/routes/beatmap/set.ts +++ b/api/v1/routes/beatmap/set.ts @@ -2,6 +2,7 @@ import { request } from "../../../../utility/request"; import { calculate_mods } from "../../../../tools/index"; import form from "../../form/beatmap/category"; +import { handleErrors } from "../../../../utility/handleErrors"; const _mode = [ 'osu', @@ -197,6 +198,9 @@ const name: types = async (id, obj = {}) => { params: params, }); + if (data.error) return handleErrors(data.error); + + if (data.length == 0) return []; const format = form(data); diff --git a/api/v1/routes/match.ts b/api/v1/routes/match.ts index 8d11b3ee..abc19cb1 100644 --- a/api/v1/routes/match.ts +++ b/api/v1/routes/match.ts @@ -1,4 +1,5 @@ import { IError } from "../../../types"; +import { handleErrors } from "../../../utility/handleErrors"; import { request } from "../../../utility/request"; import form from "../form/match"; @@ -94,10 +95,12 @@ const name: types = async (id) => { method: 'GET', params: params, }); + if (data.error) return handleErrors(data.error) as Response; + if (data.match == 0 || !data.match) { - return { error: new Error('Match not found') } as Response; - } + return handleErrors('Match not found') as Response; + }; const format: response = form(data); return format as Response; diff --git a/api/v1/routes/user/details.ts b/api/v1/routes/user/details.ts index 662b2c5e..e876ea56 100644 --- a/api/v1/routes/user/details.ts +++ b/api/v1/routes/user/details.ts @@ -1,4 +1,5 @@ import { IError } from "../../../../types"; +import { handleErrors } from "../../../../utility/handleErrors"; import { request } from "../../../../utility/request"; import form from "../../form/user/details"; @@ -120,8 +121,9 @@ const name: types = async (user, obj = {}) => { method: 'GET', params: params, }); + if (data.error) return handleErrors(data.error) as Response; - if (data.length == 0) return { error: new Error('User not found') }; + if (data.length == 0) return handleErrors('User not found') as Response; const format = form(data); return format; diff --git a/api/v1/routes/user/scores-category.ts b/api/v1/routes/user/scores-category.ts index ca1db2b6..5c77d145 100644 --- a/api/v1/routes/user/scores-category.ts +++ b/api/v1/routes/user/scores-category.ts @@ -1,3 +1,4 @@ +import { handleErrors } from "../../../../utility/handleErrors"; import { request } from "../../../../utility/request"; import form_best from "../../form/user/best"; import form_recent from "../../form/user/recent"; @@ -95,6 +96,9 @@ const name: types = async (user, type, obj = {}) => { params: params, }); + if (data.error) return handleErrors(data.error); + + if (data.length == 0) return []; if (type == 'best') { diff --git a/api/v2/assets_backgrounds.ts b/api/v2/assets_backgrounds.ts index c7b5e8a9..4d8a6f57 100644 --- a/api/v2/assets_backgrounds.ts +++ b/api/v2/assets_backgrounds.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { BeatmapsetBackground, SeasonalBackgrounds } from "../../types/v2/assets_backgrounds"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -29,7 +30,7 @@ export const assets_backgrounds = (params: T, addons?: IDefaul if (params.type == 'beatmapset') { if (params.set_id == null) { - return { error: new Error('Specify beatmapset id') } as any; + return handleErrors('Specify beatmapset id') as Response; }; @@ -48,5 +49,5 @@ export const assets_backgrounds = (params: T, addons?: IDefaul }; - return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; + return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; }; \ No newline at end of file diff --git a/api/v2/assets_dataFiles.ts b/api/v2/assets_dataFiles.ts index 6a4a8b68..7177fff4 100644 --- a/api/v2/assets_dataFiles.ts +++ b/api/v2/assets_dataFiles.ts @@ -1,5 +1,6 @@ import { IError } from "../../types"; import { AssetsDatafilesResponse } from "../../types/v2/assets_datafiles"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -11,7 +12,7 @@ export const assets_dataFiles = async (): Promise => { method: 'GET', }); - if (data.error) return data.error; + if (data.error) return handleErrors(data.error) as Response; const array = data.split('\n') diff --git a/api/v2/beatmaps_actions.ts b/api/v2/beatmaps_actions.ts index 9ea1a0dc..a7e24bc6 100644 --- a/api/v2/beatmaps_actions.ts +++ b/api/v2/beatmaps_actions.ts @@ -1,5 +1,6 @@ -import { request } from "../../utility/request"; +// import { request } from "../../utility/request"; import { IDefaultParams, IError } from "../../types"; +import { handleErrors } from "../../utility/handleErrors"; // import { postDataObject } from "../../tools"; @@ -20,7 +21,7 @@ type Response = // FIX const name = async (params: T, addons?: IDefaultParams): Promise> => { - return { error: new Error('TEMPORARY NOT WORKING, have no clue why') } as Response; + return handleErrors('TEMPORARY NOT WORKING, have no clue why') as Response; // if (params.type == null) // return { // error: 'Type not specified', diff --git a/api/v2/beatmaps_details.ts b/api/v2/beatmaps_details.ts index ed4e809b..f519a858 100644 --- a/api/v2/beatmaps_details.ts +++ b/api/v2/beatmaps_details.ts @@ -1,6 +1,7 @@ import { IDefaultParams, IError } from "../../types"; import { BeamapsDetailsDifficulty } from "../../types/v2/beamaps_details_difficulty"; import { BeamapsDetailsSet } from "../../types/v2/beamaps_details_set"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -23,7 +24,7 @@ type Response = export const beatmaps_details = async (params: T, addons?: IDefaultParams): Promise> => { if (params.id == null) { - return { error: new Error(`Specify ${params.type} id`) } as Response; + return handleErrors(`Specify ${params.type} id`) as Response; }; @@ -42,7 +43,7 @@ export const beatmaps_details = async (params: T, addons?: IDe break; default: - return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; + return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; }; @@ -51,6 +52,8 @@ export const beatmaps_details = async (params: T, addons?: IDe params: object, addons }); + + if (data.error) return handleErrors(data.error) as Response; return data as Response; diff --git a/api/v2/beatmaps_discussions_list.ts b/api/v2/beatmaps_discussions_list.ts index d22cbdcb..c7c40ed3 100644 --- a/api/v2/beatmaps_discussions_list.ts +++ b/api/v2/beatmaps_discussions_list.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { BeatmapsDiscussionsListResponse } from "../../types/v2/beatmaps_discussions_list"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -21,5 +22,8 @@ export const beatmaps_discussions_list = async (params: { addons }); + if (data.error) return handleErrors(data.error); + + return data; }; \ No newline at end of file diff --git a/api/v2/beatmaps_discussions_posts.ts b/api/v2/beatmaps_discussions_posts.ts index 0cc47170..3f90def9 100644 --- a/api/v2/beatmaps_discussions_posts.ts +++ b/api/v2/beatmaps_discussions_posts.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { BeatmapsDiscussionsListResponse } from "../../types/v2/beatmaps_discussions_list"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -32,5 +33,7 @@ export const beatmaps_discussions_posts = async (params: { addons }); + if (data.error) return handleErrors(data.error); + return data; }; \ No newline at end of file diff --git a/api/v2/beatmaps_discussions_votes.ts b/api/v2/beatmaps_discussions_votes.ts index 6c6780c2..465da32a 100644 --- a/api/v2/beatmaps_discussions_votes.ts +++ b/api/v2/beatmaps_discussions_votes.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { BeatmapsDiscussionsListResponse } from "../../types/v2/beatmaps_discussions_list"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -28,5 +29,7 @@ export const beatmaps_discussions_votes = async (params: { addons }); + if (data.error) return handleErrors(data.error); + return data; }; \ No newline at end of file diff --git a/api/v2/beatmaps_download.ts b/api/v2/beatmaps_download.ts index 3079b20f..eb051ade 100644 --- a/api/v2/beatmaps_download.ts +++ b/api/v2/beatmaps_download.ts @@ -3,6 +3,7 @@ import { download } from "../../utility/request"; import { cache } from "../../utility/auth"; import path from "path"; import fs from "fs"; +import { handleErrors } from "../../utility/handleErrors"; @@ -109,7 +110,7 @@ export const beatmaps_download = async (params: T, addons?: ID case 'osu': if ((addons.authKey || cache.v2) == null) { - return { error: new Error('osu is not authorized') } as Response; + return handleErrors('osu is not authorized') as Response; }; @@ -118,7 +119,7 @@ export const beatmaps_download = async (params: T, addons?: ID break; default: - return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; + return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; }; @@ -129,6 +130,8 @@ export const beatmaps_download = async (params: T, addons?: ID callback: progress_track, }); + if (data.error) return handleErrors(data.error); + return data; }; @@ -158,10 +161,12 @@ export const beatmaps_download = async (params: T, addons?: ID callback: progress_track, }); + if (data.error) return handleErrors(data.error); + return data; }; - return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; + return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; }; \ No newline at end of file diff --git a/api/v2/beatmaps_events_list.ts b/api/v2/beatmaps_events_list.ts index 40357b69..58239b14 100644 --- a/api/v2/beatmaps_events_list.ts +++ b/api/v2/beatmaps_events_list.ts @@ -1,6 +1,7 @@ import { BeatmapsEvents } from "../../types/v2/beatmaps_events"; import { IDefaultParams, IError, beatmap_events_types } from "../../types"; import { request } from "../../utility/request"; +import { handleErrors } from "../../utility/handleErrors"; @@ -19,5 +20,7 @@ export const beatmaps_events_list = async (obj: { addons }); + if (data.error) return handleErrors(data.error); + return data; }; \ No newline at end of file diff --git a/api/v2/beatmaps_lookup.ts b/api/v2/beatmaps_lookup.ts index 32d2a9c2..d23c7c7f 100644 --- a/api/v2/beatmaps_lookup.ts +++ b/api/v2/beatmaps_lookup.ts @@ -5,6 +5,7 @@ import { GamemodeEnum } from "../../types/enums"; import { request } from "../../utility/request"; import { IDefaultParams, IError, Modes_names } from "../../types"; import { BeatmapsLookupDifficultiesResponse } from "../../types/v2/beatmaps_lookup_difficulties"; +import { handleErrors } from "../../utility/handleErrors"; type params = ({ @@ -49,7 +50,7 @@ export const beatmaps_lookup = async (params: T, addons?: IDef url += '/beatmaps/lookup'; if (params.id == null && params.checksum && params.filename) { - return { error: new Error(`Specify at least one parameter`) } as Response; + return handleErrors(`Specify at least one parameter`) as Response; }; object.id = params.id; @@ -62,7 +63,7 @@ export const beatmaps_lookup = async (params: T, addons?: IDef url += '/beatmapsets/lookup'; if (params.id == null) { - return { error: new Error(`Specify beatmap set id`) } as Response; + return handleErrors(`Specify beatmap set id`) as Response; }; object.beatmap_id = params.id; @@ -74,7 +75,7 @@ export const beatmaps_lookup = async (params: T, addons?: IDef method = 'POST'; if (params.id == null) { - return { error: new Error(`Specify beatmap id`) } as Response; + return handleErrors(`Specify beatmap id`) as Response; }; object.mods = params.mods; @@ -89,13 +90,13 @@ export const beatmaps_lookup = async (params: T, addons?: IDef if (Array.isArray(params.ids)) object['ids[]'] = params.ids; else { - return { error: new Error(`Specify at least one beatmap id`) } as Response; + return handleErrors(`Specify at least one beatmap id`) as Response; }; break; default: - return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; + return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; }; @@ -105,6 +106,8 @@ export const beatmaps_lookup = async (params: T, addons?: IDef addons, }); + if (data.error) return handleErrors(data.error) as Response; + if (params.type == 'attributes') return data.attributes as Response; if (params.type == 'difficulties') return data.beatmaps as Response; diff --git a/api/v2/beatmaps_packs_details.ts b/api/v2/beatmaps_packs_details.ts index 5e358d6b..36f6793e 100644 --- a/api/v2/beatmaps_packs_details.ts +++ b/api/v2/beatmaps_packs_details.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { BeatmapsPacksDetailsResponse } from "../../types/v2/beatmaps_packs_details"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -8,7 +9,7 @@ type Response = BeatmapsPacksDetailsResponse & IError; export const beatmap_packs_details = async (pack_tag: string, addons?: IDefaultParams): Promise => { if (pack_tag == null) { - return { error: new Error('Specify beatmap pack tag') } as Response; + return handleErrors('Specify beatmap pack tag') as Response; }; @@ -17,6 +18,7 @@ export const beatmap_packs_details = async (pack_tag: string, addons?: IDefaultP addons, }); + if (data.error) return handleErrors(data.error); return data; }; \ No newline at end of file diff --git a/api/v2/beatmaps_packs_list.ts b/api/v2/beatmaps_packs_list.ts index 064802cb..326f5705 100644 --- a/api/v2/beatmaps_packs_list.ts +++ b/api/v2/beatmaps_packs_list.ts @@ -1,5 +1,6 @@ import { IBeatmapPackType, IDefaultParams, IError } from "../../types"; import { BeatmapsPacksListResponse } from "../../types/v2/beatmaps_packs_list"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -16,6 +17,7 @@ export const beatmaps_packs_list = async (params: { addons, }); + if (data.error) return handleErrors(data.error); return data; }; \ No newline at end of file diff --git a/api/v2/changelogs_details.ts b/api/v2/changelogs_details.ts index 4ea60489..5242540b 100644 --- a/api/v2/changelogs_details.ts +++ b/api/v2/changelogs_details.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { changelogsDetailsResponse } from "../../types/v2/changelogs_details"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -11,11 +12,11 @@ export const changelogs_details = async (params: { build_version: string; }, addons?: IDefaultParams): Promise => { if (params.stream_name == null) { - return { error: new Error(`Specify stream name`) } as Response; + return handleErrors(`Specify stream name`) as Response; }; if (params.build_version == null) { - return { error: new Error(`Specify build version`) } as Response; + return handleErrors(`Specify build version`) as Response; }; @@ -24,6 +25,7 @@ export const changelogs_details = async (params: { addons, }); + if (data.error) return handleErrors(data.error); return data; }; \ No newline at end of file diff --git a/api/v2/changelogs_list.ts b/api/v2/changelogs_list.ts index 6022ef7f..fe6e2a8b 100644 --- a/api/v2/changelogs_list.ts +++ b/api/v2/changelogs_list.ts @@ -1,6 +1,7 @@ import { IDefaultParams, IError } from "../../types"; import { ChangelogsListAllResponse } from "../../types/v2/changelogs_list_all"; import { ChangelogsListLookupResponse } from "../../types/v2/changelogs_list_lookup"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -52,7 +53,7 @@ export const changelogs_list = async (params: T, addons?: IDef url += `/changelog/${params.changelog}`; if (params.changelog == null) { - return { error: new Error(`Specify changelog stream`) } as Response; + return handleErrors(`Specify changelog stream`) as Response; }; @@ -61,7 +62,7 @@ export const changelogs_list = async (params: T, addons?: IDef break; default: - return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; + return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; }; @@ -71,6 +72,8 @@ export const changelogs_list = async (params: T, addons?: IDef addons }); + if (data.error) return handleErrors(data.error) as Response; + return data as Response; }; \ No newline at end of file diff --git a/api/v2/chat_actions.ts b/api/v2/chat_actions.ts index 1042edf3..867daaa2 100644 --- a/api/v2/chat_actions.ts +++ b/api/v2/chat_actions.ts @@ -2,6 +2,7 @@ import { request } from "../../utility/request"; import { IDefaultParams, IError } from "../../types"; import { ChatActionsNewResponse } from "../../types/v2/chat_actions_new"; import { ChatActionsKeepaliveResponse } from "../../types/v2/chat_actions_keepalive"; +import { handleErrors } from "../../utility/handleErrors"; type params = ({ @@ -41,7 +42,7 @@ export const chat_actions = async (params: T, addons?: IDefaul method = 'POST'; if (params.is_action == null || params.user_id == null || params.message == null) { - return { error: new Error('Missing required parameters') } as Response; + return handleErrors('Missing required parameters') as Response; }; @@ -60,7 +61,7 @@ export const chat_actions = async (params: T, addons?: IDefaul break; default: - return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; + return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; }; @@ -70,6 +71,8 @@ export const chat_actions = async (params: T, addons?: IDefaul addons, }); + if (data.error) return handleErrors(data.error) as Response; + if (params.type == 'keepalive') return data.silences as Response; return data as Response; diff --git a/api/v2/chat_channels_actions.ts b/api/v2/chat_channels_actions.ts index 927aebcc..71b8c808 100644 --- a/api/v2/chat_channels_actions.ts +++ b/api/v2/chat_channels_actions.ts @@ -2,6 +2,7 @@ import { request } from "../../utility/request"; import { IDefaultParams, IError } from "../../types"; import { chatChannelsActionsSendResponse } from "../../types/v2/chat_channels_actions_send"; import { chatChannelsActionsJoinResponse } from "../../types/v2/chat_channels_actions_join"; +import { handleErrors } from "../../utility/handleErrors"; type params = ({ @@ -45,7 +46,7 @@ export const chat_channels_actions = async (params: T, addons? switch (params.type) { case 'send': if (params.id == null || params.message == null || params.is_action == null) { - return { error: new Error(`Missing required parameters`) } as Response; + return handleErrors(`Missing required parameters`) as Response; }; @@ -57,7 +58,7 @@ export const chat_channels_actions = async (params: T, addons? case 'join': if (params.id == null || params.user_id == null) { - return { error: new Error(`Missing required parameters`) } as Response; + return handleErrors(`Missing required parameters`) as Response; }; @@ -67,7 +68,7 @@ export const chat_channels_actions = async (params: T, addons? case 'leave': if (params.id == null || params.user_id == null) { - return { error: new Error(`Missing required parameters`) } as Response; + return handleErrors(`Missing required parameters`) as Response; }; @@ -77,7 +78,7 @@ export const chat_channels_actions = async (params: T, addons? case 'readed': if (params.channel_id == null || params.message_id == null) { - return { error: new Error(`Missing required parameters`) } as Response; + return handleErrors(`Missing required parameters`) as Response; }; @@ -86,7 +87,7 @@ export const chat_channels_actions = async (params: T, addons? break; default: - return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; + return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; }; @@ -96,6 +97,8 @@ export const chat_channels_actions = async (params: T, addons? addons, }); + if (data.error) return handleErrors(data.error) as Response; + return data as Response; }; \ No newline at end of file diff --git a/api/v2/chat_channels_list.ts b/api/v2/chat_channels_list.ts index ffa2cf97..871ef93a 100644 --- a/api/v2/chat_channels_list.ts +++ b/api/v2/chat_channels_list.ts @@ -1,5 +1,6 @@ import { IError } from "../../types"; import { chatChannelsListResponse } from "../../types/v2/chat_channels_list"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -9,6 +10,7 @@ export const chat_channels_list = async (): Promise => { if (channel_id == null) { - return { error: new Error(`Specify channel id`) } as Response; + return handleErrors(`Specify channel id`) as Response; }; @@ -17,6 +18,7 @@ export const chat_details = async (channel_id: number, addons?: IDefaultParams): addons, }); + if (data.error) return handleErrors(data.error); return data; }; \ No newline at end of file diff --git a/api/v2/chat_list.ts b/api/v2/chat_list.ts index d2a7e71a..4a1b539a 100644 --- a/api/v2/chat_list.ts +++ b/api/v2/chat_list.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { ChatListResponse } from "../../types/v2/chat_list"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -15,6 +16,8 @@ export const chat_list = async (params: { addons }); + if (data.error) return handleErrors(data.error); + if (params?.sort == 'date_asc') data.sort((a: any, b: any) => a.last_message_id - b.last_message_id); diff --git a/api/v2/chat_messages.ts b/api/v2/chat_messages.ts index f1c54e24..adfd15e9 100644 --- a/api/v2/chat_messages.ts +++ b/api/v2/chat_messages.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { ChatMessagesResponse } from "../../types/v2/chat_messages"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -14,7 +15,7 @@ export const chat_messages = async (params: { return_object?: boolean; }, addons?: IDefaultParams): Promise => { if (params.id == null) { - return { error: new Error(`Specify channel id`) } as Response; + return handleErrors(`Specify channel id`) as Response; }; @@ -24,6 +25,7 @@ export const chat_messages = async (params: { addons, }); + if (data.error) return handleErrors(data.error); return data; }; \ No newline at end of file diff --git a/api/v2/chat_updates.ts b/api/v2/chat_updates.ts index d51850a3..7563752e 100644 --- a/api/v2/chat_updates.ts +++ b/api/v2/chat_updates.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { ChatUpdatesResponse } from "../../types/v2/chat_updates"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -21,6 +22,7 @@ export const chat_updates = async (params: { addons, }); + if (data.error) return handleErrors(data.error); return data; }; \ No newline at end of file diff --git a/api/v2/comments_actions.ts b/api/v2/comments_actions.ts index 92511bc4..fec107cd 100644 --- a/api/v2/comments_actions.ts +++ b/api/v2/comments_actions.ts @@ -5,6 +5,7 @@ import { CommentsActionsEditResponse } from "../../types/v2/comments_actions_edi import { CommentsActionsDeleteResponse } from "../../types/v2/comments_actions_delete"; import { CommentsActionsVoteResponse } from "../../types/v2/comments_actions_vote"; import { CommentsActionsUnvoteResponse } from "../../types/v2/comments_actions_unvote"; +import { handleErrors } from "../../utility/handleErrors"; type params = ({ @@ -60,15 +61,15 @@ export const comments_actions = async (params: T, addons?: IDe url += `/comments`; if (params.id == null) { - return { error: new Error(`Specify news id or beatmap set id`) } as Response; + return handleErrors(`Specify news id or beatmap set id`) as Response; }; if (params.commentable_type == null) { - return { error: new Error(`Specify commentable_type`) } as Response; + return handleErrors(`Specify commentable_type`) as Response; }; if (params.message == null) { - return { error: new Error(`You forgot to provide message`) } as Response; + return handleErrors(`You forgot to provide message`) as Response; }; @@ -80,11 +81,11 @@ export const comments_actions = async (params: T, addons?: IDe case 'edit': if (params.id == null) { - return { error: new Error(`Specify comment id`) } as Response; + return handleErrors(`Specify comment id`) as Response; }; if (params.message == null) { - return { error: new Error(`You forgot to provide message`) } as Response; + return handleErrors(`You forgot to provide message`) as Response; }; @@ -96,7 +97,7 @@ export const comments_actions = async (params: T, addons?: IDe case 'delete': if (params.id == null) { - return { error: new Error(`Specify comment id`) } as Response; + return handleErrors(`Specify comment id`) as Response; }; @@ -107,7 +108,7 @@ export const comments_actions = async (params: T, addons?: IDe case 'vote': if (params.id == null) { - return { error: new Error(`Specify comment id`) } as Response; + return handleErrors(`Specify comment id`) as Response; }; @@ -118,7 +119,7 @@ export const comments_actions = async (params: T, addons?: IDe case 'unvote': if (params.id == null) { - return { error: new Error(`Specify comment id`) } as Response; + return handleErrors(`Specify comment id`) as Response; }; @@ -128,7 +129,7 @@ export const comments_actions = async (params: T, addons?: IDe break; default: - return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; + return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; }; @@ -138,6 +139,8 @@ export const comments_actions = async (params: T, addons?: IDe addons, }); + if (data.error) return handleErrors(data.error) as Response; + return data as Response; }; \ No newline at end of file diff --git a/api/v2/comments_details.ts b/api/v2/comments_details.ts index 4c43508b..1e488390 100644 --- a/api/v2/comments_details.ts +++ b/api/v2/comments_details.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { CommentsDetailsResponse } from "../../types/v2/comments_details"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -8,7 +9,7 @@ type Response = CommentsDetailsResponse & IError; export const comments_details = async (comment_id: string, addons?: IDefaultParams): Promise => { if (comment_id == null) { - return { error: new Error(`Specify comment id`) } as Response; + return handleErrors(`Specify comment id`) as Response; }; @@ -17,6 +18,8 @@ export const comments_details = async (comment_id: string, addons?: IDefaultPara addons, }); + if (data.error) return handleErrors(data.error); + return data; }; \ No newline at end of file diff --git a/api/v2/comments_list.ts b/api/v2/comments_list.ts index bb940f4d..06c5a880 100644 --- a/api/v2/comments_list.ts +++ b/api/v2/comments_list.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { CommentsListResponse } from "../../types/v2/comments_list"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -33,6 +34,7 @@ export const comments_list = async (params: { addons, }); + if (data.error) return handleErrors(data.error); return data; }; \ No newline at end of file diff --git a/api/v2/forums_topics_actions.ts b/api/v2/forums_topics_actions.ts index a07d7fd1..89c3b11a 100644 --- a/api/v2/forums_topics_actions.ts +++ b/api/v2/forums_topics_actions.ts @@ -4,6 +4,7 @@ import { ForumsTopicsActionsCreateResponse } from "../../types/v2/forums_topics_ import { ForumsTopicsActionsReplyResponse } from "../../types/v2/forums_topics_actions_reply"; import { ForumsTopicsActionsEditTopicResponse } from "../../types/v2/forums_topics_actions_edit_topic"; import { ForumsTopicsActionsEditPostResponse } from "../../types/v2/forums_topics_actions_edit_post"; +import { handleErrors } from "../../utility/handleErrors"; type params = ({ @@ -69,15 +70,15 @@ export const forums_topics_actions = async (params: T, addons? switch (params.type) { case 'create': if (params.forum_id == null) { - return { error: new Error(`Specify forum id`) } as Response; + return handleErrors(`Specify forum id`) as Response; }; if (params.title == null) { - return { error: new Error(`Specify title`) } as Response; + return handleErrors(`Specify title`) as Response; }; if (params.message == null) { - return { error: new Error(`Specify message`) } as Response; + return handleErrors(`Specify message`) as Response; }; @@ -111,11 +112,11 @@ export const forums_topics_actions = async (params: T, addons? case 'reply': if (params.post_id == null) { - return { error: new Error(`Specify post id`) } as Response; + return handleErrors(`Specify post id`) as Response; }; if (params.message == null) { - return { error: new Error(`Specify message`) } as Response; + return handleErrors(`Specify message`) as Response; }; @@ -129,11 +130,11 @@ export const forums_topics_actions = async (params: T, addons? case 'edit_post': if (params.post_id == null) { - return { error: new Error(`Specify post id`) } as Response; + return handleErrors(`Specify post id`) as Response; }; if (params.message == null) { - return { error: new Error(`Specify message`) } as Response; + return handleErrors(`Specify message`) as Response; }; @@ -148,11 +149,11 @@ export const forums_topics_actions = async (params: T, addons? case 'edit_topic': if (params.topic_id && (params.title != null && params.title != '')) { if (params.topic_id == null) { - return { error: new Error(`Specify topic id`) } as Response; + return handleErrors(`Specify topic id`) as Response; }; if (params.title == null) { - return { error: new Error(`Specify title`) } as Response; + return handleErrors(`Specify title`) as Response; }; @@ -174,11 +175,11 @@ export const forums_topics_actions = async (params: T, addons? if (params.post_id && (params.message != null && params.message != '')) { if (params.post_id == null) { - return { error: new Error(`Specify post id`) } as Response; + return handleErrors(`Specify post id`) as Response; }; if (params.message == null) { - return { error: new Error(`Specify message`) } as Response; + return handleErrors(`Specify message`) as Response; }; @@ -195,7 +196,7 @@ export const forums_topics_actions = async (params: T, addons? break; default: - return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; + return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; }; @@ -211,6 +212,11 @@ export const forums_topics_actions = async (params: T, addons? addons, }); + if (data.error) { + results.push(handleErrors(data.error) as Response); + continue; + }; + results.push(data); }; diff --git a/api/v2/forums_topics_details.ts b/api/v2/forums_topics_details.ts index 6ba4a772..2ae8a0e5 100644 --- a/api/v2/forums_topics_details.ts +++ b/api/v2/forums_topics_details.ts @@ -1,6 +1,7 @@ import { request } from "../../utility/request"; import { IDefaultParams, IError } from "../../types"; import { ForumsTopicsDetailsResponse } from "../../types/v2/forums_topics_details"; +import { handleErrors } from "../../utility/handleErrors"; type Response = ForumsTopicsDetailsResponse & IError; @@ -18,7 +19,7 @@ export const forums_topics_details = async (params: { cursor_string?: string, }, addons?: IDefaultParams): Promise => { if (params.id == null) { - return { error: new Error(`Specify topic id`) } as Response + return handleErrors(`Specify topic id`) as Response }; @@ -36,6 +37,8 @@ export const forums_topics_details = async (params: { addons, }); + if (data.error) return handleErrors(data.error); + return data; }; \ No newline at end of file diff --git a/api/v2/matches_details.ts b/api/v2/matches_details.ts index 1607a158..f75b95f3 100644 --- a/api/v2/matches_details.ts +++ b/api/v2/matches_details.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { MatchesDetailsResponse } from "../../types/v2/matches_detaIls"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -8,7 +9,7 @@ type Response = MatchesDetailsResponse & IError; export const matches_details = async (match_id: number, addons?: IDefaultParams): Promise => { if (match_id == null) { - return { error: new Error(`Specify match id`) } as Response; + return handleErrors(`Specify match id`) as Response; }; @@ -17,6 +18,8 @@ export const matches_details = async (match_id: number, addons?: IDefaultParams) addons, }); + if (data.error) return handleErrors(data.error); + return data; }; \ No newline at end of file diff --git a/api/v2/matches_list.ts b/api/v2/matches_list.ts index 9227d27b..32beb509 100644 --- a/api/v2/matches_list.ts +++ b/api/v2/matches_list.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { MatchesListResponse } from "../../types/v2/matches_list"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -24,6 +25,8 @@ export const matches_list = async (params: { addons, }); + if (data.error) return handleErrors(data.error); + return data; }; \ No newline at end of file diff --git a/api/v2/me_details.ts b/api/v2/me_details.ts index 2943fc3b..285ced0c 100644 --- a/api/v2/me_details.ts +++ b/api/v2/me_details.ts @@ -2,6 +2,7 @@ import { credentials } from "../../utility/auth"; import { IDefaultParams, IError, Modes_names } from "../../types"; import { MeDetailsResponse } from "../../types/v2/me_details"; import { request } from "../../utility/request"; +import { handleErrors } from "../../utility/handleErrors"; type Response = MeDetailsResponse & IError; @@ -9,7 +10,7 @@ type Response = MeDetailsResponse & IError; export const me_details = async (addons?: IDefaultParams & { mode: Modes_names }): Promise => { if (credentials.method != 'lazer') { - return { error: new Error(`Login via lazer to use this endpoint`) } as Response + return handleErrors(`Login via lazer to use this endpoint`) as Response }; @@ -21,6 +22,8 @@ export const me_details = async (addons?: IDefaultParams & { mode: Modes_names } addons, }); + if (data.error) return handleErrors(data.error); + return data; }; \ No newline at end of file diff --git a/api/v2/me_download_quota.ts b/api/v2/me_download_quota.ts index 452eb6f9..90fec4b2 100644 --- a/api/v2/me_download_quota.ts +++ b/api/v2/me_download_quota.ts @@ -2,6 +2,7 @@ import { credentials } from "../../utility/auth"; import { IError } from "../../types"; import { MedownloadquotaResponse } from "../../types/v2/me_download_quota"; import { request } from "../../utility/request"; +import { handleErrors } from "../../utility/handleErrors"; type Response = MedownloadquotaResponse & IError; @@ -9,7 +10,7 @@ type Response = MedownloadquotaResponse & IError; export const me_download_quota = async (): Promise => { if (credentials.method != 'lazer') { - return { error: new Error(`Login via lazer to use this endpoint`) } as Response + return handleErrors(`Login via lazer to use this endpoint`) as Response }; @@ -17,6 +18,7 @@ export const me_download_quota = async (): Promise => { method: 'GET', }); + if (data.error) return handleErrors(data.error); return data; }; \ No newline at end of file diff --git a/api/v2/me_friends.ts b/api/v2/me_friends.ts index 97e99e37..90849592 100644 --- a/api/v2/me_friends.ts +++ b/api/v2/me_friends.ts @@ -2,6 +2,7 @@ import { credentials } from "../../utility/auth"; import { IDefaultParams, IError } from "../../types"; import { request } from "../../utility/request"; import { MeFriendsResponse } from "../../types/v2/me_friends"; +import { handleErrors } from "../../utility/handleErrors"; type Response = MeFriendsResponse[] & IError; @@ -9,7 +10,7 @@ type Response = MeFriendsResponse[] & IError; export const me_friends = async (addons?: IDefaultParams): Promise => { if (credentials.method != 'lazer') { - return { error: new Error(`Login via lazer to use this endpoint`) } as Response + return handleErrors(`Login via lazer to use this endpoint`) as Response }; @@ -18,6 +19,7 @@ export const me_friends = async (addons?: IDefaultParams): Promise => addons, }); + if (data.error) return handleErrors(data.error); return data; }; \ No newline at end of file diff --git a/api/v2/news_details.ts b/api/v2/news_details.ts index edec6220..4ea95f8e 100644 --- a/api/v2/news_details.ts +++ b/api/v2/news_details.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { NewsDetailsResponse } from "../../types/v2/news_details"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -11,7 +12,7 @@ export const news_details = async (params: { key?: 'id' | null; }, addons?: IDefaultParams): Promise => { if (params.news_id == null) { - return { error: new Error(`Specify news id`) } as Response + return handleErrors(`Specify news id`) as Response }; @@ -21,6 +22,7 @@ export const news_details = async (params: { addons, }); + if (data.error) return handleErrors(data.error); return data; }; \ No newline at end of file diff --git a/api/v2/news_list.ts b/api/v2/news_list.ts index 5077e4a3..7e83dec9 100644 --- a/api/v2/news_list.ts +++ b/api/v2/news_list.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { NewsListResponse } from "../../types/v2/news_list"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -24,6 +25,8 @@ export const news_list = async (params: { addons, }); + if (data.error) return handleErrors(data.error); + return data; }; \ No newline at end of file diff --git a/api/v2/notification_actions.ts b/api/v2/notification_actions.ts index 33610669..47f037d2 100644 --- a/api/v2/notification_actions.ts +++ b/api/v2/notification_actions.ts @@ -1,5 +1,6 @@ import { request } from "../../utility/request"; import { IDefaultParams, IError } from "../../types"; +import { handleErrors } from "../../utility/handleErrors"; type params = ({ @@ -40,7 +41,7 @@ export const notification_actions = async (params: T, addons?: method = 'POST'; if (params.notifications == null && params.identities == null) { - return { error: new Error(`Missing on of parameters`) } as Response; + return handleErrors(`Missing on of parameters`) as Response; }; // params.ids.forEach((r, index) => object[`identities[${index}][id]`] = r); @@ -55,7 +56,7 @@ export const notification_actions = async (params: T, addons?: break; default: - return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; + return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; }; @@ -65,6 +66,8 @@ export const notification_actions = async (params: T, addons?: addons, }); + if (data.error) return handleErrors(data.error) as Response; + return data as Response; }; \ No newline at end of file diff --git a/api/v2/notifications_list.ts b/api/v2/notifications_list.ts index 05f08cc4..c7690a21 100644 --- a/api/v2/notifications_list.ts +++ b/api/v2/notifications_list.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { NotificationsListResponse } from "../../types/v2/notifications_list"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -18,6 +19,8 @@ export const notifications_list = async (params: { addons, }); + if (data.error) return handleErrors(data.error); + if (params.unreaded_only == true && !('error' in data)) data.notifications = data.notifications.filter((r: any) => r.is_read == false); diff --git a/api/v2/ranking_list.ts b/api/v2/ranking_list.ts index 6ebce32a..9ad3e2a6 100644 --- a/api/v2/ranking_list.ts +++ b/api/v2/ranking_list.ts @@ -5,6 +5,7 @@ import { RankingListCountryResponse } from "../../types/v2/ranking_list_country" import { RankingListPerformanceResponse } from "../../types/v2/ranking_list_performance"; import { RankingListKudosuResponse } from "../../types/v2/ranking_list_kudosu"; import { RankingListScoreResponse } from "../../types/v2/ranking_list_score"; +import { handleErrors } from "../../utility/handleErrors"; type params = { @@ -55,9 +56,7 @@ type Response = export const ranking_list = async (params: T, addons?: IDefaultParams): Promise> => { if (params.type != 'kudosu' && params.mode == null) { - return { - error: new Error('Gamemode not specified'), - } as Response; + return handleErrors('Gamemode not specified') as Response; }; @@ -106,7 +105,7 @@ export const ranking_list = async (params: T, addons?: IDefaul break; default: - return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; + return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; }; @@ -116,10 +115,7 @@ export const ranking_list = async (params: T, addons?: IDefaul addons, }); - - if ('error' in data) { - return data as Response; - }; + if (data.error) return handleErrors(data.error) as Response; if (params.type == 'kudosu') return data.ranking as Response; diff --git a/api/v2/rooms_details.ts b/api/v2/rooms_details.ts index d36ef827..f35547ce 100644 --- a/api/v2/rooms_details.ts +++ b/api/v2/rooms_details.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { RoomsDetailsResponse } from "../../types/v2/rooms_details"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -8,7 +9,7 @@ type Response = RoomsDetailsResponse & IError; export const rooms_details = async (id: number | 'latest', addons?: IDefaultParams): Promise => { if (id == null) { - return { error: new Error(`Specify room id`) } as Response; + return handleErrors(`Specify room id`) as Response; }; @@ -17,6 +18,8 @@ export const rooms_details = async (id: number | 'latest', addons?: IDefaultPara addons, }); + if (data.error) return handleErrors(data.error); + return data; }; \ No newline at end of file diff --git a/api/v2/rooms_leaderboard.ts b/api/v2/rooms_leaderboard.ts index 9686077e..3d55da6d 100644 --- a/api/v2/rooms_leaderboard.ts +++ b/api/v2/rooms_leaderboard.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { RoomsLeaderboardResponse } from "../../types/v2/rooms_leaderboard"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -11,7 +12,7 @@ export const rooms_leaderboard = async (params: { limit?: number; }, addons?: IDefaultParams): Promise => { if (params.id == null) { - return { error: new Error(`Specify room id`) } as Response; + return handleErrors(`Specify room id`) as Response; }; @@ -21,6 +22,8 @@ export const rooms_leaderboard = async (params: { addons, }); + if (data.error) return handleErrors(data.error); + return data; }; \ No newline at end of file diff --git a/api/v2/rooms_list.ts b/api/v2/rooms_list.ts index 407c76de..0e3c9145 100644 --- a/api/v2/rooms_list.ts +++ b/api/v2/rooms_list.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { RoomsListResponse } from "../../types/v2/rooms_list"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -33,6 +34,8 @@ export const rooms_list = async (params: { addons, }); + if (data.error) return handleErrors(data.error); + if (params?.query && !('error' in data)) data.rooms = data.rooms.filter((r: any) => r.name.toLowerCase().includes(params.query.trim().toLowerCase())) diff --git a/api/v2/rooms_scores.ts b/api/v2/rooms_scores.ts index 2de2b6de..503a1f8c 100644 --- a/api/v2/rooms_scores.ts +++ b/api/v2/rooms_scores.ts @@ -3,6 +3,7 @@ import { IDefaultParams, IError } from "../../types"; import { RoomsScoresSingleResponse } from "../../types/v2/rooms_scores_single"; import { RoomScoresUserHighestResponse } from "../../types/v2/rooms_scores_user_highest"; import { RoomsScoresAllResponse } from "../../types/v2/rooms_scores_all"; +import { handleErrors } from "../../utility/handleErrors"; type params = ({ @@ -47,11 +48,11 @@ export const rooms_scores = async (params: T, addons?: IDefaul if (params.id == null) { - return { error: new Error(`Specify room id`) } as Response; + return handleErrors(`Specify room id`) as Response; }; if (params.playlist_id == null) { - return { error: new Error(`Specify playlist id`) } as Response; + return handleErrors(`Specify playlist id`) as Response; }; @@ -75,7 +76,7 @@ export const rooms_scores = async (params: T, addons?: IDefaul break; default: - return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; + return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; }; @@ -85,6 +86,8 @@ export const rooms_scores = async (params: T, addons?: IDefaul addons, }); + if (data.error) return handleErrors(data.error) as Response; + return data as Response; }; \ No newline at end of file diff --git a/api/v2/scores_details.ts b/api/v2/scores_details.ts index 532e8b51..5a5af16c 100644 --- a/api/v2/scores_details.ts +++ b/api/v2/scores_details.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError, Modes_names } from "../../types"; import { ScoresDetailsResponse } from "../../types/v2/scores_details"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -11,7 +12,7 @@ export const scores_details = async (params: { mode?: Modes_names; }, addons?: IDefaultParams): Promise => { if (params.id == null) { - return { error: new Error(`Specify score id`) } as Response; + return handleErrors(`Specify score id`) as Response; }; @@ -22,6 +23,8 @@ export const scores_details = async (params: { addons, }); + if (data.error) return handleErrors(data.error); + return data; }; \ No newline at end of file diff --git a/api/v2/scores_download.ts b/api/v2/scores_download.ts index 2bdf6e9b..bcc065dc 100644 --- a/api/v2/scores_download.ts +++ b/api/v2/scores_download.ts @@ -1,5 +1,6 @@ import { IError, Modes_names } from "../../types"; import { ScoresDownloadResponse } from "../../types/v2/scores_download"; +import { handleErrors } from "../../utility/handleErrors"; import { download } from "../../utility/request"; @@ -12,7 +13,7 @@ export const scores_download = async (params: { file_path?: string; }): Promise => { if (params.id == null) { - return { error: new Error(`Specify score id`) } as Response; + return handleErrors(`Specify score id`) as Response; }; @@ -22,6 +23,8 @@ export const scores_download = async (params: { _callback: false, }); + if (data.error) return handleErrors(data.error); + return data; }; \ No newline at end of file diff --git a/api/v2/scores_list.ts b/api/v2/scores_list.ts index 7838cb85..fefd8618 100644 --- a/api/v2/scores_list.ts +++ b/api/v2/scores_list.ts @@ -8,6 +8,7 @@ import { ScoresListUserBestResponse } from "../../types/v2/scores_list_user_best import { ScoresListUserFirstsResponse } from "../../types/v2/scores_list_user_firsts"; import { ScoresListUserRecentResponse } from "../../types/v2/scores_list_user_recent"; import { ScoresListUserPinnedResponse } from "../../types/v2/scores_list_user_pinned"; +import { handleErrors } from "../../utility/handleErrors"; type params = { @@ -70,7 +71,7 @@ export const scores_list = async (params: T, addons?: IDefault switch (params.type) { case 'leaderboard': if (params.beatmap_id == null) { - return { error: new Error(`Specify beatmap id`) } as Response; + return handleErrors(`Specify beatmap id`) as Response; }; @@ -84,11 +85,11 @@ export const scores_list = async (params: T, addons?: IDefault case 'beatmap_best': if (params.beatmap_id == null) { - return { error: new Error(`Specify beatmap id`) } as Response; + return handleErrors(`Specify beatmap id`) as Response; }; if (params.user_id == null) { - return { error: new Error(`Specify user id`) } as Response; + return handleErrors(`Specify user id`) as Response; }; @@ -101,11 +102,11 @@ export const scores_list = async (params: T, addons?: IDefault case 'beatmap_all': if (params.beatmap_id == null) { - return { error: new Error(`Specify beatmap id`) } as Response; + return handleErrors(`Specify beatmap id`) as Response; }; if (params.user_id == null) { - return { error: new Error(`Specify user id`) } as Response; + return handleErrors(`Specify user id`) as Response; }; @@ -120,7 +121,7 @@ export const scores_list = async (params: T, addons?: IDefault case 'user_recent': case 'user_pinned': if (params.user_id == null) { - return { error: new Error(`Specify user id`) } as Response; + return handleErrors(`Specify user id`) as Response; }; @@ -135,7 +136,7 @@ export const scores_list = async (params: T, addons?: IDefault case 'solo_scores': if (params.beatmap_id == null) { - return { error: new Error(`Specify beatmap id`) } as Response; + return handleErrors(`Specify beatmap id`) as Response; }; @@ -148,7 +149,7 @@ export const scores_list = async (params: T, addons?: IDefault break; default: - return { error: new Error(`Unsupported type: ${(params as any).type}`) } as Response; + return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; }; @@ -158,10 +159,7 @@ export const scores_list = async (params: T, addons?: IDefault addons, }); - - if ('error' in data) { - return data; - }; + if (data.error) return handleErrors(data.error) as Response; if (['leaderboard', 'beatmap_all'].includes(params.type)) { diff --git a/api/v2/search.ts b/api/v2/search.ts index d0c9fdb1..05dfe9a1 100644 --- a/api/v2/search.ts +++ b/api/v2/search.ts @@ -1,6 +1,7 @@ import { beatmap_category, beatmap_sorting, beatmap_statuses, Modes_names, beatmap_genres, beatmap_languages, beatmap_ranks, beatmap_extra, IDefaultParams, IError } from "../../types"; import { Genres_enum, Languages_enum, GamemodeEnum } from "../../types/enums"; import { SearchBeatmaps, SearchWiki } from '../../types/v2/search_all'; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -83,6 +84,8 @@ export const search_all = async (params: T, addons?: IDefaultP addons }); + if (data.error) return handleErrors(data.error) as Response; + return data as Response; }; \ No newline at end of file diff --git a/api/v2/session_actions.ts b/api/v2/session_actions.ts index 1905f643..db3cd92e 100644 --- a/api/v2/session_actions.ts +++ b/api/v2/session_actions.ts @@ -1,5 +1,6 @@ import { request } from "../../utility/request"; import { IDefaultParams, IError } from "../../types"; +import { handleErrors } from "../../utility/handleErrors"; type params = ({ @@ -51,6 +52,8 @@ export const session_actions = async (params: T, addons?: IDef addons, }); + if (data.error) return handleErrors(data.error) as Response; + return data as Response; }; \ No newline at end of file diff --git a/api/v2/spotlights_list.ts b/api/v2/spotlights_list.ts index bc8a668b..06185ec0 100644 --- a/api/v2/spotlights_list.ts +++ b/api/v2/spotlights_list.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { SpotlightsListResponse } from "../../types/v2/spotlights_list"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -12,6 +13,8 @@ export const spotlights_list = async (addons?: IDefaultParams): Promise => { if (params.id == null) { - return { error: new Error(`Specify activity id`) } as Response; + return handleErrors(`Specify activity id`) as Response; }; @@ -25,6 +26,8 @@ export const users_activity = async (params: { addons, }); + if (data.error) return handleErrors(data.error); + return data; }; \ No newline at end of file diff --git a/api/v2/users_beatmaps.ts b/api/v2/users_beatmaps.ts index e66c2ac9..d2c47c8f 100644 --- a/api/v2/users_beatmaps.ts +++ b/api/v2/users_beatmaps.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { UsersBeatmapsResponse } from "../../types/v2/users_beatmaps"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -14,11 +15,11 @@ export const users_beatmaps = async (params: { offset?: number; }, addons?: IDefaultParams): Promise => { if (params.id == null) { - return { error: new Error(`Specify user id`) } as Response; + return handleErrors(`Specify user id`) as Response; }; if (params.type == null) { - return { error: new Error(`Specify beatmaps type`) } as Response; + return handleErrors(`Specify beatmaps type`) as Response; }; @@ -31,6 +32,8 @@ export const users_beatmaps = async (params: { addons, }); + if (data.error) return handleErrors(data.error); + return data; }; \ No newline at end of file diff --git a/api/v2/users_details.ts b/api/v2/users_details.ts index effb2196..6e77f6db 100644 --- a/api/v2/users_details.ts +++ b/api/v2/users_details.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError, Modes_names } from "../../types"; import { UsersDetailsResponse } from "../../types/v2/users_details"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -12,7 +13,7 @@ export const users_details = async (params: { key?: 'id' | 'username'; }, addons?: IDefaultParams): Promise => { if (params.id == null) { - return { error: new Error(`Specify user id`) } as Response; + return handleErrors(`Specify user id`) as Response; }; @@ -22,6 +23,7 @@ export const users_details = async (params: { addons, }); + if (data.error) return handleErrors(data.error); return data; }; \ No newline at end of file diff --git a/api/v2/users_events.ts b/api/v2/users_events.ts index e29bdbce..bfd34484 100644 --- a/api/v2/users_events.ts +++ b/api/v2/users_events.ts @@ -1,6 +1,7 @@ import { request } from "../../utility/request"; import { UsersEventsResponse } from '../../types/v2/users_events'; import { IDefaultParams, IError } from "../../types"; +import { handleErrors } from "../../utility/handleErrors"; type Response = UsersEventsResponse[] & IError; @@ -17,11 +18,11 @@ export const users_events = async ({ sort, cursor_string, type }: { addons, }); - if (data.error) return data.error; + if (data.error) return handleErrors(data.error); if (type != null && !Array.isArray(type)) { - return { error: new Error(`Events Type must be an Array of types. Example: ['achievement', 'rank']`) } as Response; + return handleErrors(`Events Type must be an Array of types. Example: ['achievement', 'rank']`) as Response; }; diff --git a/api/v2/users_kudosu.ts b/api/v2/users_kudosu.ts index 584bfd46..f2287604 100644 --- a/api/v2/users_kudosu.ts +++ b/api/v2/users_kudosu.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { UsersKudosuResponse } from "../../types/v2/users_kudosu"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -12,7 +13,7 @@ export const users_kudosu = async (params: { offset?: number; }, addons?: IDefaultParams): Promise => { if (params.id == null) { - return { error: new Error(`Specify user id`) } as Response; + return handleErrors(`Specify user id`) as Response; }; @@ -25,6 +26,8 @@ export const users_kudosu = async (params: { addons, }); + if (data.error) return handleErrors(data.error); + return data; }; \ No newline at end of file diff --git a/api/v2/users_list.ts b/api/v2/users_list.ts index 2087803f..918ff51b 100644 --- a/api/v2/users_list.ts +++ b/api/v2/users_list.ts @@ -1,6 +1,7 @@ import { request } from "../../utility/request"; import { IDefaultParams, IError } from "../../types"; import { UsersLisResponse } from "../../types/v2/users_list"; +import { handleErrors } from "../../utility/handleErrors"; type Response = UsersLisResponse[] & IError; @@ -8,7 +9,7 @@ type Response = UsersLisResponse[] & IError; export const users_list = async (ids: number[], addons?: IDefaultParams): Promise => { if ((ids || [])?.length == 0) { - return { error: new Error(`Specify at least one user id`) } as Response; + return handleErrors(`Specify at least one user id`) as Response; }; @@ -20,6 +21,8 @@ export const users_list = async (ids: number[], addons?: IDefaultParams): Promis addons }); + if (data.error) return handleErrors(data.error); + if (data.users) return data.users; return data; diff --git a/api/v2/wiki_details.ts b/api/v2/wiki_details.ts index 66792c38..afa7cf15 100644 --- a/api/v2/wiki_details.ts +++ b/api/v2/wiki_details.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { WikiDetailsResponse } from "../../types/v2/wiki_details"; +import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -11,11 +12,11 @@ export const wiki_details = async (params: { path_name: string; }, addons?: IDefaultParams): Promise => { if (params.locale == null) { - return { error: new Error(`Specify locale code. Example: en`) } as Response; + return handleErrors(`Specify locale code. Example: en`) as Response; }; if (params.path_name == null) { - return { error: new Error(`Specify wiki page path`) } as Response; + return handleErrors(`Specify wiki page path`) as Response; }; @@ -24,6 +25,8 @@ export const wiki_details = async (params: { addons, }); + if (data.error) return handleErrors(data.error); + return data; }; \ No newline at end of file diff --git a/tools/accuracy.ts b/tools/accuracy.ts index 267f28c4..248db655 100644 --- a/tools/accuracy.ts +++ b/tools/accuracy.ts @@ -1,6 +1,7 @@ import { IError } from "../types"; import { GamemodeEnum } from "../types/enums"; import { AccuracyResponse } from "../types/tools"; +import { handleErrors } from "../utility/handleErrors"; type Hits = { @@ -25,7 +26,7 @@ type Response = AccuracyResponse & IError; export const calculate_accuracy = (hits: Hits, mode: GamemodeEnum | string | number): Response => { if (Object.keys(hits).length == 0) { - return { error: new Error('Provide hits (300, 100, 50, etc)') } as Response; + return handleErrors('Provide hits (300, 100, 50, etc)') as Response; }; @@ -71,7 +72,7 @@ export const calculate_accuracy = (hits: Hits, mode: GamemodeEnum | string | num break; default: - return { error: new Error(`Unsupported gamemode: ${mode}}`) } as Response; + return handleErrors(`Unsupported gamemode: ${mode}}`) as Response; }; diff --git a/tools/country.ts b/tools/country.ts index 914befdb..4a734ce1 100644 --- a/tools/country.ts +++ b/tools/country.ts @@ -1,6 +1,7 @@ import { IError } from "../types"; import { CountryCodes, CountryNames } from "../types/enums"; import { CountryResponse } from "../types/tools"; +import { handleErrors } from "../utility/handleErrors"; type Response = CountryResponse & IError; @@ -8,14 +9,14 @@ type Response = CountryResponse & IError; export const country_details = (name: string): Response => { if (name == null || name == '') { - return { error: new Error('Specify country code or country name') } as Response; + return handleErrors('Specify country code or country name') as Response; }; if (name.length == 2) { const find = (CountryNames as any)[name.toUpperCase()]; if (find == null) { - return { error: new Error('Country not found') } as Response; + return handleErrors('Country not found') as Response; }; @@ -28,7 +29,7 @@ export const country_details = (name: string): Response => { const find = (CountryCodes as any)[name]; if (find == null) { - return { error: new Error('Country not found') } as Response; + return handleErrors('Country not found') as Response; }; diff --git a/tools/index.ts b/tools/index.ts index a59e216f..167a4e3d 100644 --- a/tools/index.ts +++ b/tools/index.ts @@ -1,3 +1,5 @@ +import { handleErrors } from "../utility/handleErrors"; + export { beatmaps_download } from "../api/v2/beatmaps_download"; export { calculate_accuracy } from "./accuracy"; export { calculate_mods } from "./mods"; @@ -8,7 +10,7 @@ export { calculate_total_objects } from "./objects"; export const calculate_pp = () => { - return new Error('Use rosu-pp-js instead'); + return handleErrors('Use rosu-pp-js instead'); }; diff --git a/tools/mods.ts b/tools/mods.ts index f8b977af..9c053b28 100644 --- a/tools/mods.ts +++ b/tools/mods.ts @@ -1,6 +1,7 @@ import { IError } from "../types"; import { ModsOrder } from "../types/enums"; import { ModsResponse } from "../types/tools"; +import { handleErrors } from "../utility/handleErrors"; @@ -130,7 +131,7 @@ type Response = ModsResponse & IError; // SWITCH STATEMENT CREATED ON PURPOSE BECAUSE IT'S WAY FASTER export const calculate_mods = (ModsName: string | number, order?: boolean): Response => { if (ModsName == null) { - return { error: new Error(`Specify mods name (HDDT or 72)`) } as Response; + return handleErrors(`Specify mods name (HDDT or 72)`) as Response; }; @@ -147,7 +148,7 @@ export const calculate_mods = (ModsName: string | number, order?: boolean): Resp const ModsArray = ModsName.toLowerCase().match(/.{1,2}/g); if (!Array.isArray(ModsArray)) { - return { error: new Error(`Can't convert mods (${ModsName}) to array of mods`) } as Response; + return handleErrors(`Can't convert mods (${ModsName}) to array of mods`) as Response; }; diff --git a/tools/objects.ts b/tools/objects.ts index bb1b5ff6..e3528373 100644 --- a/tools/objects.ts +++ b/tools/objects.ts @@ -1,6 +1,7 @@ import { IError } from "../types"; import { GamemodeEnum } from "../types/enums"; import { TotalObjectsResponse } from "../types/tools"; +import { handleErrors } from "../utility/handleErrors"; type Hits = { @@ -25,7 +26,7 @@ type Response = TotalObjectsResponse & IError; export const calculate_total_objects = (hits: Hits, mode: GamemodeEnum | string | number): Response => { if (Object.keys(hits).length == 0) { - return { error: new Error('Provide hits (300, 100, 50, etc)') } as Response; + return handleErrors('Provide hits (300, 100, 50, etc)') as Response; }; @@ -61,7 +62,7 @@ export const calculate_total_objects = (hits: Hits, mode: GamemodeEnum | string break; default: - return { error: new Error(`Unsupported gamemode: ${mode}}`) } as Response; + return handleErrors(`Unsupported gamemode: ${mode}}`) as Response; }; diff --git a/tools/rank.ts b/tools/rank.ts index de84b24f..225c5133 100644 --- a/tools/rank.ts +++ b/tools/rank.ts @@ -1,6 +1,7 @@ import { IError } from "../types"; -import { GamemodeEnum, ModsBitwise, ModsEnum } from "../types/enums"; +import { GamemodeEnum } from "../types/enums"; import { RankResponse } from "../types/tools"; +import { handleErrors } from "../utility/handleErrors"; import { calculate_accuracy } from "./accuracy"; import { calculate_mods } from "./mods"; @@ -27,7 +28,7 @@ type Response = RankResponse & IError; export const calculate_rank = (hits: Hits, mods: string | number = 0, mode: GamemodeEnum | string | number): Response => { if (Object.keys(hits).length == 0) { - return { error: new Error('Provide hits (300, 100, 50, etc)') } as Response; + return handleErrors('Provide hits (300, 100, 50, etc)') as Response; }; diff --git a/types/index.ts b/types/index.ts index 876f0b8f..da138681 100644 --- a/types/index.ts +++ b/types/index.ts @@ -45,7 +45,8 @@ export type auth_scopes = ( export type auth_params = { - timeout?: number, + timeout?: number; + tokenPath?: string; } & ({ method: 'v2'; @@ -76,10 +77,15 @@ export type auth_params = { export type auth_response = { + token_type: string; access_token: string; expires_in: number; }; +export interface lazer_auth_response extends auth_response { + refresh_token: string; +}; + export type IBeatmapPackType = 'standard' | 'featured' | 'tournament' | 'loved' | 'chart' | 'theme' | 'artist'; diff --git a/utility/auth.ts b/utility/auth.ts index e3ad054c..2343562c 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -3,12 +3,14 @@ import { request } from "./request"; import readln from "readline"; -import { auth_params, auth_response, auth_scopes, Modes_names } from '../types/index'; +import { auth_params, auth_response, auth_scopes, lazer_auth_response, Modes_names } from '../types/index'; import { UserAuth } from '../types/v2/users_details'; +import { handleErrors } from './handleErrors'; export const settings = { timeout: 60000, + throwErrors: true, }; @@ -26,6 +28,8 @@ export const credentials: { redirect_url: string; state: string; + tokenPath: string; + scopes: auth_scopes; } = { method: '' as any, @@ -41,6 +45,8 @@ export const credentials: { redirect_url: '', state: '', + tokenPath: '', + scopes: ['public'], }; @@ -57,6 +63,9 @@ export const cache = { export const login = (params: auth_params) => { credentials.method = params.method; + if (params.tokenPath) credentials.tokenPath = params.tokenPath; + if (params.timeout) settings.timeout = params.timeout; + if (params.method == 'v1') { credentials.api_key = params.api_key; @@ -109,7 +118,7 @@ export const refresh_token = async () => { const client_login = async (client_id: number | string, client_secret: string, scopes: auth_scopes): Promise => { - const { access_token, expires_in } = await request('https://osu.ppy.sh/oauth/token', { + const response = await request('https://osu.ppy.sh/oauth/token', { method: 'POST', headers: { "Accept": "application/json", @@ -124,14 +133,16 @@ const client_login = async (client_id: number | string, client_secret: string, s }) }); + if (response.error) return handleErrors(response.error); + - cache.v2 = access_token; - return { access_token, expires_in }; + cache.v2 = response.access_token; + return response; }; -const lazer_login = async (login: string, password: string) => { - const { access_token, expires_in } = await request('https://osu.ppy.sh/oauth/token', { +const lazer_login = async (login: string, password: string): Promise => { + const response = await request('https://osu.ppy.sh/oauth/token', { method: 'POST', headers: { "Accept": "application/json", @@ -147,9 +158,11 @@ const lazer_login = async (login: string, password: string) => { }) }); + if (response.error) return handleErrors(response.error); - cache.v2 = access_token; - return { access_token, expires_in }; + + cache.v2 = response.access_token; + return response; }; @@ -164,7 +177,7 @@ const authorize_cli = async (client_id: number | string, client_secret: string, const code = await question('Paste code here'); - const { access_token, expires_in } = await request('https://osu.ppy.sh/oauth/token', { + const response = await request('https://osu.ppy.sh/oauth/token', { method: 'POST', headers: { "Accept": "application/json", @@ -179,9 +192,11 @@ const authorize_cli = async (client_id: number | string, client_secret: string, }) }); + if (response.error) return handleErrors(response.error); + - cache.v2 = access_token; - return { access_token, expires_in }; + cache.v2 = response.access_token; + return response; }; @@ -215,7 +230,7 @@ export const authorize = async ({ code, mode, client_id, client_secret, redirect redirect_url: string; }): Promise => { - const { access_token, refresh_token, expires_in } = await request('https://osu.ppy.sh/oauth/token', { + const response = await request('https://osu.ppy.sh/oauth/token', { method: 'POST', headers: { "Accept": "application/json", @@ -230,14 +245,20 @@ export const authorize = async ({ code, mode, client_id, client_secret, redirect }) }); + if (response.error) return handleErrors(response.error); + const user = await request(`https://osu.ppy.sh/api/v2/me/${mode}`, { method: 'GET', - addons: { authKey: access_token, ignoreSessionRefresh: true } + addons: { authKey: response.access_token, ignoreSessionRefresh: true } }); - user.access_token = access_token; - user.refresh_token = refresh_token; - user.expires_in = expires_in; + + if (user.error) return handleErrors(user.error); + + + user.access_token = response.access_token; + user.refresh_token = response.refresh_token; + user.expires_in = response.expires_in; return user; }; @@ -252,7 +273,7 @@ export const refresh_session = async ({ refresh_token, mode, client_id, client_s redirect_url: string; }): Promise => { - const { access_token, refresh_token: refresh_token_new, expires_in } = await request('https://osu.ppy.sh/oauth/token', { + const response = await request('https://osu.ppy.sh/oauth/token', { method: 'POST', headers: { "Accept": "application/json", @@ -267,14 +288,20 @@ export const refresh_session = async ({ refresh_token, mode, client_id, client_s }) }); + if (response.error) return handleErrors(response.error); + const user = await request(`https://osu.ppy.sh/api/v2/me/${mode}`, { method: 'GET', - addons: { authKey: access_token, ignoreSessionRefresh: true } + addons: { authKey: response.access_token, ignoreSessionRefresh: true } }); - user.access_token = access_token; - user.refresh_token = refresh_token_new; - user.expires_in = expires_in; + + if (user.error) return handleErrors(user.error); + + + user.access_token = response.access_token; + user.refresh_token = response.refresh_token_new; + user.expires_in = response.expires_in; return user; }; \ No newline at end of file diff --git a/utility/handleErrors.ts b/utility/handleErrors.ts new file mode 100644 index 00000000..e0b91981 --- /dev/null +++ b/utility/handleErrors.ts @@ -0,0 +1,11 @@ +import { settings } from '../utility/auth'; + + +export const handleErrors = (message: string): any => { + if (settings.throwErrors) { + throw new Error(message); + }; + + + return { error: new Error(message) }; +}; \ No newline at end of file diff --git a/utility/request.ts b/utility/request.ts index 032e9416..9e895be6 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -17,7 +17,7 @@ export interface RequestType { headers?: { [key: string]: string }, params?: { [key: string]: any }; addons?: IDefaultParams; - }): Promise; + }): Promise; }; @@ -44,11 +44,11 @@ const sanitize_query = (obj: object): string => { export const request: RequestType = (url, { method, headers, data, params = {}, addons = {} }) => new Promise((resolve, reject) => { // check required args if (url == null) { - return resolve({ error: new Error('URL not specified'), }); + return resolve({ error: 'URL not specified', }); }; if (method == null) { - return resolve({ error: new Error('Method not specified'), }); + return resolve({ error: 'Method not specified', }); }; @@ -57,7 +57,7 @@ export const request: RequestType = (url, { method, headers, data, params = {}, params.k = addons.authKey || auth.cache.v1; if (params.k == null) { - return resolve({ error: new Error('v1 api key not specified'), }); + return resolve({ error: 'v1 api key not specified', }); }; }; @@ -72,7 +72,7 @@ export const request: RequestType = (url, { method, headers, data, params = {}, headers['x-api-version'] = addons.apiVersion == '' ? null : addons.apiVersion || '20240130'; if ((addons.authKey || auth.cache.v2) == null) { - return resolve({ error: new Error('v2 not authorized') }); + return resolve({ error: 'v2 not authorized' }); }; }; @@ -135,23 +135,23 @@ export const request: RequestType = (url, { method, headers, data, params = {}, if ('error' in parse) { if (parse.error === null) { - return resolve({ error: new Error(`osu returned empty error, double check your parameters (request)`) }); + return resolve({ error: `osu returned empty error, double check your parameters (request)` }); }; - return resolve({ error: new Error(parse.error) }); + return resolve({ error: parse.error }); }; if (parse.authentication === 'basic') { - return resolve({ error: new Error('Unauthorized (double check credentials)') }); + return resolve({ error: 'Unauthorized (double check credentials)' }); }; total_retries = 0; return resolve(parse); } catch (error) { - return resolve({ error: error }); + return resolve({ error: (error as any).name }); }; }; @@ -163,13 +163,13 @@ export const request: RequestType = (url, { method, headers, data, params = {}, // send error req.on('error', (error) => { - resolve({ error: error }); + resolve({ error: error.name }); }); // timeout req.setTimeout(addons.timeout_ms || auth.settings.timeout, () => { req.destroy(); - resolve({ error: new Error(`Request to ${build_url} time out after ${addons.timeout_ms || auth.settings.timeout}ms`) }); + resolve({ error: `Request to ${build_url} time out after ${addons.timeout_ms || auth.settings.timeout}ms` }); }); @@ -217,7 +217,7 @@ export const download = (url: string, dest: string, { _callback, headers = {}, d if (response.statusCode === 404) { - return resolve({ error: new Error('file unavailable') }); + return resolve({ error: 'file unavailable' }); }; @@ -233,13 +233,13 @@ export const download = (url: string, dest: string, { _callback, headers = {}, d if ('error' in json && json.error == null) { - return resolve({ error: new Error('osu returned empty error (download)') }); + return resolve({ error: 'osu returned empty error (download)' }); }; return resolve(json); } catch (error) { - return resolve({ error: new Error(`Unable to download file: ${data} (${url})`) }); + return resolve({ error: `Unable to download file: ${data} (${url})` }); }; }); @@ -252,7 +252,7 @@ export const download = (url: string, dest: string, { _callback, headers = {}, d file.on('error', error => { fs.unlinkSync(dest); - resolve({ error: error }); + resolve({ error: error.name }); }); file.on('finish', () => { @@ -282,14 +282,14 @@ export const download = (url: string, dest: string, { _callback, headers = {}, d // send error req.on('error', (error) => { - resolve({ error: error }); + resolve({ error: error.name }); }); // timeout req.setTimeout(addons.timeout_ms || auth.settings.timeout, () => { req.destroy(); - resolve({ error: new Error(`Request to ${build_url} time out after ${addons.timeout_ms || auth.settings.timeout}ms`) }); + resolve({ error: `Request to ${build_url} time out after ${addons.timeout_ms || auth.settings.timeout}ms` }); }); if (data) { From 5e9e9f693e1117e8d38c2c8f4c33a78eaacd0a78 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 27 Apr 2024 20:15:01 +0300 Subject: [PATCH 141/259] Save access_token to a file, to prevent request spam to osu auth (EXPEREMENTAL) --- utility/auth.ts | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/utility/auth.ts b/utility/auth.ts index 2343562c..bc52b76f 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -1,6 +1,8 @@ import { execSync } from 'child_process'; import { request } from "./request"; import readln from "readline"; +import path from "path"; +import fs from "fs"; import { auth_params, auth_response, auth_scopes, lazer_auth_response, Modes_names } from '../types/index'; @@ -116,8 +118,36 @@ export const refresh_token = async () => { }; +const token_exists = () => { + if (!fs.existsSync(credentials.tokenPath)) return false; + + try { + const authData: auth_response = JSON.parse(fs.readFileSync(credentials.tokenPath, 'utf8')); + set_v2(authData.access_token); + + return true; + } catch (error) { + return false; + }; +}; + + +const save_token = (response: auth_response) => { + const { dir } = path.parse(credentials.tokenPath); + if (fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); + + fs.writeFileSync(credentials.tokenPath, JSON.stringify(response), 'utf8'); +}; + + const client_login = async (client_id: number | string, client_secret: string, scopes: auth_scopes): Promise => { + if (cache.v2 == '' && credentials.tokenPath != '') { + const is = token_exists(); + if (is) return; + }; + + const response = await request('https://osu.ppy.sh/oauth/token', { method: 'POST', headers: { @@ -137,11 +167,20 @@ const client_login = async (client_id: number | string, client_secret: string, s cache.v2 = response.access_token; + save_token(response); + + return response; }; const lazer_login = async (login: string, password: string): Promise => { + if (cache.v2 == '' && credentials.tokenPath != '') { + const is = token_exists(); + if (is) return; + }; + + const response = await request('https://osu.ppy.sh/oauth/token', { method: 'POST', headers: { @@ -162,6 +201,9 @@ const lazer_login = async (login: string, password: string): Promise Date: Sat, 27 Apr 2024 20:35:00 +0300 Subject: [PATCH 142/259] oopps --- utility/request.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/utility/request.ts b/utility/request.ts index 9e895be6..adcaabc5 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -101,12 +101,12 @@ export const request: RequestType = (url, { method, headers, data, params = {}, return; }; - console.log(response.statusCode, response.statusMessage, response.headers.accept, { - 'ratelimit-limit': auth.cache['ratelimit-limit'], - 'ratelimit-remaining': auth.cache['ratelimit-remaining'], - }, { - url: build_url, method, headers, data, generate_query, params, - }); // debug + // console.log(response.statusCode, response.statusMessage, response.headers.accept, { + // 'ratelimit-limit': auth.cache['ratelimit-limit'], + // 'ratelimit-remaining': auth.cache['ratelimit-remaining'], + // }, { + // url: build_url, method, headers, data, generate_query, params, + // }); // debug const chunks: any[] = []; From 32c8756d84dd74cc9e7e3d6abba40c234cf95868 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 27 Apr 2024 21:02:12 +0300 Subject: [PATCH 143/259] mods types by @YoruNoKen --- types/mods.ts | 347 ++++++++++++++++++++++++++ types/v2/matches_detaIls.ts | 6 +- types/v2/rooms_details.ts | 11 +- types/v2/rooms_list.ts | 6 +- types/v2/rooms_scores_all.ts | 4 +- types/v2/rooms_scores_single.ts | 6 +- types/v2/rooms_scores_user_highest.ts | 6 +- types/v2/scores_details.ts | 5 +- types/v2/scores_list_beatmap_all.ts | 5 +- types/v2/scores_list_beatmap_best.ts | 6 +- types/v2/scores_list_leaderboard.ts | 10 +- types/v2/scores_list_solo_scores.ts | 11 +- types/v2/scores_list_user_best.ts | 6 +- types/v2/scores_list_user_firsts.ts | 6 +- types/v2/scores_list_user_pinned.ts | 5 +- types/v2/scores_list_user_recent.ts | 5 +- types/v2/scores_user_beamap.ts | 16 +- 17 files changed, 390 insertions(+), 71 deletions(-) create mode 100644 types/mods.ts diff --git a/types/mods.ts b/types/mods.ts new file mode 100644 index 00000000..378f4cd6 --- /dev/null +++ b/types/mods.ts @@ -0,0 +1,347 @@ +interface EZ { + acronym: "EZ"; + settings?: { + retries: number; + }; +} + +interface NF { + acronym: "NF"; +} + +interface HT { + acronym: "HT"; + settings?: { + speed_change?: number; + adjust_pitch?: boolean; + }; +} + +interface DC { + acronym: "DC"; + settings?: { + speed_change: number; + }; +} + +interface HR { + acronym: "HR"; +} + +interface SD { + acronym: "SD"; + settings?: { + restart: boolean; + }; +} + +interface PF { + acronym: "PF"; + settings?: { + restart: boolean; + }; +} + +interface DT { + acronym: "DT"; + settings?: { + speed_change?: number; + adjust_pitch?: boolean; + }; +} + +interface NC { + acronym: "NC"; + settings?: { + speed_change: number; + }; +} + +interface HD { + acronym: "HD"; + settings?: { + only_fade_approach_circles: boolean; + }; +} + +interface FL { + acronym: "FL"; + settings?: { + follow_delay?: number; + size_multiplier?: number; + combo_based_size?: boolean; + }; +} + +interface BL { + acronym: "BL"; +} + +interface ST { + acronym: "ST"; +} + +interface AC { + acronym: "AC"; + settings?: { + minimum_accuracy?: number; + accuracy_judge_mode?: string; + restart?: boolean; + }; +} + +interface TP { + acronym: "TP"; + settings?: { + seed?: number; + metronome?: boolean; + }; +} + +interface DA { + acronym: "DA"; + settings?: { + circle_size?: number; + approach_rate?: number; + drain_rate?: number; + overall_difficulty?: number; + extended_limits?: boolean; + }; +} + +interface CL { + acronym: "CL"; + settings?: { + no_slider_head_accuracy?: boolean; + classic_note_lock?: boolean; + always_play_tail_sample?: boolean; + fade_hit_circle_early?: boolean; + classic_health?: boolean; + }; +} + +interface RD { + acronym: "RD"; + settings?: { + angle_sharpness?: number; + seed?: number; + }; +} + +interface MR { + acronym: "MR"; + settings?: { + reflection: string; + }; +} + +interface AL { + acronym: "AL"; +} + +interface SG { + acronym: "SG"; +} + +interface AT { + acronym: "AT"; +} + +interface CN { + acronym: "CN"; +} + +interface RX { + acronym: "RX"; +} + +interface AP { + acronym: "AP"; +} + +interface SO { + acronym: "SO"; +} + +interface TR { + acronym: "TR"; +} + +interface WG { + acronym: "WG"; + settings?: { + strength: number; + }; +} + +interface SI { + acronym: "SI"; +} + +interface GR { + acronym: "GR"; + settings?: { + start_scale: number; + }; +} + +interface DF { + acronym: "DF"; + settings?: { + start_scale: number; + }; +} + +interface WU { + acronym: "WU"; + settings?: { + initial_rate?: number; + final_rate?: number; + adjust_pitch?: boolean; + }; +} + +interface WD { + acronym: "WD"; + settings?: { + initial_rate?: number; + final_rate?: number; + adjust_pitch?: boolean; + }; +} + +interface TC { + acronym: "TC"; +} + +interface BR { + acronym: "BR"; + settings?: { + spin_speed?: number; + direction?: string; + }; +} + +interface AD { + acronym: "AD"; + settings?: { + scale?: number; + style?: string; + }; +} + +interface MU { + acronym: "MU"; + settings?: { + inverse_muting?: boolean; + enable_metronome?: boolean; + mute_combo_count?: number; + affects_hit_sounds?: boolean; + }; +} + +interface NS { + acronym: "NS"; + settings?: { + hidden_combo_count: number; + }; +} + +interface MG { + acronym: "MG"; + settings?: { + attraction_strength: number; + }; +} + +interface RP { + acronym: "RP"; + settings?: { + repulsion_strength: number; + }; +} + +interface AS { + acronym: "AS"; + settings?: { + initial_rate?: number; + adjust_pitch?: boolean; + }; +} + +interface FR { + acronym: "FR"; +} + +interface BU { + acronym: "BU"; +} + +interface SY { + acronym: "SY"; +} + +interface DP { + acronym: "DP"; + settings?: { + max_depth?: number; + show_approach_circles?: boolean; + }; +} + +interface TD { + acronym: "TD"; +} + +interface SV2 { + acronym: "SV2"; +} + +export type Mod = + | EZ + | NF + | HT + | DC + | HR + | SD + | PF + | DT + | NC + | HD + | FL + | BL + | ST + | AC + | TP + | DA + | CL + | RD + | MR + | AL + | SG + | AT + | CN + | RX + | AP + | SO + | TR + | WG + | SI + | GR + | DF + | WU + | WD + | TC + | BR + | AD + | MU + | NS + | MG + | RP + | AS + | FR + | BU + | SY + | DP + | TD + | SV2; \ No newline at end of file diff --git a/types/v2/matches_detaIls.ts b/types/v2/matches_detaIls.ts index 02b5ba8d..5bfab10f 100644 --- a/types/v2/matches_detaIls.ts +++ b/types/v2/matches_detaIls.ts @@ -1,3 +1,5 @@ +import { Mod } from "../mods" + export interface MatchesDetailsResponse { match: Match events: Event[] @@ -36,7 +38,7 @@ export interface Game { mode_int: number scoring_type: string team_type: string - mods: string[] + mods: Mod[] beatmap?: Beatmap scores: Score[] } @@ -94,7 +96,7 @@ export interface Score { max_combo: number mode: string mode_int: number - mods: string[] + mods: Mod[] passed: boolean perfect: number pp: any diff --git a/types/v2/rooms_details.ts b/types/v2/rooms_details.ts index 38271e27..6dcec2d9 100644 --- a/types/v2/rooms_details.ts +++ b/types/v2/rooms_details.ts @@ -1,3 +1,5 @@ +import { Mod } from "../mods" + export interface RoomsDetailsResponse { id: number name: string @@ -57,8 +59,8 @@ export interface Playlist { room_id: number beatmap_id: number ruleset_id: number - allowed_mods: any[] - required_mods: RequiredMod[] + allowed_mods: Mod[] + required_mods: Mod[] expired: boolean owner_id: number playlist_order?: number @@ -66,11 +68,6 @@ export interface Playlist { beatmap: Beatmap } -export interface RequiredMod { - acronym: string - settings: Settings -} - export interface Settings { } export interface Beatmap { diff --git a/types/v2/rooms_list.ts b/types/v2/rooms_list.ts index 7d40a7dd..3e251076 100644 --- a/types/v2/rooms_list.ts +++ b/types/v2/rooms_list.ts @@ -1,3 +1,5 @@ +import { Mod } from "../mods" + export interface RoomsListResponse { rooms: Room[] cursor: Cursor @@ -31,8 +33,8 @@ export interface CurrentPlaylistItem { room_id: number beatmap_id: number ruleset_id: number - allowed_mods: any[] - required_mods: any[] + allowed_mods: Mod[] + required_mods: Mod[] expired: boolean owner_id: number playlist_order: number diff --git a/types/v2/rooms_scores_all.ts b/types/v2/rooms_scores_all.ts index 8e4dee7b..6d9dcda2 100644 --- a/types/v2/rooms_scores_all.ts +++ b/types/v2/rooms_scores_all.ts @@ -1,3 +1,5 @@ +import { Mod } from "../mods" + export interface RoomsScoresAllResponse { params: Params scores: Score[] @@ -20,7 +22,7 @@ export interface Score { preserve: boolean processed: boolean maximum_statistics: MaximumStatistics - mods: any[] + mods: Mod[] statistics: Statistics beatmap_id: number best_id: any diff --git a/types/v2/rooms_scores_single.ts b/types/v2/rooms_scores_single.ts index f43a0689..c466eae4 100644 --- a/types/v2/rooms_scores_single.ts +++ b/types/v2/rooms_scores_single.ts @@ -1,3 +1,5 @@ +import { Mod } from "../mods" + export interface RoomsScoresSingleResponse { playlist_item_id: number room_id: number @@ -5,7 +7,7 @@ export interface RoomsScoresSingleResponse { ranked: boolean preserve: boolean maximum_statistics: MaximumStatistics - mods: any[] + mods: Mod[] statistics: Statistics beatmap_id: number best_id: any @@ -118,7 +120,7 @@ export interface Score { ranked: boolean preserve: boolean maximum_statistics: MaximumStatistics2 - mods: any[] + mods: Mod[] statistics: Statistics2 beatmap_id: number best_id: any diff --git a/types/v2/rooms_scores_user_highest.ts b/types/v2/rooms_scores_user_highest.ts index a9aa01ea..17ab0b87 100644 --- a/types/v2/rooms_scores_user_highest.ts +++ b/types/v2/rooms_scores_user_highest.ts @@ -1,3 +1,5 @@ +import { Mod } from "../mods" + export interface RoomScoresUserHighestResponse { playlist_item_id: number room_id: number @@ -5,7 +7,7 @@ export interface RoomScoresUserHighestResponse { ranked: boolean preserve: boolean maximum_statistics: MaximumStatistics - mods: any[] + mods: Mod[] statistics: Statistics beatmap_id: number best_id: any @@ -109,7 +111,7 @@ export interface Score { ranked: boolean preserve: boolean maximum_statistics: MaximumStatistics2 - mods: any[] + mods: Mod[] statistics: Statistics2 beatmap_id: number best_id: any diff --git a/types/v2/scores_details.ts b/types/v2/scores_details.ts index 367b3b7b..ac9231e2 100644 --- a/types/v2/scores_details.ts +++ b/types/v2/scores_details.ts @@ -1,3 +1,5 @@ +import { Mod } from "../mods" + export interface ScoresDetailsResponse { ranked: boolean preserve: boolean @@ -41,9 +43,6 @@ export interface MaximumStatistics { slider_tail_hit?: number } -export interface Mod { - acronym: string -} export interface Statistics { ok: number diff --git a/types/v2/scores_list_beatmap_all.ts b/types/v2/scores_list_beatmap_all.ts index b278fc77..2d0ed0df 100644 --- a/types/v2/scores_list_beatmap_all.ts +++ b/types/v2/scores_list_beatmap_all.ts @@ -1,3 +1,5 @@ +import { Mod } from "../mods" + export interface ScoresListBeatmapAllResponse { ranked: boolean preserve: boolean @@ -35,9 +37,6 @@ export interface MaximumStatistics { legacy_combo_increase: number } -export interface Mod { - acronym: string -} export interface Statistics { ok: number diff --git a/types/v2/scores_list_beatmap_best.ts b/types/v2/scores_list_beatmap_best.ts index 784a6eeb..cb410655 100644 --- a/types/v2/scores_list_beatmap_best.ts +++ b/types/v2/scores_list_beatmap_best.ts @@ -1,3 +1,5 @@ +import { Mod } from "../mods" + export interface ScoresListBeatmapBestResponse { position: number score: Score @@ -41,10 +43,6 @@ export interface MaximumStatistics { legacy_combo_increase: number } -export interface Mod { - acronym: string -} - export interface Statistics { ok: number great: number diff --git a/types/v2/scores_list_leaderboard.ts b/types/v2/scores_list_leaderboard.ts index fe40c3c4..dcb705df 100644 --- a/types/v2/scores_list_leaderboard.ts +++ b/types/v2/scores_list_leaderboard.ts @@ -1,3 +1,5 @@ +import { Mod } from "../mods" + export interface ScoresListLeaderboardResponse { ranked: boolean preserve: boolean @@ -38,14 +40,6 @@ export interface MaximumStatistics { slider_tail_hit?: number } -export interface Mod { - acronym: string - settings?: Settings -} - -export interface Settings { - speed_change: number -} export interface Statistics { ok?: number diff --git a/types/v2/scores_list_solo_scores.ts b/types/v2/scores_list_solo_scores.ts index 24d72854..fadad585 100644 --- a/types/v2/scores_list_solo_scores.ts +++ b/types/v2/scores_list_solo_scores.ts @@ -1,3 +1,5 @@ +import { Mod } from "../mods" + export interface ScoresListSoloScoresResponse { ranked: boolean preserve: boolean @@ -39,15 +41,6 @@ export interface MaximumStatistics { perfect?: number } -export interface Mod { - acronym: string - settings?: Settings -} - -export interface Settings { - speed_change: number -} - export interface Statistics { great?: number ignore_hit?: number diff --git a/types/v2/scores_list_user_best.ts b/types/v2/scores_list_user_best.ts index 3ede20ea..a69e135e 100644 --- a/types/v2/scores_list_user_best.ts +++ b/types/v2/scores_list_user_best.ts @@ -1,3 +1,5 @@ +import { Mod } from "../mods" + export interface ScoresListUserBestResponse { ranked: boolean preserve: boolean @@ -44,10 +46,6 @@ export interface MaximumStatistics { slider_tail_hit?: number } -export interface Mod { - acronym: string -} - export interface Statistics { ok?: number great: number diff --git a/types/v2/scores_list_user_firsts.ts b/types/v2/scores_list_user_firsts.ts index e2c38d68..b19fc79d 100644 --- a/types/v2/scores_list_user_firsts.ts +++ b/types/v2/scores_list_user_firsts.ts @@ -1,3 +1,5 @@ +import { Mod } from "../mods" + export interface ScoresListUserFirstsResponse { ranked: boolean preserve: boolean @@ -38,10 +40,6 @@ export interface MaximumStatistics { legacy_combo_increase: number } -export interface Mod { - acronym: string -} - export interface Statistics { ok?: number miss?: number diff --git a/types/v2/scores_list_user_pinned.ts b/types/v2/scores_list_user_pinned.ts index f37961fa..13ddb5c1 100644 --- a/types/v2/scores_list_user_pinned.ts +++ b/types/v2/scores_list_user_pinned.ts @@ -1,3 +1,5 @@ +import { Mod } from "../mods" + export interface ScoresListUserPinnedResponse { ranked: boolean preserve: boolean @@ -38,9 +40,6 @@ export interface MaximumStatistics { legacy_combo_increase: number } -export interface Mod { - acronym: string -} export interface Statistics { ok: number diff --git a/types/v2/scores_list_user_recent.ts b/types/v2/scores_list_user_recent.ts index 6cadcf1b..08f33c30 100644 --- a/types/v2/scores_list_user_recent.ts +++ b/types/v2/scores_list_user_recent.ts @@ -1,3 +1,5 @@ +import { Mod } from "../mods" + export interface ScoresListUserRecentResponse { ranked: boolean preserve: boolean @@ -38,9 +40,6 @@ export interface MaximumStatistics { legacy_combo_increase: number } -export interface Mod { - acronym: string -} export interface Statistics { ok: number diff --git a/types/v2/scores_user_beamap.ts b/types/v2/scores_user_beamap.ts index 1c44ece7..d23e05f8 100644 --- a/types/v2/scores_user_beamap.ts +++ b/types/v2/scores_user_beamap.ts @@ -1,3 +1,5 @@ +import { Mod } from "../mods"; + export interface ScoresUserBeatmap { ranked: boolean; maximum_statistics: MaximumStatistics; @@ -35,20 +37,6 @@ export interface MaximumStatistics { large_tick_hit?: number; } -export interface Mod { - acronym: string; - settings?: Settings; -} - -export interface Settings { - seed?: number; - angle_sharpness?: number; - drain_rate?: number; - circle_size?: number; - approach_rate?: number; - overall_difficulty?: number; -} - export interface Statistics { ok?: number; great: number; From a1b38b00d9f5a747792a7c89a4f5317bbab2e579 Mon Sep 17 00:00:00 2001 From: GabuTheDev Date: Sun, 28 Apr 2024 15:53:49 +0300 Subject: [PATCH 144/259] Add JSDoc to `v2.beatmaps` endpoints. --- routes/v2.ts | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) diff --git a/routes/v2.ts b/routes/v2.ts index 7bf615be..a5df5649 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -11,20 +11,159 @@ import { beatmaps_discussions_votes } from "../api/v2/beatmaps_discussions_votes import beatmaps_actions from "../api/v2/beatmaps_actions"; +/** + * ##### Description + * Object containing methods for retrieving beatmaps data. + */ export const beatmaps = { + /** + * ##### Description + * Covers API Endpoints regarding beatmap packs. + * + */ packs: { + /** + * ##### Description + * Request `GET` https://osu.ppy.sh/api/v2/beatmaps/packs + * + * `async` Retrieves a list of all available beatmap packs. + * + * @param type - Type of the beatmap pack. + * @param [cursor_string] - [Cursor string for pagination.](https://osu.ppy.sh/docs/index.html#cursorstring) + * @param [addons] - Additional parameters to include in the request. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ list: beatmaps_packs_list, + /** + * ##### Description + * Request `GET` https://osu.ppy.sh/api/v2/beatmaps/packs/ + * + * `async` Retrieves a beatmap pack by given ID. + * + * @param pack_tag - ID of the beatmap pack to retrieve. + * @param [addons] - Additional parameters to include in the request. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ details: beatmap_packs_details, }, + /** + * ##### Description + * Request `GET` https://osu.ppy.sh/api/v2/beatmaps/lookup + * + * `async` Lookup for a beatmap by given parameters. + * + * Check documentation for available parameters. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ lookup: beatmaps_lookup, + /** + * ##### Description + * Request `GET` https://osu.ppy.sh/api/v2/beatmaps | https://osu.ppy.sh/api/v2/beatmapsets + * + * `async` Retrieves a beatmap or beatmap set by given ID. + * + * Check documentation for available parameters. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ details: beatmaps_details, + /** + * ##### Description + * Covers API Endpoints regarding beatmap set events. + */ events: { + /** + * ##### Description + * Request `GET` https://osu.ppy.sh/api/v2/beatmapsets/events + * + * `async` Retrieves a list of beatmap set events. + * + * @param obj - Object containing parameters to include in the request. + * @param obj.user - Filter by author of the event. + * @param obj.types - Filter by type of the event. + * @param obj.min_date - Filter by minimum date of the event. + * @param obj.max_date - Filter by maximum date of the event. + * @param [addons] - Additional parameters to include in the request. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ list: beatmaps_events_list, }, + /** + * ##### Description + * + * `async` Downloads a beatmap or beatmap set by given ID. (Supports different hosts) + * + * Check documentation for available parameters. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ download: beatmaps_download, + /** + * ##### Description + * Covers API Endpoints regarding beatmap discussions. + */ discussions: { + /** + * ##### Description + * Request `GET` https://osu.ppy.sh/api/v2/beatmapsets/discussions + * + * `async` Retrieves a list of beatmap set discussions. + * + * @param params - Parameters to include in the request. + * @param [params.only_unresolved] - Filter by unresolved discussions. + * @param [params.user] - Filter by author of the discussion. + * @param [params.beatmap_id] - Filter by beatmap ID. + * @param [params.beatmapset_id] - Filter by beatmap set ID. + * @param [params.beatmapset_status] - Filter by beatmap set status. + * @param [params.message_type] - Filter by message type. + * @param [params.limit] - Maximum number of discussions to return. + * @param [params.sort] - Sort order of the discussions. + * @param [params.cursor_string] - [Cursor string for pagination.](https://osu.ppy.sh/docs/index.html#cursorstring) + * @param addons - Additional parameters to include in the request. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ list: beatmaps_discussions_list, + /** + * ##### Description + * Request `GET` https://osu.ppy.sh/api/v2/beatmapsets/discussions/posts + * + * `async` Retrieves the posts of a beatmap set discussion. + * + * @param {Object} params - Parameters to include in the request. + * @param [params.discussion_id] - ID of the beatmap set discussion to retrieve. + * @param [params.sort] - Sort order of the posts. + * @param [params.type] - Filter by type of the post. + * @param [params.limit]- Maximum number of posts to return. + * @param [params.user] - Filter by author of the post. + * @param [params.cursor_string] - [Cursor string for pagination.](https://osu.ppy.sh/docs/index.html#cursorstring) + * @param [addons] - Additional parameters to include in the request. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ posts: beatmaps_discussions_posts, + /** + * ##### Description + * Request `GET` https://osu.ppy.sh/api/v2/beatmapsets/discussions/votes + * + * `async` Retrieves the votes given to beatmap set discussions. + * + * @param params - Parameters to include in the request. + * @param [params.discussion_id] - ID of the beatmap set discussion to retrieve. + * @param [params.sort] - Sort order of the votes. + * @param [params.score] - Filter by score of the vote. + * @param [params.user] - Filter by author of the vote. + * @param [params.receiver] - Filter by receiver of the vote. + * @param [params.limit] - Maximum number of votes to return. + * @param [params.cursor_string] - [Cursor string for pagination.](https://osu.ppy.sh/docs/index.html#cursorstring) + * @param [addons] - Additional parameters to include in the request. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ votes: beatmaps_discussions_votes, }, actions: beatmaps_actions, From 2a547788e10af11975efab90f7c7eb2b411aa928 Mon Sep 17 00:00:00 2001 From: GabuTheDev Date: Sun, 28 Apr 2024 16:22:19 +0300 Subject: [PATCH 145/259] Add JSDoc to `v2.changelogs` endpoints. --- routes/v2.ts | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/routes/v2.ts b/routes/v2.ts index a5df5649..db9eec84 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -175,9 +175,35 @@ export const beatmaps = { import { changelogs_list } from '../api/v2/changelogs_list'; import { changelogs_details } from '../api/v2/changelogs_details'; - +/** + * ##### Description + * Covers API Endpoints regarding changelogs. + */ export const changelogs = { + /** + * ##### Description + * `GET` https://osu.ppy.sh/api/v2/changelogs + * + * `async` Retrieves a list of all available changelogs. + * + * Check documentation for available parameters. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ list: changelogs_list, + /** + * ##### Description + * `GET` https://osu.ppy.sh/api/v2/changelogs + * + * `async` Retrieves a changelog by given parameters. + * + * @param {Object} params - Parameters to include in the request. + * @param params.stream_name - Filter by changelog stream name. + * @param params.build_version - Filter by build version. + * @param [addons] - Additional parameters to include in the request. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ details: changelogs_details, }; From 9d04500d2ad1a78fa93573deb440e350dd6a912a Mon Sep 17 00:00:00 2001 From: GabuTheDev Date: Sun, 28 Apr 2024 16:33:37 +0300 Subject: [PATCH 146/259] Add JSDoc to `v2.comments` endpoints. --- routes/v2.ts | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/routes/v2.ts b/routes/v2.ts index db9eec84..7edb9857 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -214,10 +214,52 @@ import { comments_list } from '../api/v2/comments_list'; import { comments_details } from '../api/v2/comments_details'; import { comments_actions } from '../api/v2/comments_actions'; - +/** + * ##### Description + * Covers API Endpoints regarding comments. + */ export const comments = { + /** + * ##### Description + * `GET` https://osu.ppy.sh/api/v2/comments + * + * `async` Retrieves a list of all comments by given parameters. + * + * @param {Object} params - Parameters to include in the request. + * @param [params.type] - Filter by type of the resource to get comments from. + * @param [param.id] - Filter by ID of the resource to get comments from. + * @param [param.parent_id] - Filter by ID of the parent comment. + * @param [params.after_id] - Filter by ID of the comment after which the comments will be returned. + * @param [params.cursor.id] - The ID of the cursor. + * @param [params.cursor.created_at] - The timestamp of the cursor. + * @param [params.sort] - Sort order of the comments. + * @param [addons] - Additional parameters to include in the request. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ list: comments_list, + /** + * ##### Description + * `GET` https://osu.ppy.sh/api/v2/comments + * + * `async` Retrieves a comment by given parameters. + * + * @param comment_id - ID of the comment to retrieve. + * @param [addons] - Additional parameters to include in the request. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ details: comments_details, + /** + * ##### Description + * `PUT` `PATCH` `POST` `DELETE` https://osu.ppy.sh/api/v2/comments + * + * `async` Perform comment actions via endpoint. + * + * Check documentation for available parameters. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ actions: comments_actions, }; From 90f8da1775d950582e2ae911840234e4c416ac76 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Sun, 28 Apr 2024 17:17:12 +0300 Subject: [PATCH 147/259] Add JSDoc to `v2.users` endpoints. --- routes/v2.ts | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/routes/v2.ts b/routes/v2.ts index 7edb9857..530f093f 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -273,13 +273,95 @@ import { users_activity } from "../api/v2/users_activity"; import { users_beatmaps } from "../api/v2/users_beatmaps"; import { users_kudosu } from "../api/v2/users_kudosu"; - +/** + * ##### Description + * Covers API Endpoints regarding users. + */ export const users = { + /** + * ##### Description + * `GET` https://osu.ppy.sh/api/v2/users + * + * `async` Retrieves a list of users by given parameters. + * + * @param ids - List of user ids to retrieve. + * @param [addons] - Additional parameters to include in the request. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ list: users_list, + /** + * ##### Description + * `GET` https://osu.ppy.sh/api/v2/users/{user}/kudosu + * + * `async` Retrieves the kudosu history of a given users. + * + * @params ids - List of user ids to retrieve. + * @param [addons] - Additional parameters to include in the request. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ kudosu: users_kudosu, + /** + * ##### Description + * `GET` https://osu.ppy.sh/api/v2/events + * + * `async` Retrieves a list of user events by given parameters. + * + * @param params - Parameters to include in the request. + * @param [params.type] - Filter by type of event. + * @param [params.sort] - Sort order of the events by id. + * @param [params.cursor_string] - [Cursor string for pagination.](https://osu.ppy.sh/docs/index.html#cursorstring) + * @param [addons] - Additional parameters to include in the request. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ events: users_events, + /** + * ##### Description + * `GET` https://osu.ppy.sh/api/v2/users/ + * + * `async` Retrieves a user by given parameters. + * + * @param {Object} params - Parameters to include in the request. + * @param params.id - ID or username of the user to retrieve. + * @param [params.mode] - Retrieve data for a specific gamemode. + * @param [params.key] - Type of the `params.id` parameter. + * @param [addons] - Additional parameters to include in the request. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ details: users_details, + /** + * ##### Description + * `GET` https://osu.ppy.sh/api/v2/users/{user}/beatmapsets/ + * + * `async` Retrieves a list of user's beatmaps sets by given parameters. + * + * @param {Object} params - Parameters to include in the request. + * @param params.type - Filter by type of beatmap set. + * @param params.id - ID of the user to retrieve. + * @param [params.limit] - Maximum number of beatmap sets to return. + * @param [params.offset] - Result offset for pagination. + * @param [addons] - Additional parameters to include in the request. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ beatmaps: users_beatmaps, + /** + * ##### Description + * `GET` https://osu.ppy.sh/api/v2/users/{user}/activity + * + * `async` Retrieves a list of user's recent activities by given parameters. + * + * @param {Object} params - Parameters to include in the request. + * @param params.id - ID of the user to retrieve. + * @param [params.limit] - Maximum number of activities to return. + * @param [params.offset] - Result offset for pagination. + * @param [addons] - Additional parameters to include in the request. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ activity: users_activity, }; From d1c931f624b45b9d197b8c06d6ac0b1061c78711 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Sun, 28 Apr 2024 18:13:55 +0300 Subject: [PATCH 148/259] Add JSDoc to `v2.scores` endpoints. --- routes/v2.ts | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/routes/v2.ts b/routes/v2.ts index 530f093f..acbf6e87 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -372,10 +372,50 @@ import { scores_list } from "../api/v2/scores_list"; import { scores_details } from "../api/v2/scores_details"; import { scores_download } from "../api/v2/scores_download"; - +/** + * ##### Description + * Covers API Endpoints regarding scores. + */ export const scores = { + /** + * ##### Description + * `GET` https://osu.ppy.sh/api/v2/beatmaps/ + * + * `async` Retrieves a list of scores by given parameters. + * + * Check documentation for available parameters. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ list: scores_list, + /** + * ##### Description + * `GET` https://osu.ppy.sh/api/v2/scores/ + * + * `async` Retrieves a score by given parameters. + * + * @param {Object} params - Parameters to include in the request. + * @param params.id - ID of the score to retrieve. + * @param [params.mode] - Gamemode of the score. + * @param [addons] - Additional parameters to include in the request. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ details: scores_details, + /** + * ##### Description + * `GET` https://osu.ppy.sh/api/v2/scores/ + * + * `async` Downloads a score by given parameters. + * + * @param {Object} params - Parameters to include in the request. + * @param params.id - ID of the score to download. + * @param [params.mode] - Gamemode of the score. + * @param [params.file_path] - Where to save the file. + * @param [addons] - Additional parameters to include in the request. + * + * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + */ download: scores_download, }; From 9099a74a226eb7f13696f24a7feaaaaf5faf18d8 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Mon, 29 Apr 2024 16:49:04 +0300 Subject: [PATCH 149/259] Add JSDoc to `v2.forums` endpoints. --- routes/v2.ts | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/routes/v2.ts b/routes/v2.ts index acbf6e87..8905ffac 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -424,9 +424,100 @@ export const scores = { import { forums_topics_details } from '../api/v2/forums_topics_details'; import { forums_topics_actions } from '../api/v2/forums_topics_actions'; +/** + * ##### Description + * Covers API Endpoints regarding forums. + */ export const forums = { + /** + * ##### Description + * Covers API Endpoints regarding forum topics. + */ topics: { + /** + * ### `GET` [/v2/forums/topics](https://osu.ppy.sh/docs/index.html#get-topic-and-posts) + * `async` Retrieves a list of forum topics by given parameters. + * + *   + * + * ### Parameters + * - `params.id` - ID of the topic to retrieve. + * - `params.start_id?` - ID of the topic after which the topics will be returned. + * - `params.end_id?` - ID of the topic before which the topics will be returned. + * - `params.limit?` - Maximum number of topics to return. + * - `params.sort?` - Sort order of the topics. + * - `params.cursor_string?` - [Cursor string for pagination.](https://osu.ppy.sh/docs/index.html#cursorstring) + * - `addons?` - Additional parameters to include in the request. ([See IDefaultParams](../types/index.ts)) + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-beatmap-packs) | [Check return types](../types/v2/forums_topics_details.ts) + */ details: forums_topics_details, + /** + * ### `POST` [/v2/forums/topics](https://osu.ppy.sh/docs/index.html#create-topic) + * ### `POST` [v2/forums/topics/{topic}/reply](https://osu.ppy.sh/docs/index.html#reply-topic) + * ### `PUT/PATCH` [v2/forums/posts/{post}](https://osu.ppy.sh/docs/index.html#edit-post) + * ### `PUT/PATCH` [v2/forums/topics/{topic}](https://osu.ppy.sh/docs/index.html#edit-topic) + * + * `async` Perform actions on forum topics via API. + * + *   + * + * ### Global Parameters + * - `params.type` - Type of action to perform. + * + * ### Parameters for `params.type:'create'` + * - `params.forum_id` - ID of the forum to create the topic in. + * - `params.title` - Title of the topic. + * - `params.message` - Message of the topic. + * - `params.enable_poll` - Whether to enable the poll. + * - `params.poll.allow_vote_change?` - Whether to allow users to change their vote. + * - `params.poll.hide_results?` - Whether to hide the results of the poll. + * - `params.poll.title` - Title of the poll. + * - `params.poll.options` - Options of the poll. + * - `params.poll.max_votes_per_user?` - Maximum number of votes per user. + * - `params.poll.duration_days?` - Duration of the poll. + * + *   + * + * ### Parameters for `params.type:'reply'` + * - `params.post_id` - ID of the post to reply to. + * - `params.message` - Message of the reply. + * + *   + * + * ### Parameters for `params.type:'edit_post'` + * - `params.post_id` - ID of the post to edit. + * - `params.message` - Message of the edit. + * + *   + * + * ### Parameters for `params.type:'edit_topic'` + * - `params.topic_id?` - ID of the topic to edit. + * - `params.post_id?` - ID of the post to edit. + * - `params.title?` - New title of the topic. + * - `params.message` - New message of the topic. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * + * [See documentation](https://osu.ppy.sh/docs/index.html#forum) | [Check return types](../) + */ actions: forums_topics_actions, }, }; From 083ce4fc6ad3d12cebf0112e07f5921e6433dbb5 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 29 Apr 2024 21:22:51 +0300 Subject: [PATCH 150/259] fix mods --- tools/mods.ts | 129 ++++++++++--------------------------------------- types/enums.ts | 70 ++++++++++++++------------- 2 files changed, 61 insertions(+), 138 deletions(-) diff --git a/tools/mods.ts b/tools/mods.ts index 9c053b28..9c270e3c 100644 --- a/tools/mods.ts +++ b/tools/mods.ts @@ -6,122 +6,43 @@ import { handleErrors } from "../utility/handleErrors"; // WHILE LOOP FASTER dot +const bitValues = [ + 'NF', 'EZ', 'TD', 'HD', 'HR', 'SD', 'DT', 'RX', 'HT', 'NC', + 'FL', 'AT', 'SO', 'AP', 'PF', '4K', '5K', '6K', '7K', '8K', + 'FI', 'RD', 'CN', 'TG', '9K', '10K', '1K', '3K', '2K', 'v2' +]; + export const ModsToName = (modsNumber: number, order?: boolean): string => { - const convertedParts = []; let bit = 1; - while (bit <= modsNumber) { - switch (bit) { - case 1: - if (modsNumber & bit) convertedParts.push('NF'); - break; - case 2: - if (modsNumber & bit) convertedParts.push('EZ'); - break; - case 4: - if (modsNumber & bit) convertedParts.push('TD'); - break; - case 8: - if (modsNumber & bit) convertedParts.push('HD'); - break; - case 16: - if (modsNumber & bit) convertedParts.push('HR'); - break; - case 32: - if (modsNumber & bit) convertedParts.push('SD'); - break; - case 64: - if (modsNumber & bit) convertedParts.push('DT'); - break; - case 128: - if (modsNumber & bit) convertedParts.push('RX'); - break; - case 256: - if (modsNumber & bit) convertedParts.push('HT'); - break; - case 576: - if (modsNumber & bit) convertedParts.push('NC'); - break; - case 1024: - if (modsNumber & bit) convertedParts.push('FL'); - break; - case 2048: - if (modsNumber & bit) convertedParts.push('AT'); - break; - case 4096: - if (modsNumber & bit) convertedParts.push('SO'); - break; - case 8192: - if (modsNumber & bit) convertedParts.push('AP'); - break; - case 16416: - if (modsNumber & bit) convertedParts.push('PF'); - break; - case 32768: - if (modsNumber & bit) convertedParts.push('4K'); - break; - case 65536: - if (modsNumber & bit) convertedParts.push('5K'); - break; - case 131072: - if (modsNumber & bit) convertedParts.push('6K'); - break; - case 262144: - if (modsNumber & bit) convertedParts.push('7K'); - break; - case 524288: - if (modsNumber & bit) convertedParts.push('8K'); - break; - case 1048576: - if (modsNumber & bit) convertedParts.push('FI'); - break; - case 2097152: - if (modsNumber & bit) convertedParts.push('RD'); - break; - case 4194304: - if (modsNumber & bit) convertedParts.push('LM'); - break; - case 8388608: - if (modsNumber & bit) convertedParts.push('Target'); - break; - case 16777216: - if (modsNumber & bit) convertedParts.push('9K'); - break; - case 33554432: - if (modsNumber & bit) convertedParts.push('KeyCoop'); - break; - case 67108864: - if (modsNumber & bit) convertedParts.push('1K'); - break; - case 134217728: - if (modsNumber & bit) convertedParts.push('3K'); - break; - case 268435456: - if (modsNumber & bit) convertedParts.push('2K'); - break; - case 536870912: - if (modsNumber & bit) convertedParts.push('ScoreV2'); - break; - case 1073741824: - if (modsNumber & bit) convertedParts.push('MR'); - break; - default: - break; + if (order == true) { + const convertedParts = []; + + while (bit <= modsNumber && bit <= (1 << 30)) { + if (modsNumber & bit) { + convertedParts.push(bitValues[Math.log2(bit)]); + }; + bit <<= 1; }; + convertedParts.sort((a, b) => ModsOrder[a.toLowerCase()] - ModsOrder[b.toLowerCase()]); - bit <<= 1; + const converted = convertedParts.join(''); + return converted; }; - if (order) { - convertedParts.sort((a, b) => ModsOrder[a.toLowerCase()] - ModsOrder[b.toLowerCase()]); - }; + let convertedParts = ''; + while (bit <= modsNumber && bit <= (1 << 30)) { + if (modsNumber & bit) { + convertedParts += bitValues[Math.log2(bit)]; + } + bit <<= 1; + }; - const converted = convertedParts.join(''); - return converted; + return convertedParts; }; diff --git a/types/enums.ts b/types/enums.ts index 34c45164..6a0f251c 100644 --- a/types/enums.ts +++ b/types/enums.ts @@ -113,40 +113,42 @@ export enum ModsEnum { }; -export const ModsBitwise = { - None: 0, - NoFail: 1, - Easy: 1 << 1, - TouchDevice: 1 << 2, - Hidden: 1 << 3, - HardRock: 1 << 4, - SuddenDeath: 1 << 5, - DoubleTime: 1 << 6, - Relax: 1 << 7, - HalfTime: 1 << 8, - Nightcore: 1 << 9, // DoubleTime mod - Flashlight: 1 << 10, - Autoplay: 1 << 11, - SpunOut: 1 << 12, - Relax2: 1 << 13, // Autopilot - Perfect: 1 << 14, // SuddenDeath mod - Key4: 1 << 15, - Key5: 1 << 16, - Key6: 1 << 17, - Key7: 1 << 18, - Key8: 1 << 19, - FadeIn: 1 << 20, - Random: 1 << 21, - Cinema: 1 << 22, - Target: 1 << 23, - Key9: 1 << 24, - KeyCoop: 1 << 25, - Key1: 1 << 26, - Key3: 1 << 27, - Key2: 1 << 28, - KeyMod: 521109504, - FreeModAllowed: 522171579, - ScoreIncreaseMods: 1049662 +export enum ModsEnumBitwise { + Nomod = 0, + NoFail = 1 << 0, + Easy = 1 << 1, + TouchDevice = 1 << 2, + Hidden = 1 << 3, + HardRock = 1 << 4, + SuddenDeath = 1 << 5, + DoubleTime = 1 << 6, + Relax = 1 << 7, + HalfTime = 1 << 8, + Nightcore = 1 << 9, + Flashlight = 1 << 10, + Autoplay = 1 << 11, + SpunOut = 1 << 12, + Relax2 = 1 << 13, + Perfect = 1 << 14, + Key4 = 1 << 15, + Key5 = 1 << 16, + Key6 = 1 << 17, + Key7 = 1 << 18, + Key8 = 1 << 19, + FadeIn = 1 << 20, + Random = 1 << 21, + Cinema = 1 << 22, + Target = 1 << 23, + Key9 = 1 << 24, + Key10 = 1 << 25, + Key1 = 1 << 26, + Key3 = 1 << 27, + Key2 = 1 << 28, + LastMod = 1 << 29, + keyMod = Key1 | Key2 | Key3 | Key4 | Key5 | Key6 | Key7 | Key8 | Key9 | Key10, + KeyModUnranked = Key1 | Key2 | Key3 | Key9 | Key10, + FreeModAllowed = NoFail | Easy | Hidden | HardRock | SuddenDeath | Flashlight | FadeIn | Relax | Relax2 | SpunOut | keyMod, + ScoreIncreaseMods = Hidden | HardRock | DoubleTime | Flashlight | FadeIn }; From ea7dfb5968c87a0d1cfabbef905d622d11fbd3f8 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 29 Apr 2024 21:23:26 +0300 Subject: [PATCH 151/259] remove chimu since it's dead --- api/v2/beatmaps_download.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/v2/beatmaps_download.ts b/api/v2/beatmaps_download.ts index eb051ade..ac3c2d64 100644 --- a/api/v2/beatmaps_download.ts +++ b/api/v2/beatmaps_download.ts @@ -21,7 +21,7 @@ type params = ({ type: 'set'; id: number; - host: 'osu' | 'beatconnect' | 'chimu' | 'nerinyan' | 'osu_direct_mirror' | 'sayobot' | 'gatari' | 'ripple' | 'catboy', + host: 'osu' | 'beatconnect' | 'nerinyan' | 'osu_direct_mirror' | 'sayobot' | 'gatari' | 'ripple' | 'catboy', file_path: string; no_video?: boolean; @@ -64,9 +64,9 @@ export const beatmaps_download = async (params: T, addons?: ID if (params.type == 'set') { switch (params.host) { - case 'chimu': - url = `https://api.chimu.moe/v1/download/${params.id}`; - break; + // case 'chimu': + // url = `https://api.chimu.moe/v1/download/${params.id}`; + // break; case 'beatconnect': url = `https://beatconnect.io/b/${params.id}/`; From b052145fddfce58c8eb72564d5d9a48e5f958c5d Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 29 Apr 2024 21:27:41 +0300 Subject: [PATCH 152/259] url builder --- tools/index.ts | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/tools/index.ts b/tools/index.ts index 167a4e3d..f16efe12 100644 --- a/tools/index.ts +++ b/tools/index.ts @@ -14,6 +14,58 @@ export const calculate_pp = () => { }; +export const build_url = ({ _direct, type, mode, value }: { + _direct?: boolean; + mode: 'osu' | 'fruits' | 'mania' | 'taiko'; + + type: 'beatmap' | 'beatmapset' | 'editor_timing' | 'news' | 'match' | 'avatar' | 'user' | 'badge' | 'score' | 'beatmapset_download'; + value: any; +}) => { + switch (type) { + case 'beatmap': + return _direct == true ? `osu://b/${value}` : `https://osu.ppy.sh/b/${value}`; + + case 'beatmapset': + return _direct == true ? `osu://s/${value}` : `https://osu.ppy.sh/s/${value}`; + + + case 'news': + return `https://osu.ppy.sh/home/news/${value}`; + + + case 'editor_timing': + return `osu://edit/${value}`; + + + case 'match': + return `https://osu.ppy.sh/community/matches/${value}`; + + + case 'avatar': + return `https://a.ppy.sh/${value}`; + + case 'user': + return `https://osu.ppy.sh/users/${value}`; + + + case 'badge': + return `https://assets.ppy.sh/profile-badges/${value}`; + + + case 'score': + return `https://osu.ppy.sh/scores/${mode ? "/" + mode : ''}${value}`; + + + case 'beatmapset_download': + return `https://osu.ppy.sh/scores/${mode ? "/" + mode : ''}${value}`; + + + default: + return ''; + }; +}; + + From f5c9b9248b9c63e84db21654e6c00c04a7570005 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 29 Apr 2024 21:29:49 +0300 Subject: [PATCH 153/259] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a2632dcc..39fb4948 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.30", + "version": "3.0.0-beta.31", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", From 4d6a14ea83cf848567d8b8f49b97d090ad6c505a Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Wed, 1 May 2024 15:05:27 +0300 Subject: [PATCH 154/259] Add missing slash (/) in API path for `v2.details.actions`. --- routes/v2.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/routes/v2.ts b/routes/v2.ts index 8905ffac..7e5225f9 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -463,9 +463,9 @@ export const forums = { details: forums_topics_details, /** * ### `POST` [/v2/forums/topics](https://osu.ppy.sh/docs/index.html#create-topic) - * ### `POST` [v2/forums/topics/{topic}/reply](https://osu.ppy.sh/docs/index.html#reply-topic) - * ### `PUT/PATCH` [v2/forums/posts/{post}](https://osu.ppy.sh/docs/index.html#edit-post) - * ### `PUT/PATCH` [v2/forums/topics/{topic}](https://osu.ppy.sh/docs/index.html#edit-topic) + * ### `POST` [/v2/forums/topics/{topic}/reply](https://osu.ppy.sh/docs/index.html#reply-topic) + * ### `PUT/PATCH` [/v2/forums/posts/{post}](https://osu.ppy.sh/docs/index.html#edit-post) + * ### `PUT/PATCH` [/v2/forums/topics/{topic}](https://osu.ppy.sh/docs/index.html#edit-topic) * * `async` Perform actions on forum topics via API. * From d454bb42a4678da4b8427d5f6ca2c0b9d499f821 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Wed, 1 May 2024 15:22:14 +0300 Subject: [PATCH 155/259] Adapt `v2.beatmaps` to the new JSDoc format. (1/2) --- routes/v2.ts | 113 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 90 insertions(+), 23 deletions(-) diff --git a/routes/v2.ts b/routes/v2.ts index 7e5225f9..c5e2c07d 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -23,51 +23,118 @@ export const beatmaps = { */ packs: { /** - * ##### Description - * Request `GET` https://osu.ppy.sh/api/v2/beatmaps/packs - * + * ### `GET` [/v2/beatmaps/packs](https://osu.ppy.sh/docs/index.html#get-beatmap-packs) * `async` Retrieves a list of all available beatmap packs. * - * @param type - Type of the beatmap pack. - * @param [cursor_string] - [Cursor string for pagination.](https://osu.ppy.sh/docs/index.html#cursorstring) - * @param [addons] - Additional parameters to include in the request. + *   * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + * ## Parameters + * - `params.type` - Type of the beatmap pack. + * - `params.cusor_string?` - [Cursor string for pagination.](https://osu.ppy.sh/docs/index.html#cursorstring) + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-beatmap-packs) | [Check return types](../types/v2/beatmaps_packs_list.ts) */ list: beatmaps_packs_list, /** - * ##### Description - * Request `GET` https://osu.ppy.sh/api/v2/beatmaps/packs/ - * + * ### `GET` [/v2/beatmaps/packs/{pack_tag}](https://osu.ppy.sh/docs/index.html#get-beatmap-pack) * `async` Retrieves a beatmap pack by given ID. * - * @param pack_tag - ID of the beatmap pack to retrieve. - * @param [addons] - Additional parameters to include in the request. + *   * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + * ### Parameters + * - `pack_tag` - ID of the beatmap pack to retrieve. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-beatmap-pack) | [Check return types](../types/v2/beatmaps_packs_details.ts) */ details: beatmap_packs_details, }, /** - * ##### Description - * Request `GET` https://osu.ppy.sh/api/v2/beatmaps/lookup - * + * ### `GET` [/v2/beatmaps/lookup](https://osu.ppy.sh/docs/index.html#lookup-beatmap) + * ### `GET` [/v2/beatmapsets/lookup](https://osu.ppy.sh/docs/index.html#get-apiv2beatmapsetslookup) + * ### `POST` [/v2/beatmaps/{beatmap}/attributes](https://osu.ppy.sh/docs/index.html#get-beatmap-attributes) + * ### `GET` [/v2/beatmaps](https://osu.ppy.sh/docs/index.html#get-beatmaps) * `async` Lookup for a beatmap by given parameters. * - * Check documentation for available parameters. + *   * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + * ### Global Parameters + * - `params.type` - Type of lookup. + * + * &   + * + * ### Parameters for `params.type:'difficulty'` + * - `params.id` - ID of the difficulty to lookup for. + * - `params.checksum` - Checksum of the difficulty to lookup. + * - `params.filename` - Filename of the difficulty to lookup. + * + *   + * + * ### Parameters for `params.type:'set'` + * - `params.id` - ID of the beatmap set to lookup for. + * + *   + * + * ### Parameters for `params.type:'attribute'` + * - `params.id` - ID of the beatmap to lookup for. + * - `params.mods` - Mod combination of the beatmap to lookup for. + * - `params.mode` - Mode of the beatmap to lookup for. + * + *   + * + * ### Parameters for `params.type:'difficulties'` + * - `params.ids` - IDs of the difficulties to lookup for. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#lookup-beatmap) | [Check return types](../types/v2/beatmaps_lookup.ts) */ lookup: beatmaps_lookup, /** - * ##### Description - * Request `GET` https://osu.ppy.sh/api/v2/beatmaps | https://osu.ppy.sh/api/v2/beatmapsets - * + * ### `GET` [v2/beatmaps/{beatmap}](https://osu.ppy.sh/docs/index.html#get-beatmap) + * ### `GET` [v2/beatmapsets/{beatmapset}](https://osu.ppy.sh/docs/index.html#get-apiv2beatmapsetsbeatmapset) * `async` Retrieves a beatmap or beatmap set by given ID. * - * Check documentation for available parameters. + *   * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + * ##### Parameters + * - `params.type` - The type to search for. + * - `params.id` - The ID to search for. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-beatmap) | [Check return types](../types/v2/beatmaps_details.ts) */ details: beatmaps_details, /** From 11deec99e7da2b161bf042c357b031832354470c Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Wed, 1 May 2024 17:10:27 +0300 Subject: [PATCH 156/259] Adapt `v2.beatmaps` to the new JSDoc format. (2/2) --- routes/v2.ts | 171 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 115 insertions(+), 56 deletions(-) diff --git a/routes/v2.ts b/routes/v2.ts index c5e2c07d..282d3e50 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -134,6 +134,8 @@ export const beatmaps = { * // TBA * ``` * + *   + * * [See documentation](https://osu.ppy.sh/docs/index.html#get-beatmap) | [Check return types](../types/v2/beatmaps_details.ts) */ details: beatmaps_details, @@ -143,30 +145,57 @@ export const beatmaps = { */ events: { /** - * ##### Description - * Request `GET` https://osu.ppy.sh/api/v2/beatmapsets/events - * + * ### `GET` [v2/beatmapsets/{beatmapset}/events](https://osu.ppy.sh/docs/index.html#get-apiv2beatmapsetsevents) * `async` Retrieves a list of beatmap set events. * - * @param obj - Object containing parameters to include in the request. - * @param obj.user - Filter by author of the event. - * @param obj.types - Filter by type of the event. - * @param obj.min_date - Filter by minimum date of the event. - * @param obj.max_date - Filter by maximum date of the event. - * @param [addons] - Additional parameters to include in the request. + *   * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + * ### Parameters + * - `obj.user` - Filter by author of the event. + * - `obj.types` - Filter by type of the event. + * - `obj.min_date` - Filter by minimum date of the event. + * - `obj.max_date` - Filter by maximum date of the event. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2beatmapsetsevents) | [Check return types](../types/v2/beatmaps_events_list.ts) */ list: beatmaps_events_list, }, /** - * ##### Description - * * `async` Downloads a beatmap or beatmap set by given ID. (Supports different hosts) * - * Check documentation for available parameters. + *   * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + * ### Available hosts + * - `type:'difficulty'`: osu, osu_direct_mirror, catboy + * - `type:'set'`: osu, beatconnect, nerinyan, osu_direct_mirror, sayobot, gatari, ripple, catboy + * + *   + * + * ### Global Parameters + * - `params.type` - Type of the beatmap. + * - `params.id` - ID of the beatmap or beatmap set. + * - `params.host` - Host of the download source. + * - `params.file_path` - Path to the save location. + * - `params.overwrite` - Whether to overwrite the file if it already exists. + * + *   + * + * ### Parameters for `params.type:'set'` + * - `params.no_video?` - Whether to include video in the download. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2beatmapsetsbeatmapsetdownload) | [Check return types](../types/v2/beatmaps_download.ts) */ download: beatmaps_download, /** @@ -175,64 +204,94 @@ export const beatmaps = { */ discussions: { /** - * ##### Description - * Request `GET` https://osu.ppy.sh/api/v2/beatmapsets/discussions - * + * ### `GET` [/v2/beatmapsets/discussions`](https://osu.ppy.sh/docs/index.html#get-beatmapset-discussions) * `async` Retrieves a list of beatmap set discussions. * - * @param params - Parameters to include in the request. - * @param [params.only_unresolved] - Filter by unresolved discussions. - * @param [params.user] - Filter by author of the discussion. - * @param [params.beatmap_id] - Filter by beatmap ID. - * @param [params.beatmapset_id] - Filter by beatmap set ID. - * @param [params.beatmapset_status] - Filter by beatmap set status. - * @param [params.message_type] - Filter by message type. - * @param [params.limit] - Maximum number of discussions to return. - * @param [params.sort] - Sort order of the discussions. - * @param [params.cursor_string] - [Cursor string for pagination.](https://osu.ppy.sh/docs/index.html#cursorstring) - * @param addons - Additional parameters to include in the request. - * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + *   + * + * ### Parameters + * - `params.only_unresolved?` - Filter by unresolved discussions. + * - `params.user?` - Filter by author of the discussion. + * - `params.beatmap_id?` - Filter by beatmap ID. + * - `params.beatmapset_id?` - Filter by beatmap set ID. + * - `params.beatmapset_status?` - Filter by beatmap set status. + * - `params.message_type?` - Filter by message type. + * - `params.limit?` - Maximum number of discussions to return. + * - `params.sort?` - Sort order of the discussions. + * - `params.cursor_string?` - [Cursor string for pagination.](https://osu.ppy.sh/docs/index.html#cursorstring) + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-beatmapset-discussions) | [Check return types](../types/v2/beatmaps_discussions_list.ts) */ list: beatmaps_discussions_list, /** - * ##### Description - * Request `GET` https://osu.ppy.sh/api/v2/beatmapsets/discussions/posts - * + * ### `GET` [/v2/beatmapsets/discussions/posts](https://osu.ppy.sh/docs/index.html#beatmapset-discussions) * `async` Retrieves the posts of a beatmap set discussion. * - * @param {Object} params - Parameters to include in the request. - * @param [params.discussion_id] - ID of the beatmap set discussion to retrieve. - * @param [params.sort] - Sort order of the posts. - * @param [params.type] - Filter by type of the post. - * @param [params.limit]- Maximum number of posts to return. - * @param [params.user] - Filter by author of the post. - * @param [params.cursor_string] - [Cursor string for pagination.](https://osu.ppy.sh/docs/index.html#cursorstring) - * @param [addons] - Additional parameters to include in the request. + *   + * + * ### Parameters + * - `params.discussion_id?` - ID of the beatmap set discussion to retrieve. + * - `params.sort?` - Sort order of the posts. + * - `params.type?` - Filter by type of the post. + * - `params.limit?` - Maximum number of posts to return. + * - `params.user?` - Filter by author of the post. + * - `params.cursor_string?` - [Cursor string for pagination.](https://osu.ppy.sh/docs/index.html#cursorstring) + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + * [See documentation](https://osu.ppy.sh/docs/index.html#beatmapset-discussions) | [Check return types](../types/v2/beatmaps_discussions_posts.ts) */ posts: beatmaps_discussions_posts, /** - * ##### Description - * Request `GET` https://osu.ppy.sh/api/v2/beatmapsets/discussions/votes - * + * ### `GET` [/v2/beatmapsets/discussions/votes](https://osu.ppy.sh/docs/index.html#get-beatmapset-discussion-votes) * `async` Retrieves the votes given to beatmap set discussions. * - * @param params - Parameters to include in the request. - * @param [params.discussion_id] - ID of the beatmap set discussion to retrieve. - * @param [params.sort] - Sort order of the votes. - * @param [params.score] - Filter by score of the vote. - * @param [params.user] - Filter by author of the vote. - * @param [params.receiver] - Filter by receiver of the vote. - * @param [params.limit] - Maximum number of votes to return. - * @param [params.cursor_string] - [Cursor string for pagination.](https://osu.ppy.sh/docs/index.html#cursorstring) - * @param [addons] - Additional parameters to include in the request. - * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + *   + * + * ### Parameters + * - `params.discussion_id?` - ID of the beatmap set discussion to retrieve. + * - `params.sort?` - Sort order of the votes. + * - `params.score?` - Filter by score of the vote. + * - `params.user?` - Filter by author of the vote. + * - `params.receiver?` - Filter by receiver of the vote. + * - `params.limit?` - Maximum number of votes to return. + * - `params.cursor_string?` - [Cursor string for pagination.](https://osu.ppy.sh/docs/index.html#cursorstring) + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-beatmapset-discussion-votes) | [Check return types](../types/v2/beatmaps_discussions_votes.ts) */ votes: beatmaps_discussions_votes, }, + /** + * Currently broken. + */ actions: beatmaps_actions, }; From 23fc5718616ea7b0f20365f70fdc80da7bc4b87a Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Mon, 13 May 2024 23:36:55 +0300 Subject: [PATCH 157/259] Adapt `v2.changelogs` to the new JSDoc format. --- routes/v2.ts | 62 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/routes/v2.ts b/routes/v2.ts index 282d3e50..449be595 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -307,28 +307,64 @@ import { changelogs_details } from '../api/v2/changelogs_details'; */ export const changelogs = { /** - * ##### Description - * `GET` https://osu.ppy.sh/api/v2/changelogs - * + * ### `GET` [/v2/changelogs](https://osu.ppy.sh/docs/index.html#get-changelog-listing) + * ### `GET` [/v2/changelogs/{changelog}](https://osu.ppy.sh/docs/index.html#lookup-changelog-build) * `async` Retrieves a list of all available changelogs. * - * Check documentation for available parameters. + *   * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + * ### Global Parameters + * - `params.type` - Fetch type. + * - `params.message_formats` - Return format. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Parameters for `type:'all'` + * - `params.from_build?` - Minimum build version. + * - `params.to_build?` - Maximum build version. + * - `params.stream_name?` - Stream name to return builds from. + * - `params.max_id?` - Maximum build ID. + * + *   + * + * ### Parameters for `type:'lookup'` + * - `params.changelog` - Build version, update stream name, or build ID. + * - `params.key` - Unset to query by build version or stream name, or id to query by build ID. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-changelog-listing) | [Check return types](../types/v2/changelogs_list.ts) */ list: changelogs_list, /** - * ##### Description - * `GET` https://osu.ppy.sh/api/v2/changelogs + * ### `GET` [/v2/changelog/{stream}/{build}](https://osu.ppy.sh/docs/index.html#get-changelog-build) + * `async` Retrieves details of the specified build. * - * `async` Retrieves a changelog by given parameters. + *   * - * @param {Object} params - Parameters to include in the request. - * @param params.stream_name - Filter by changelog stream name. - * @param params.build_version - Filter by build version. - * @param [addons] - Additional parameters to include in the request. + * ### Parameters + * - `params.stream_name` - Update stream name. + * - `params.build_version` - Build version. + * - `addons?` - Additional parameters to include in the request. * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-changelog-build) | [Check return types](../types/v2/changelogs_details.ts) */ details: changelogs_details, }; From 98e3fec68a7f384b14a3e06239f2430516da0b82 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Tue, 14 May 2024 00:01:18 +0300 Subject: [PATCH 158/259] Adapt `v2.comments` to the new JSDoc format. --- routes/v2.ts | 96 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 72 insertions(+), 24 deletions(-) diff --git a/routes/v2.ts b/routes/v2.ts index 449be595..e034798e 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -382,45 +382,93 @@ import { comments_actions } from '../api/v2/comments_actions'; */ export const comments = { /** - * ##### Description - * `GET` https://osu.ppy.sh/api/v2/comments - * + * ### `GET` [/v2/comments](https://osu.ppy.sh/api/v2/comments) * `async` Retrieves a list of all comments by given parameters. * - * @param {Object} params - Parameters to include in the request. - * @param [params.type] - Filter by type of the resource to get comments from. - * @param [param.id] - Filter by ID of the resource to get comments from. - * @param [param.parent_id] - Filter by ID of the parent comment. - * @param [params.after_id] - Filter by ID of the comment after which the comments will be returned. - * @param [params.cursor.id] - The ID of the cursor. - * @param [params.cursor.created_at] - The timestamp of the cursor. - * @param [params.sort] - Sort order of the comments. - * @param [addons] - Additional parameters to include in the request. + *   * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + * ### Parameters + * - `params.type?` - Type of the resource to get comments from. + * - `params.id?` - ID of the resource to get comments from. + * - `params.parent_id?` - ID of the parent comment. + * - `params.after_id?` - ID of the comment after which the comments will be returned. + * - `params.cursor?.id`- The ID of the cursor. + * - `params.cursor?.created_at` - The timestamp of the cursor. + * - `params.sort?` - Sort order of the comments. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-comments-listing) | [Check return types](../types/v2/comments_list.ts) */ list: comments_list, /** - * ##### Description - * `GET` https://osu.ppy.sh/api/v2/comments - * + * ### `GET` [/v2/comments/{comment}](https://osu.ppy.sh/docs/index.html#get-a-comment) * `async` Retrieves a comment by given parameters. * - * @param comment_id - ID of the comment to retrieve. - * @param [addons] - Additional parameters to include in the request. + *   * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + * ### Parameters + * - `params.comment_id` - ID of the comment to retrieve. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-a-comment) | [Check return types](../types/v2/comments_details.ts) */ details: comments_details, /** - * ##### Description - * `PUT` `PATCH` `POST` `DELETE` https://osu.ppy.sh/api/v2/comments - * + * ### `POST` [/v2/comments](https://osu.ppy.sh/docs/index.html#post-a-new-comment) + * ### `PUT` [/v2/comments/{comment}](https://osu.ppy.sh/docs/index.html#edit-comment) + * ### `PATCH` [/v2/comments/{comment}](https://osu.ppy.sh/docs/index.html#edit-comment) + * ### `DELETE` [/v2/comments/{comment}](https://osu.ppy.sh/docs/index.html#delete-comment) + * ### `POST` [/v2/comments/{comment}/vote](https://osu.ppy.sh/docs/index.html#add-comment-vote) + * ### `DELETE` [/v2/comments/{comment}/vote](https://osu.ppy.sh/docs/index.html#remove-comment-vote) * `async` Perform comment actions via endpoint. * - * Check documentation for available parameters. + *   * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + * ### Global Parameters + * - `params.id?` - ID of the comment to perform the action on. + * - `params.type` - Type of the action to perform. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Parameters for `params.type:'new'` + * - `params.message?` - The message of the comment. + * - `params.parent_id?` - The id of the comment to reply to. + * - `params.commentable_type?` - Resource type the comment thread is attached to. + * + *   + * + * ### Parameters for `params.type:'edit'` + * - `params.message?` - The message of the comment. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#post-a-new-comment) | [Check return types](../types/v2/comments_actions.ts) */ actions: comments_actions, }; From 9f7c5c8de1c2cdc401d4b775b1dcfdefc13db9d0 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Tue, 14 May 2024 18:23:30 +0300 Subject: [PATCH 159/259] fix save token --- package.json | 2 +- utility/auth.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 39fb4948..7000c44a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.31", + "version": "3.0.0-beta.32", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/utility/auth.ts b/utility/auth.ts index bc52b76f..bd9e28f2 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -133,6 +133,8 @@ const token_exists = () => { const save_token = (response: auth_response) => { + if (!credentials.tokenPath) return; + const { dir } = path.parse(credentials.tokenPath); if (fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); From fe56176af0cd6dcbf1e493658931995e0b6c85b4 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Tue, 14 May 2024 18:23:47 +0300 Subject: [PATCH 160/259] remove old --- src/api/v2/routes/beatmap/set/download.ts | 83 ------- src/api/v2/routes/scores/details.ts | 41 ---- src/api/v2/routes/scores/user/category.ts | 100 -------- src/api/v2/routes/site/ranking/details.ts | 80 ------- src/api/v2/routes/users/events.ts | 67 ------ src/types/mods.ts | 51 ---- src/types/v2_beatmap_set_download.ts | 30 --- src/types/v2_room_details.ts | 140 ----------- src/types/v2_room_leaderboard.ts | 140 ----------- src/types/v2_rooms_list.ts | 134 ----------- src/types/v2_scores_details.ts | 165 ------------- src/types/v2_scores_user_beatmap.ts | 66 ----- src/types/v2_scores_user_category.ts | 143 ----------- src/types/v2_site_ranking_details.ts | 188 --------------- src/types/v2_user_me_download_quota.ts | 278 ---------------------- src/utility/auth.ts | 204 ---------------- src/utility/request.ts | 191 --------------- src/utility/types.ts | 23 -- 18 files changed, 2124 deletions(-) delete mode 100644 src/api/v2/routes/beatmap/set/download.ts delete mode 100644 src/api/v2/routes/scores/details.ts delete mode 100644 src/api/v2/routes/scores/user/category.ts delete mode 100644 src/api/v2/routes/site/ranking/details.ts delete mode 100644 src/api/v2/routes/users/events.ts delete mode 100644 src/types/mods.ts delete mode 100644 src/types/v2_beatmap_set_download.ts delete mode 100644 src/types/v2_room_details.ts delete mode 100644 src/types/v2_room_leaderboard.ts delete mode 100644 src/types/v2_rooms_list.ts delete mode 100644 src/types/v2_scores_details.ts delete mode 100644 src/types/v2_scores_user_beatmap.ts delete mode 100644 src/types/v2_scores_user_category.ts delete mode 100644 src/types/v2_site_ranking_details.ts delete mode 100644 src/types/v2_user_me_download_quota.ts delete mode 100644 src/utility/auth.ts delete mode 100644 src/utility/request.ts delete mode 100644 src/utility/types.ts diff --git a/src/api/v2/routes/beatmap/set/download.ts b/src/api/v2/routes/beatmap/set/download.ts deleted file mode 100644 index d39d75bd..00000000 --- a/src/api/v2/routes/beatmap/set/download.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { types } from '../../../../../types/v2_beatmap_set_download'; -import { Description } from '../../../../../utility/types'; - -import { download } from "../../../../../utility/request"; - - -export const description: Description = { - auth: 0, - title: __filename, - method: 'GET', - description: 'Download beatmap set to specified directory', - params: [ - { - type: 'number', - name: 'beatmapset', - optional: false, - description: 'id of the beatmap set', - }, - { - type: 'string', - name: 'file_path', - optional: false, - description: 'path to file with their name and extension', - }, - { - type: 'string', - name: 'host_name', - optional: false, - description: '\`\`\`osu\`\`\` or \`\`\`chimu\`\`\` or \`\`\`beatconnect\`\`\` or \`\`\`sayobot\`\`\` or \`\`\`nerinyan\`\`\` or ', - }, - { - type: 'boolean', - name: 'no_video', - optional: false, - description: 'Download with or without video', - }, - { - type: 'Function', - name: 'callback', - optional: true, - description: 'function which is will be triggered on downloading progress', - }, - ], - return: 'string', -}; - - -const name: types = async (beatmapset, file_path, host_name, no_video, callback) => { - const url = (() => { - switch (host_name) { - case 'osu': - return `https://osu.ppy.sh/api/v2/beatmapsets/${beatmapset}/download${no_video ? '?noVideo=1' : ''}`; - - case 'chimu': - return `https://chimu.moe/v1/download/${beatmapset}`; - - case 'beatconnect': - return `https://beatconnect.io/b/${beatmapset}/`; - - case 'sayobot': - return `https://dl.sayobot.cn/beatmaps/download/${no_video ? 'novideo' : 'full'}/${beatmapset}`; - - case 'nerinyan': - return `https://api.nerinyan.moe/d/${beatmapset}${no_video ? '?nv=1' : ''}`; - - case 'mino': - return `https://catboy.best/d/${beatmapset}${no_video ? "n" : ""}`; - - default: - return `https://osu.ppy.sh/api/v2/beatmapsets/${beatmapset}/download${no_video ? '?noVideo=1' : ''}`; - }; - })(); - - const data = await download(url, file_path, { - headers: { - "Referer": "https://osu.ppy.sh/", - } - }, callback); - return data; -}; - - -export default name; diff --git a/src/api/v2/routes/scores/details.ts b/src/api/v2/routes/scores/details.ts deleted file mode 100644 index e9a88c59..00000000 --- a/src/api/v2/routes/scores/details.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { types } from '../../../../types/v2_scores_details'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return data for a score', - params: [ - { - type: 'number', - name: 'score_id', - optional: false, - description: 'id of the score', - }, - { - type: 'string', - name: 'mode', - optional: false, - description: '\`\`\`osu\`\`\` or \`\`\`fruits\`\`\` or \`\`\`mania\`\`\` or \`\`\`taiko\`\`\`', - }, - ], - return: 'response', -}; - - -const name: types = async (score_id, mode) => { - const data = await request(`scores/${score_id}`, { - method: 'GET', - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/scores/user/category.ts b/src/api/v2/routes/scores/user/category.ts deleted file mode 100644 index e5b3934c..00000000 --- a/src/api/v2/routes/scores/user/category.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { types, response } from '../../../../../types/v2_scores_user_category'; -import { id as mods_id } from '../../../../../utility/mods'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return list of user scores on a beatmap', - imports: [ - 'mods' - ], - params: [ - { - type: 'number', - name: 'user', - optional: false, - description: 'id of the user', - }, - { - type: 'string', - name: 'type', - optional: false, - description: '\`\`\`recent\`\`\` or \`\`\`best\`\`\` or \`\`\`firsts\`\`\` or \`\`\`pinned\`\`\`', - }, - { - name: 'object', - params: [ - { - type: 'boolean', - name: 'include_fails', - options: false, - optional: true, - description: 'Only for \`\`\`recent\`\`\` scores, include scores of failed plays. Set to \`\`\`true\`\`\` to include them. Defaults to \`\`\`false\`\`\`', - }, - { - type: 'string', - name: 'mode', - optional: true, - description: '\`\`\`osu\`\`\` or \`\`\`fruits\`\`\` or \`\`\`mania\`\`\` or \`\`\`taiko\`\`\`', - }, - { - type: 'number', - name: 'mods', - options: false, - optional: true, - description: 'Use \`\`\`mods.enums\`\`\` instead of mods id or name', - }, - { - type: 'number', - name: 'limit', - optional: true, - description: 'Maximum number of results', - }, - { - type: 'string', - name: 'offset', - optional: true, - description: 'Result offset for pagination', - }, - ] - }, - ], -}; - - -const name: types = async (user, type, obj) => { - // @ts-ignore - if (obj.include_fails) obj.include_fails = obj.include_fails == true ? 1 : 0; - - const data: response[] = await request(`users/${user}/scores/${type}`, { - method: 'GET', - params: obj, - }); - - if (Array.isArray(data)) { - const transform = data.map((v, i) => { - const id = v.mods.map(r => r.acronym).filter(r => r != 'CL').join(''); - - return { - position: i + 1, - mods_id: mods_id(id) || 0, - ...v - }; - }); - - if (obj.mods) return transform.filter(r => (r.mods_id & obj.mods) > 0); - return transform; - }; - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/site/ranking/details.ts b/src/api/v2/routes/site/ranking/details.ts deleted file mode 100644 index 76303b46..00000000 --- a/src/api/v2/routes/site/ranking/details.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { types } from '../../../../../types/v2_site_ranking_details'; -import { Description } from '../../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Gets the current ranking leaderboard for the specified type and game mode', - params: [ - { - type: 'string', - name: 'mode', - optional: false, - description: '\`\`\`osu\`\`\` or \`\`\`fruits\`\`\` or \`\`\`mania\`\`\` or \`\`\`taiko\`\`\`', - }, - { - type: 'string', - name: 'type', - optional: false, - description: '\`\`\`charts\`\`\` or \`\`\`country\`\`\` or \`\`\`performance\`\`\` or \`\`\`score\`\`\`', - }, - { - name: 'object', - optional: true, - params: [ - { - type: 'string', - name: 'country', - options: false, - optional: true, - description: 'Filter ranking by country code. Only available for \`\`\`type\`\`\` of \`\`\`performance\`\`\`', - }, - { - type: 'number', - name: 'cursor[page]', - optional: true, - description: 'Page number', - }, - { - type: 'string', - name: 'filter', - optional: true, - description: '\`\`\`all\`\`\` or \`\`\`friends\`\`\`', - }, - { - type: 'string', - name: 'spotlight', - optional: true, - description: 'The id of the spotlight if type is charts. Ranking for latest spotlight will be returned if not specified', - }, - { - type: 'string', - name: 'variant', - options: false, - optional: true, - description: `Filter ranking to specified mode variant. For \`\`\`mode\`\`\` of \`\`\`mania\`\`\`, it's either \`\`\`4k\`\`\` or \`\`\`7k\`\`\`. Only available for \`\`\`type\`\`\` of \`\`\`performance\`\`\``, - }, - ] - }, - ], - return: 'response', -}; - - -const name: types = async (mode, type, obj) => { - const data = await request(`rankings/${mode}/${type}`, { - method: 'GET', - params: obj, - }); - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/api/v2/routes/users/events.ts b/src/api/v2/routes/users/events.ts deleted file mode 100644 index 84a9ccc5..00000000 --- a/src/api/v2/routes/users/events.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { types, response } from '../../../../types/v2_users_events'; -import { Description } from '../../../../utility/types'; - - -import { namespace, RequestNamespace } from "../../../../utility/request"; -const request: RequestNamespace = namespace('https://osu.ppy.sh/api/v2/'); - -export const description: Description = { - auth: 1, - title: __filename, - method: 'GET', - description: 'Return list of events in order of creation time', - params: [ - { - name: 'object', - optional: true, - params: [ - { - type: 'string', - name: 'sort', - optional: true, - description: '\`\`\`id_desc\`\`\` or \`\`\`id_asc\`\`\`', - }, - { - type: 'string', - name: 'cursor_string', - optional: true, - description: 'Parameter for pagination', - }, - { - type: 'string[]', - name: 'type', - optional: true, - description: '\`\`\`achievement\`\`\` or \`\`\`beatmapPlaycount\`\`\` or \`\`\`beatmapsetApprove\`\`\` or \`\`\`beatmapsetDelete\`\`\` or \`\`\`beatmapsetRevive\`\`\` or \`\`\`beatmapsetUpdate\`\`\` or \`\`\`beatmapsetUpload\`\`\` or \`\`\`rank\`\`\` or \`\`\`userSupportAgain\`\`\` or \`\`\`userSupportFirst\`\`\` or \`\`\`userSupportGift\`\`\` or \`\`\`usernameChange\`\`\`', - } - ] - }, - ], - return: 'response', -}; - - -const name: types = async (object) => { - const params: any = {}; - if (object?.sort) params.sort = object.sort; - if (object?.cursor_string) params.cursor_string = object.cursor_string; - - - const data: response = await request(`events`, { - method: 'GET', - params: params, - }); - - - if (object?.type != null) { - if (!Array.isArray(object.type)) throw new Error('Event Type must be an Array of options'); - - const sorted = data.events.filter(r => object.type.includes(r.type as any)); - data.events = sorted; - }; - - - return data; -}; - - -export default name; \ No newline at end of file diff --git a/src/types/mods.ts b/src/types/mods.ts deleted file mode 100644 index dcb59dd8..00000000 --- a/src/types/mods.ts +++ /dev/null @@ -1,51 +0,0 @@ -export interface Mod { - acronym: string - settings?: Settings; -} - -export interface Settings { - retries?: number; - speed_change?: number; - adjust_pitch?: boolean; - restart?: boolean; - only_fade_approach_circles?: boolean; - follow_delay?: number; - size_multiplier?: number; - combo_based_size?: boolean; - minimum_accuracy?: number; - accuracy_judge_mode?: string; - seed?: number; - metronome?: boolean; - circle_size?: number; - approach_rate?: number; - drain_rate?: number; - overall_difficulty?: number; - extended_limits?: boolean; - no_slider_head_accuracy?: boolean; - classic_note_lock?: boolean; - always_play_tail_sample?: boolean; - fade_hit_circle_early?: boolean; - classic_health?: boolean; - angle_sharpness?: number; - reflection?: string; - strength?: number; - start_scale?: number; - initial_rate?: number; - final_rate?: number; - spin_speed?: number; - direction?: string; - scale?: number; - style?: string; - inverse_muting?: boolean; - enable_metronome?: boolean; - mute_combo_count?: number; - affects_hit_sounds?: boolean; - hidden_combo_count?: number; - attraction_strength?: number; - repulsion_strength?: number; - max_depth?: number; - show_approach_circles?: boolean; - scroll_speed?: number; - hard_rock_offsets?: boolean; - coverage?: number; -} \ No newline at end of file diff --git a/src/types/v2_beatmap_set_download.ts b/src/types/v2_beatmap_set_download.ts deleted file mode 100644 index b714b569..00000000 --- a/src/types/v2_beatmap_set_download.ts +++ /dev/null @@ -1,30 +0,0 @@ -export interface response { -} - - -export interface types { - /** - * Download beatmap set to specified directory - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login_lazer(USERNAME, USER_PASSWORD); - * - * const v2_beatmap_set_download = await v2.beatmap.set.download(beatmapset, file_path, host_name, no_video, callback); - * console.log(v2_beatmap_set_download); - * }; - * - * main(); - * ``` - * @param {number} beatmapset id of the beatmap set - * @param {string} file_path path to file with their name and extension - * @param {string} host_name ```osu``` or ```chimu``` or ```beatconnect``` or ```sayobot``` or ```nerinyan``` or - * @param {boolean} no_video Download with or without video - * @param {Function} callback function which is will be triggered on downloading progress - */ - (beatmapset: number, file_path: string, host_name: 'osu' | 'chimu' | 'beatconnect' | 'sayobot' | 'nerinyan' | 'mino' | '', no_video: boolean, callback?: Function): Promise; -} diff --git a/src/types/v2_room_details.ts b/src/types/v2_room_details.ts deleted file mode 100644 index 113735da..00000000 --- a/src/types/v2_room_details.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { Mod } from "./mods"; - -export interface response { - id: number; - name: string; - category: string; - type: string; - user_id: number; - starts_at: string; - ends_at: string; - max_attempts: string; - participant_count: number; - channel_id: number; - active: boolean; - has_password: boolean; - queue_mode: string; - auto_skip: boolean; - current_user_score: { - accuracy: number; - attempts: number; - completed: number; - pp: number; - room_id: number; - total_score: number; - user_id: number; - playlist_item_attempts: []; - }; - host: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour: string; - username: string; - country: { - code: string; - name: string; - }; - }; - playlist: { - id: number; - room_id: number; - beatmap_id: number; - ruleset_id: number; - allowed_mods: Mod[]; - required_mods: []; - expired: boolean; - owner_id: number; - playlist_order?: string; - played_at?: string; - beatmap: { - beatmapset_id: number; - difficulty_rating: number; - id: number; - mode: string; - status: string; - total_length: number; - user_id: number; - version: string; - beatmapset: { - artist: string; - artist_unicode: string; - covers: { - cover: string; - 'cover@2x': string; - card: string; - 'card@2x': string; - list: string; - 'list@2x': string; - slimcover: string; - 'slimcover@2x': string; - }; - creator: string; - favourite_count: number; - hype: string; - id: number; - nsfw: boolean; - offset: number; - play_count: number; - preview_url: string; - source: string; - spotlight: boolean; - status: string; - title: string; - title_unicode: string; - track_id: number; - user_id: number; - video: boolean; - }; - checksum: string; - max_combo: number; - }; - }[]; - recent_participants: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit?: string; - pm_friends_only: boolean; - profile_colour?: string; - username: string; - }[]; -} - - -export interface types { - /** - * - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_room_details = await v2.room.details(room_id); - * console.log(v2_room_details); - * }; - * - * main(); - * ``` - * @param {number} room_id Id of the room - */ - (room_id: number): Promise; -} diff --git a/src/types/v2_room_leaderboard.ts b/src/types/v2_room_leaderboard.ts deleted file mode 100644 index 514cba99..00000000 --- a/src/types/v2_room_leaderboard.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { Mod } from "./mods"; - -export interface response { - id: number; - name: string; - category: string; - type: string; - user_id: number; - starts_at: string; - ends_at: string; - max_attempts: string; - participant_count: number; - channel_id: number; - active: boolean; - has_password: boolean; - queue_mode: string; - auto_skip: boolean; - current_user_score: { - accuracy: number; - attempts: number; - completed: number; - pp: number; - room_id: number; - total_score: number; - user_id: number; - playlist_item_attempts: []; - }; - host: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour: string; - username: string; - country: { - code: string; - name: string; - }; - }; - playlist: { - id: number; - room_id: number; - beatmap_id: number; - ruleset_id: number; - allowed_mods: Mod[]; - required_mods: []; - expired: boolean; - owner_id: number; - playlist_order?: string; - played_at?: string; - beatmap: { - beatmapset_id: number; - difficulty_rating: number; - id: number; - mode: string; - status: string; - total_length: number; - user_id: number; - version: string; - beatmapset: { - artist: string; - artist_unicode: string; - covers: { - cover: string; - 'cover@2x': string; - card: string; - 'card@2x': string; - list: string; - 'list@2x': string; - slimcover: string; - 'slimcover@2x': string; - }; - creator: string; - favourite_count: number; - hype: string; - id: number; - nsfw: boolean; - offset: number; - play_count: number; - preview_url: string; - source: string; - spotlight: boolean; - status: string; - title: string; - title_unicode: string; - track_id: number; - user_id: number; - video: boolean; - }; - checksum: string; - max_combo: number; - }; - }[]; - recent_participants: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit?: string; - pm_friends_only: boolean; - profile_colour?: string; - username: string; - }[]; -} - - -export interface types { - /** - * Return leaderboard of room - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_room_leaderboard = await v2.room.leaderboard(room_id); - * console.log(v2_room_leaderboard); - * }; - * - * main(); - * ``` - * @param {number} room_id Id of the room - */ - (room_id: number): Promise; -} diff --git a/src/types/v2_rooms_list.ts b/src/types/v2_rooms_list.ts deleted file mode 100644 index eed4fd22..00000000 --- a/src/types/v2_rooms_list.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { Mod } from "./mods"; - -export interface response { - id: number; - name: string; - category: string; - type: string; - user_id: number; - starts_at: string; - ends_at: string; - max_attempts: string; - participant_count: number; - channel_id: number; - active: boolean; - has_password: boolean; - queue_mode: string; - auto_skip: boolean; - host: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour: string; - username: string; - country: { - code: string; - name: string; - }; - }; - playlist: { - id: number; - room_id: number; - beatmap_id: number; - ruleset_id: number; - allowed_mods: Mod[]; - required_mods: []; - expired: boolean; - owner_id: number; - playlist_order?: string; - played_at?: string; - beatmap: { - beatmapset_id: number; - difficulty_rating: number; - id: number; - mode: string; - status: string; - total_length: number; - user_id: number; - version: string; - beatmapset: { - artist: string; - artist_unicode: string; - covers: { - cover: string; - 'cover@2x': string; - card: string; - 'card@2x': string; - list: string; - 'list@2x': string; - slimcover: string; - 'slimcover@2x': string; - }; - creator: string; - favourite_count: number; - hype: string; - id: number; - nsfw: boolean; - offset: number; - play_count: number; - preview_url: string; - source: string; - spotlight: boolean; - status: string; - title: string; - title_unicode: string; - track_id: number; - user_id: number; - video: boolean; - }; - checksum: string; - max_combo: number; - }; - }[]; - recent_participants: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit?: string; - pm_friends_only: boolean; - profile_colour?: string; - username: string; - }[]; -} - - -export interface types { - /** - * - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_rooms_list = await v2.rooms.list(mode, object); - * console.log(v2_rooms_list); - * }; - * - * main(); - * ``` - * @param {string} mode ```all``` or ```owned``` or ```participated``` or ```ended``` - * @param {string} object.category ```normal``` or ```spotlight``` or ```featured_artist``` - * @param {number} object.limit Number of results - * @param {number} object.season_id season_id - * @param {string} object.type_group ```playlists``` or ```realtime``` - */ - (mode: 'all' | 'owned' | 'participated' | 'ended' , object?: {category?: 'normal' | 'spotlight' | 'featured_artist' , limit?: number, season_id?: number, type_group?: 'playlists' | 'realtime' , }): Promise; -} diff --git a/src/types/v2_scores_details.ts b/src/types/v2_scores_details.ts deleted file mode 100644 index 5362678e..00000000 --- a/src/types/v2_scores_details.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { Mod } from "./mods" - -export type response = { - maximum_statistics: { - great: number - legacy_combo_increase: number - } - mods: Mod[] - statistics: { - ok: number - meh: number - miss: number - great: number - } - beatmap_id: number - best_id: any - id: number - rank: string - type: string - user_id: number - accuracy: number - build_id: any - ended_at: string - has_replay: boolean - legacy_perfect: any - legacy_score_id: number - legacy_total_score: number - max_combo: number - passed: boolean - pp: any - ruleset_id: number - started_at: any - total_score: number - replay: boolean - current_user_attributes: { - pin: any - } - beatmap: { - beatmapset_id: number - difficulty_rating: number - id: number - mode: string - status: string - total_length: number - user_id: number - version: string - accuracy: number - ar: number - bpm: number - convert: boolean - count_circles: number - count_sliders: number - count_spinners: number - cs: number - deleted_at: any - drain: number - hit_length: number - is_scoreable: boolean - last_updated: string - mode_int: number - passcount: number - playcount: number - ranked: number - url: string - checksum: string - max_combo: number - user: { - avatar_url: string - country_code: string - default_group: string - id: number - is_active: boolean - is_bot: boolean - is_deleted: boolean - is_online: boolean - is_supporter: boolean - last_visit: string - pm_friends_only: boolean - profile_colour: any - username: string - } - } - beatmapset: { - artist: string - artist_unicode: string - covers: { - cover: string - "cover@2x": string - card: string - "card@2x": string - list: string - "list@2x": string - slimcover: string - "slimcover@2x": string - } - creator: string - favourite_count: number - hype: any - id: number - nsfw: boolean - offset: number - play_count: number - preview_url: string - source: string - spotlight: boolean - status: string - title: string - title_unicode: string - track_id: any - user_id: number - video: boolean - } - rank_global: number - user: { - avatar_url: string - country_code: string - default_group: string - id: number - is_active: boolean - is_bot: boolean - is_deleted: boolean - is_online: boolean - is_supporter: boolean - last_visit: string - pm_friends_only: boolean - profile_colour: any - username: string - country: { - code: string - name: string - } - cover: { - custom_url: string - url: string - id: any - } - groups: Array - } -} - - - -export interface types { - /** - * Return data for a score - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_scores_details = await v2.scores.details(score_id, mode); - * console.log(v2_scores_details); - * }; - * - * main(); - * ``` - * @param {number} score_id id of the score - * @param {string} mode ```osu``` or ```fruits``` or ```mania``` or ```taiko``` - */ - (score_id: number, mode: 'osu' | 'fruits' | 'mania' | 'taiko' ): Promise; -} diff --git a/src/types/v2_scores_user_beatmap.ts b/src/types/v2_scores_user_beatmap.ts deleted file mode 100644 index 8db888fa..00000000 --- a/src/types/v2_scores_user_beatmap.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { Mod } from "./mods" - -export interface response { - maximum_statistics: { - great: number - legacy_combo_increase: number - } - mods: Mod[] - statistics: { - ok: number - meh?: number - miss: number - great: number - } - beatmap_id: number - best_id: any - id: number - rank: string - type: string - user_id: number - accuracy: number - build_id: any - ended_at: string - has_replay: boolean - legacy_perfect: any - legacy_score_id: number - legacy_total_score: number - max_combo: number - passed: boolean - pp: any - ruleset_id: number - started_at: any - total_score: number - replay: boolean - current_user_attributes: { - pin: any - } -} - - -export interface types { - /** - * Return best user score on beatmap - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_scores_user_beatmap = await v2.scores.user.beatmap(beatmap, user, object); - * console.log(v2_scores_user_beatmap); - * }; - * - * main(); - * ``` - * @param {number} beatmap id of the beatmap - * @param {string|number} user id of the user - * @param {string} object.mode ```osu``` or ```fruits``` or ```mania``` or ```taiko``` - * @param {string[]} object.mods Array of matching mods ['HD', 'DT'] - * @param {boolean} object.best_only Return only best score from the beatmap - */ - (beatmap: number, user?: string | number, object?: { mode?: 'osu' | 'fruits' | 'mania' | 'taiko', mods?: string[], best_only?: boolean, }): Promise; -} diff --git a/src/types/v2_scores_user_category.ts b/src/types/v2_scores_user_category.ts deleted file mode 100644 index f9d90a4e..00000000 --- a/src/types/v2_scores_user_category.ts +++ /dev/null @@ -1,143 +0,0 @@ -import { Mod } from "./mods" - -export interface response { - position: number - mods_id: number - maximum_statistics: { - great: number - legacy_combo_increase: number - } - mods: Mod[] - statistics: { - ok?: number - meh?: number - miss?: number - great: number - } - beatmap_id: number - best_id: any - id: number - rank: string - type: string - user_id: number - accuracy: number - build_id: any - ended_at: string - has_replay: boolean - legacy_perfect: any - legacy_score_id: number - legacy_total_score: number - max_combo: number - passed: boolean - pp?: number - ruleset_id: number - started_at: any - total_score: number - replay: boolean - current_user_attributes: { - pin: any - } - beatmap: { - beatmapset_id: number - difficulty_rating: number - id: number - mode: string - status: string - total_length: number - user_id: number - version: string - accuracy: number - ar: number - bpm: number - convert: boolean - count_circles: number - count_sliders: number - count_spinners: number - cs: number - deleted_at: any - drain: number - hit_length: number - is_scoreable: boolean - last_updated: string - mode_int: number - passcount: number - playcount: number - ranked: number - url: string - checksum: string - } - beatmapset: { - artist: string - artist_unicode: string - covers: { - cover: string - "cover@2x": string - card: string - "card@2x": string - list: string - "list@2x": string - slimcover: string - "slimcover@2x": string - } - creator: string - favourite_count: number - hype: any - id: number - nsfw: boolean - offset: number - play_count: number - preview_url: string - source: string - spotlight: boolean - status: string - title: string - title_unicode: string - track_id?: number - user_id: number - video: boolean - } - user: { - avatar_url: string - country_code: string - default_group: string - id: number - is_active: boolean - is_bot: boolean - is_deleted: boolean - is_online: boolean - is_supporter: boolean - last_visit: string - pm_friends_only: boolean - profile_colour: any - username: string - } -} - -export interface types { - /** - * Return list of user scores on a beatmap - * - * ## Example - * - * ```js - * const { v2, auth, mods } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_scores_user_category = await v2.scores.user.category(user, type, object); - * console.log(v2_scores_user_category); - * }; - * - * main(); - * ``` - * @param {number} user id of the user - * @param {string} type ```recent``` or ```best``` or ```firsts``` or ```pinned``` - * @param {boolean} object.include_fails Only for ```recent``` scores, include scores of failed plays. Set to ```true``` to include them. Defaults to ```false``` - * @param {string} object.mode ```osu``` or ```fruits``` or ```mania``` or ```taiko``` - * @param {number} object.mods Use ```mods.enums``` instead of mods id or name - * @param {string} object.limit Maximum number of results - * @param {string} object.offset Result offset for pagination - */ - (user: number, type: 'recent' | 'best' | 'firsts' | 'pinned', object: { include_fails?: boolean, mode?: 'osu' | 'fruits' | 'mania' | 'taiko', mods?: number, limit?: string, offset?: string, }): Promise; -} diff --git a/src/types/v2_site_ranking_details.ts b/src/types/v2_site_ranking_details.ts deleted file mode 100644 index bb7f6d76..00000000 --- a/src/types/v2_site_ranking_details.ts +++ /dev/null @@ -1,188 +0,0 @@ -export interface response { - cursor: { - page: number; - }; - ranking: { - count_100?: number; - count_300?: number; - count_50?: number; - count_miss?: number; - level: { - current: number; - progress: number; - }; - global_rank?: number; - global_rank_exp?: number; - pp?: number; - pp_exp?: number; - ranked_score: number; - hit_accuracy?: number; - play_count: number; - play_time?: number; - total_score?: number; - total_hits?: number; - maximum_combo?: number; - replays_watched_by_others?: number; - is_ranked?: boolean; - grade_counts: { - ss: number; - ssh: number; - s: number; - sh: number; - a: number; - }; - rank_change_since_30_days?: number; - user: { - avatar_url: string; - country_code: string; - default_group: string; - id: number; - is_active: boolean; - is_bot: boolean; - is_deleted: boolean; - is_online: boolean; - is_supporter: boolean; - last_visit: string; - pm_friends_only: boolean; - profile_colour: string; - username: string; - country: { - code: string; - name: string; - }; - cover: { - custom_url: string; - url: string; - id: number; - }; - }; - code?: string; - active_users?: number; - performance?: number; - country: { - code: string; - name: string; - }; - }[]; - total: number; - beatmapsets: { - artist: string; - artist_unicode: string; - covers: { - cover: string; - 'cover@2x': string; - card: string; - 'card@2x': string; - list: string; - 'list@2x': string; - slimcover: string; - 'slimcover@2x': string; - }; - creator: string; - favourite_count: number; - hype?: string; - id: number; - nsfw: boolean; - offset: number; - play_count: number; - preview_url: string; - source: string; - spotlight: boolean; - status: string; - title: string; - title_unicode: string; - track_id?: string; - user_id: number; - video: boolean; - bpm: number; - can_be_hyped: boolean; - deleted_at?: string; - discussion_enabled: boolean; - discussion_locked: boolean; - is_scoreable: boolean; - last_updated: string; - legacy_thread_url: string; - nominations_summary: { - current: number; - required: number; - }; - ranked: number; - ranked_date: string; - storyboard: boolean; - submitted_date: string; - tags: string; - availability: { - download_disabled: boolean; - more_information: string; - }; - has_favourited: boolean; - beatmaps: { - beatmapset_id: number; - difficulty_rating: number; - id: number; - mode: string; - status: string; - total_length: number; - user_id: number; - version: string; - accuracy: number; - ar: number; - bpm: number; - convert: boolean; - count_circles: number; - count_sliders: number; - count_spinners: number; - cs: number; - deleted_at?: string; - drain: number; - hit_length: number; - is_scoreable: boolean; - last_updated: string; - mode_int: number; - passcount: number; - playcount: number; - ranked: number; - url: string; - checksum: string; - }[]; - }[]; - spotlight: { - end_date: string; - id: number; - mode_specific: boolean; - name: string; - start_date: string; - type: string; - participant_count: number; - }; -} - - -export interface types { - /** - * Gets the current ranking leaderboard for the specified type and game mode - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login(CLIENT_ID, CLIENT_SECRET); - * - * const v2_site_ranking_details = await v2.site.ranking.details(mode, type, object); - * console.log(v2_site_ranking_details); - * }; - * - * main(); - * ``` - * @param {string} mode ```osu``` or ```fruits``` or ```mania``` or ```taiko``` - * @param {string} type ```charts``` or ```country``` or ```performance``` or ```score``` - * @param {number} object.country Filter ranking by country code. Only available for ```type``` of ```performance``` - * @param {number} object.cursor[page] Page number - * @param {string} object.filter ```all``` or ```friends``` - * @param {string} object.spotlight The id of the spotlight if type is charts. Ranking for latest spotlight will be returned if not specified - * @param {string} object.variant Filter ranking to specified mode variant. For ```mode``` of ```mania```, it's either ```4k``` or ```7k```. Only available for ```type``` of ```performance``` - */ - (mode: 'osu' | 'fruits' | 'mania' | 'taiko', type: 'charts' | 'country' | 'performance' | 'score', object?: { country?: string, "cursor[page]"?: number, filter?: 'all' | 'friends' , spotlight?: string, variant?: string, }): Promise; -} diff --git a/src/types/v2_user_me_download_quota.ts b/src/types/v2_user_me_download_quota.ts deleted file mode 100644 index 20ee3337..00000000 --- a/src/types/v2_user_me_download_quota.ts +++ /dev/null @@ -1,278 +0,0 @@ -export interface response { - avatar_url: string - country_code: string - default_group: string - id: number - is_active: boolean - is_bot: boolean - is_deleted: boolean - is_online: boolean - is_supporter: boolean - last_visit: any - pm_friends_only: boolean - profile_colour: any - username: string - cover_url: string - discord: string - has_supported: boolean - interests: string - join_date: string - location: string - max_blocks: number - max_friends: number - occupation: any - playmode: string - playstyle: Array - post_count: number - profile_order: Array - title: any - title_url: any - twitter: string - website: string - country: { - code: string - name: string - } - cover: { - custom_url: string - url: string - id: any - } - is_restricted: boolean - kudosu: { - available: number - total: number - } - account_history: Array - active_tournament_banner: any - active_tournament_banners: Array - badges: Array - beatmap_playcounts_count: number - comments_count: number - favourite_beatmapset_count: number - follower_count: number - graveyard_beatmapset_count: number - groups: Array - guest_beatmapset_count: number - loved_beatmapset_count: number - mapping_follower_count: number - monthly_playcounts: Array<{ - start_date: string - count: number - }> - nominated_beatmapset_count: number - page: { - html: string - raw: string - } - pending_beatmapset_count: number - previous_usernames: Array - rank_highest: { - rank: number - updated_at: string - } - ranked_beatmapset_count: number - replays_watched_counts: Array<{ - start_date: string - count: number - }> - scores_best_count: number - scores_first_count: number - scores_pinned_count: number - scores_recent_count: number - session_verified: boolean - statistics: { - count_100: number - count_300: number - count_50: number - count_miss: number - level: { - current: number - progress: number - } - global_rank: number - global_rank_exp: number - pp: number - pp_exp: number - ranked_score: number - hit_accuracy: number - play_count: number - play_time: number - total_score: number - total_hits: number - maximum_combo: number - replays_watched_by_others: number - is_ranked: boolean - grade_counts: { - ss: number - ssh: number - s: number - sh: number - a: number - } - country_rank: number - rank: { - country: number - } - } - statistics_rulesets: { - osu: { - count_100: number - count_300: number - count_50: number - count_miss: number - level: { - current: number - progress: number - } - global_rank: number - global_rank_exp: number - pp: number - pp_exp: number - ranked_score: number - hit_accuracy: number - play_count: number - play_time: number - total_score: number - total_hits: number - maximum_combo: number - replays_watched_by_others: number - is_ranked: boolean - grade_counts: { - ss: number - ssh: number - s: number - sh: number - a: number - } - } - taiko: { - count_100: number - count_300: number - count_50: number - count_miss: number - level: { - current: number - progress: number - } - global_rank: any - global_rank_exp: any - pp: number - pp_exp: number - ranked_score: number - hit_accuracy: number - play_count: number - play_time: number - total_score: number - total_hits: number - maximum_combo: number - replays_watched_by_others: number - is_ranked: boolean - grade_counts: { - ss: number - ssh: number - s: number - sh: number - a: number - } - } - fruits: { - count_100: number - count_300: number - count_50: number - count_miss: number - level: { - current: number - progress: number - } - global_rank: any - global_rank_exp: any - pp: number - pp_exp: number - ranked_score: number - hit_accuracy: number - play_count: number - play_time: number - total_score: number - total_hits: number - maximum_combo: number - replays_watched_by_others: number - is_ranked: boolean - grade_counts: { - ss: number - ssh: number - s: number - sh: number - a: number - } - } - mania: { - count_100: number - count_300: number - count_50: number - count_miss: number - level: { - current: number - progress: number - } - global_rank: any - global_rank_exp: any - pp: number - pp_exp: number - ranked_score: number - hit_accuracy: number - play_count: number - play_time: number - total_score: number - total_hits: number - maximum_combo: number - replays_watched_by_others: number - is_ranked: boolean - grade_counts: { - ss: number - ssh: number - s: number - sh: number - a: number - } - } - } - support_level: number - user_achievements: Array<{ - achieved_at: string - achievement_id: number - }> - rank_history: { - mode: string - data: Array - } - rankHistory: { - mode: string - data: Array - } - ranked_and_approved_beatmapset_count: number - unranked_beatmapset_count: number -} - - -export interface types { - /** - * Return user download quota number? - * - * ## Example - * - * ```js - * const { v2, auth } = require('osu-api-extended'); - * - * const main = async () => { - * await auth.login_lazer(USERNAME, USER_PASSWORD); - * - * const v2_user_me_download_quota = await v2.user.me.download.quota(); - * console.log(v2_user_me_download_quota); - * }; - * - * main(); - * ``` - */ - (): Promise; -} diff --git a/src/utility/auth.ts b/src/utility/auth.ts deleted file mode 100644 index 55f3d1d9..00000000 --- a/src/utility/auth.ts +++ /dev/null @@ -1,204 +0,0 @@ -import { execSync } from 'child_process'; -import readln from "readline"; - - -import { types as user_types } from '../types/v2_user_me_details'; -import { osu_mode, auth_scopes } from './types'; -import { request } from "../utility/request"; - - -interface _login { - access_token: string, - expires_in: number -} - -const credentials: { - type: number, - username: string, - password: string, - clientId: number, - clientSecret: string, - redirect_uri: string, - scope: auth_scopes, -} = { - type: 0, - username: '', - password: '', - clientId: 0, - clientSecret: '', - redirect_uri: '', - scope: ['public'], -}; - - -export let cache_v1: string = ''; -export let cache_v2: string = ''; - - -export const set_v1 = (v: string) => cache_v1 = v; -export const set_v2 = (v: string) => cache_v2 = v; - -const isInitial = () => cache_v2 != ''; - -const save_credentials = (type: number, obj: any) => { - if (type == 1) { - credentials.type = 1; - credentials.username = obj.username; - credentials.password = obj.password; - }; - - if (type == 2) { - credentials.type = 2; - credentials.clientId = obj.clientId; - credentials.clientSecret = obj.clientSecret; - credentials.scope = obj.scope; - }; - - if (type == 3) { - credentials.type = 3; - credentials.clientId = obj.clientId; - credentials.clientSecret = obj.clientSecret; - credentials.redirect_uri = obj.redirect_uri; - credentials.scope = obj.scope; - }; -}; - - -export const re_login = async () => { - if (credentials.type == 1) await login_lazer(credentials.username, credentials.password); - if (credentials.type == 2) await login(credentials.clientId, credentials.clientSecret, credentials.scope); - if (credentials.type == 3) await authorize_cli(credentials.clientId, credentials.clientSecret, credentials.redirect_uri, credentials.scope); - - return true; -}; - - -export const login_lazer = async (username: string, password: string): Promise<_login> => { - if (!isInitial()) save_credentials(1, { username, password }); - - const { access_token, expires_in } = await request('https://osu.ppy.sh/oauth/token', { - method: 'POST', - headers: { - "Accept": "application/json", - "Content-Type": "application/json", - 'x-api-version': '20240130', - }, - data: JSON.stringify({ - username, - password, - grant_type: "password", - client_id: 5, - client_secret: 'FGc9GAtyHzeQDshWP5Ah7dega8hJACAJpQtw6OXk', - scope: "*" - }) - }); - - cache_v2 = access_token; - - return { access_token, expires_in }; -}; - - -export const login = async (clientId: number, clientSecret: string, scope: auth_scopes): Promise<_login> => { - if (!Array.isArray(scope) || !scope) throw new Error('Scope must be an Array'); - if (!isInitial()) save_credentials(2, { clientId, clientSecret, scope }); - - const { access_token, expires_in } = await request('https://osu.ppy.sh/oauth/token', { - method: 'POST', - headers: { - "Accept": "application/json", - "Content-Type": "application/json", - 'x-api-version': '20240130', - }, - data: JSON.stringify({ - grant_type: 'client_credentials', - client_id: clientId, - client_secret: clientSecret, - scope: scope.join(' '), - code: 'code', - }) - }); - - cache_v2 = access_token; - - return { access_token, expires_in }; -}; - - -export const authorize_cli = async (clientId: number, clientSecret: string, redirectUri: string, scope: auth_scopes, state?: string): Promise<_login> => { - if (!Array.isArray(scope) || !scope) throw new Error('Scope must be an Array'); - if (!isInitial()) save_credentials(3, { clientId, clientSecret, redirect_uri: redirectUri, scope }); - - const cl = readln.createInterface(process.stdin, process.stdout); - const question = (q: string) => new Promise((res, rej) => cl.question(q + ': ', (answer: string) => res(answer))); - - - const url = build_url(clientId, redirectUri, scope, state); - // await open(url); - const start = (process.platform == 'darwin' ? 'open' : process.platform == 'win32' ? 'start' : 'xdg-open'); - execSync(start + ' ' + url.replaceAll('&', '^&')); - - - const code = await question('Paste code here'); - const { access_token, expires_in } = await request('https://osu.ppy.sh/oauth/token', { - method: 'POST', - headers: { - "Accept": "application/json", - "Content-Type": "application/json", - 'x-api-version': '20240130', - }, - data: JSON.stringify({ - grant_type: 'authorization_code', - client_id: clientId, - client_secret: clientSecret, - redirect_uri: redirectUri, - code, - }) - }); - - cache_v2 = access_token; - - return { access_token, expires_in }; -}; - - -export const build_url = (clientId: number, redirectUri: string, scope: auth_scopes, state?: string): string => { - if (!Array.isArray(scope) || !scope) throw new Error('Scope must be an Array'); - - const url = new URL('https://osu.ppy.sh/oauth/authorize'); - const params: any = { - client_id: clientId, - redirect_uri: redirectUri, - response_type: 'code', - scope: scope.join(' '), - state: state, - }; - - Object.keys(params) - .forEach(key => url.searchParams.append(key, params[key])); - - return url.href; -}; - - -export const authorize = async (code: string, gamemode: osu_mode, clientId: number, clientSecret: string, redirectUri: string): Promise => { - const { access_token } = await request('https://osu.ppy.sh/oauth/token', { - method: 'POST', - headers: { - "Accept": "application/json", - "Content-Type": "application/json", - 'x-api-version': '20240130', - }, - data: JSON.stringify({ - grant_type: 'authorization_code', - client_id: clientId, - client_secret: clientSecret, - redirect_uri: redirectUri, - code, - }) - }); - - - const user = await request(`https://osu.ppy.sh/api/v2/me/${gamemode}`, { params: { v2: access_token } }); - return user; -}; \ No newline at end of file diff --git a/src/utility/request.ts b/src/utility/request.ts deleted file mode 100644 index 59966a76..00000000 --- a/src/utility/request.ts +++ /dev/null @@ -1,191 +0,0 @@ -import * as auth from "../utility/auth"; -import https from 'https'; -import fs from "fs"; - -interface RequestParams { - method?: string; - headers?: { [key: string]: string }; - data?: string; - params?: object | [object, ...object[]]; -} - -export interface RequestNamespace { - (url: string, params: { method: string, data?: string, headers?: { [key: string]: string }, params?: object }): Promise; -} - -const generateQueryString = (obj: any, trail: string = ''): string => { - const params: string[] = []; - - const processValue = (key: string, value: any) => { - if (Array.isArray(value)) { - value.forEach((item) => { - params.push(`${key}[]=${encodeURIComponent(item)}`); - }); - } else if (typeof value === 'object' && value !== null) { - const newTrail = trail ? `${trail}.${key}` : key; - params.push(generateQueryString(value, newTrail)); - } else if (typeof value === 'number' && value > 0) { - params.push(`${key}=${value}`); - } else if (typeof value === 'string') { - params.push(`${key}=${encodeURIComponent(value)}`); - } - }; - - for (const key in obj) { - if (obj.hasOwnProperty(key)) { - const value = obj[key]; - if (value !== undefined) { - processValue(key, value); - } - } - } - - return params.join('&'); -}; - - -const TIMEOUT_MS = 60000; -let amount_retry = 0; - -/** - * Executes an HTTP request - * @param {string} url The url - * @returns {Promise} The response - */ -export const request = (url: string, { method = "GET", headers, data, params = {} }: RequestParams = {}): Promise => { - if (url.includes('https://osu.ppy.sh/api/') && !url.includes('https://osu.ppy.sh/api/v2')) { - // @ts-ignore - params.k = params.v1 || auth.cache_v1; - } - - if (url.includes('https://osu.ppy.sh/api/v2')) - headers = { - // @ts-ignore - Authorization: `Bearer ${params.v2 || auth.cache_v2}`, - Accept: `application/json`, - 'Content-Type': `application/json`, - 'x-api-version': '20240130', - }; - - // console.log({ url, method, headers, data, params: generateQueryString(params) }); // debug too - return new Promise((resolve, reject) => { - const req = https.request(url + (generateQueryString(params) ? `?${generateQueryString(params)}` : ''), { method, headers }, (response) => { - const chunks: any[] = []; - - response.on('data', (chunk: any) => chunks.push(chunk)); - response.on('end', async () => { - const data = Buffer.concat(chunks).toString(); - - if (/^application\/json/.test(response.headers['content-type'])) { - try { - const parse = JSON.parse(data); - if (parse.authentication === 'basic' && auth.cache_v2 && amount_retry < 3) { - await auth.re_login(); - - amount_retry++; - - const again = await request(url, { method, headers, data, params }); - return resolve(again); - } - - amount_retry = 0; - - return resolve(parse); - } catch (err) { - console.log(`JSON Parse on content of type ${response.headers['content-type']} failed.\nError: ${err}\nData: ${data}`); - } - } - - resolve(data); - }); - }).on('error', reject); - - req.setTimeout(TIMEOUT_MS, () => { - req.destroy(); - reject(new Error(`Request to ${url} time out after ${TIMEOUT_MS}ms`)); - }); - - if (data) req.write(data); - req.end(); - }); -}; - - -/** - * Executes an HTTP request - * @param {string} url The url - * @param {string} dest The file destination - * @returns {Promise} The response - */ -export const download = (url: string, dest: string, { headers = {}, data, params }: RequestParams = {}, callback?: Function): Promise => { - return new Promise((resolve, reject) => { - if (url.includes('https://osu.ppy.sh/api/v2')) headers['Authorization'] = `Bearer ${auth.cache_v2}`; - - headers['accept'] = `application/octet-stream`; - headers['content-Type'] = `application/octet-stream`; - - - const req = https.request(url + (params ? '?' + generateQueryString(params) : ''), { method: 'GET', headers }, response => { - const { location } = response.headers; - - if (location) { - download(location, dest, { headers, data, params }, callback) - .then(resolve) - .catch(reject); - return; - } - - if (response.statusCode === 404) { - resolve({ error: 'file unavailable' }); - return; - } - - const file = fs.createWriteStream(dest, { encoding: 'utf8' }); - - file.on('error', err => { - fs.unlinkSync(dest); - reject(err); - }); - - file.on('finish', () => { - file.close(); - resolve(dest); - }); - - if (callback !== undefined) { - const totalLength = parseInt(response.headers['content-length']); - - let progress = 0; - let progressBar = 0; - - response.on('data', (chunk) => { - progress += chunk.length; - progressBar = 100 * (progress / totalLength); - callback(progressBar); - }); - } - - response.pipe(file); - }); - - req.setTimeout(TIMEOUT_MS, () => { - req.destroy(); - reject(new Error(`Request to ${url} time out after ${TIMEOUT_MS}ms`)); - }); - - if (data) { - req.write(data); - } - req.end(); - }); -}; - -/** - * Makes a namespace - * @param {string} url The namespace url - * @param {{ query?: string }} [params] Options ig - * @returns {(params: string, { query: string }) => Promise} The function that does the reqs - */ -export const namespace = (url: string, { query }: { query?: { [key: string]: string }, headers?: Record } = {}): RequestNamespace => { - return (path: string, params) => request(url + path, params); -}; \ No newline at end of file diff --git a/src/utility/types.ts b/src/utility/types.ts deleted file mode 100644 index 8dc1e592..00000000 --- a/src/utility/types.ts +++ /dev/null @@ -1,23 +0,0 @@ -export interface Description { - auth: number; - title: string; - method: string; - description: string; - imports?: string[]; - params: Param[]; - return?: string; - notes?: object[]; -} - -export interface Param { - type?: string; - name: string; - options?: boolean; - optional?: boolean; - description?: string; - params?: Param[]; -}; - -export type osu_mode = 'osu' | 'fruits' | 'mania' | 'taiko'; - -export type auth_scopes = ('chat.write' | 'delegate' | 'forum.write' | 'friends.read' | 'identify' | 'public')[]; \ No newline at end of file From 922a9137a3475b380f586faf5a771cf807558ac4 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Tue, 14 May 2024 18:33:00 +0300 Subject: [PATCH 161/259] Add `net-pp` function to `tools`. --- tools/net-pp.ts | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 tools/net-pp.ts diff --git a/tools/net-pp.ts b/tools/net-pp.ts new file mode 100644 index 00000000..f8565295 --- /dev/null +++ b/tools/net-pp.ts @@ -0,0 +1,45 @@ +import { v2 } from "../"; +import type { Modes_names } from "../types"; + +export const calculate_net_pp = async (params: { + user_id: number; + pp_value: number; + gamemode?: Modes_names; +}): Promise => { + // fetch user's top plays + const top_plays = await v2.scores.list({ + type: "user_best", + user_id: params.user_id, + limit: 100, + }); + + // map returned data to only pp values. + const old_scores = top_plays.map(x => x.pp); + + // create a copy of the top plays array for simulation. + const new_scores = [...top_plays]; + + // return 0.0 if the passed pp value is lower than the lowest best score. + if (params.pp_value < Math.min(...old_scores)) return 0.0; + + // weight the user's current scores. (see https://osu.ppy.sh/wiki/en/Performance_points/Weighting_system) + const weighted_old_scores = old_scores.map((x, i) => x * Math.pow(0.95, i)); + + // change the last score to the new value. + new_scores[new_scores.length - 1].pp = params.pp_value; + + // sort the array by pp value (descending). + new_scores.sort((a, b) => b.pp - a.pp); + + // weight the new scores. (see https://osu.ppy.sh/wiki/en/Performance_points/Weighting_system) + const weighted_new_scores = new_scores.map((x, i) => x.pp * Math.pow(0.95, i)); + + // sum up the total pp value of the user's current scores. + const total_pp_old = weighted_old_scores.reduce((a, b) => a + b, 0); + + // sum up the total pp value of the user's new simulated scores. + const total_pp_new = weighted_new_scores.reduce((a, b) => a + b, 0); + + // return the delta between the two pp values. + return total_pp_new - total_pp_old; +}; \ No newline at end of file From 7cefe08ee26e3ddb45e02e9cd4b24eea67ea3046 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Tue, 14 May 2024 18:34:23 +0300 Subject: [PATCH 162/259] Export `net-pp` function. --- tools/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/index.ts b/tools/index.ts index f16efe12..d269f97e 100644 --- a/tools/index.ts +++ b/tools/index.ts @@ -6,6 +6,7 @@ export { calculate_mods } from "./mods"; export { country_details } from "./country"; export { calculate_rank } from "./rank"; export { calculate_total_objects } from "./objects"; +export { calculate_net_pp } from "./net-pp"; From 123e08060d1410ed01acca7f86d156b5bdf62ff9 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Tue, 14 May 2024 19:20:28 +0300 Subject: [PATCH 163/259] net_pp: make it universal + fixes --- tools/net-pp.ts | 82 +++++++++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 33 deletions(-) diff --git a/tools/net-pp.ts b/tools/net-pp.ts index f8565295..2e9c78c4 100644 --- a/tools/net-pp.ts +++ b/tools/net-pp.ts @@ -1,45 +1,61 @@ -import { v2 } from "../"; -import type { Modes_names } from "../types"; +import type { IError, Modes_names } from "../types"; +import { handleErrors } from "../utility/handleErrors"; -export const calculate_net_pp = async (params: { - user_id: number; - pp_value: number; - gamemode?: Modes_names; -}): Promise => { - // fetch user's top plays - const top_plays = await v2.scores.list({ - type: "user_best", - user_id: params.user_id, - limit: 100, - }); +import { ScoresListUserBestResponse } from "../types/v2/scores_list_user_best"; - // map returned data to only pp values. - const old_scores = top_plays.map(x => x.pp); - // create a copy of the top plays array for simulation. - const new_scores = [...top_plays]; +type Response = { + pp: number; + totalNow: number; + totalBefore: number; +} & IError; - // return 0.0 if the passed pp value is lower than the lowest best score. - if (params.pp_value < Math.min(...old_scores)) return 0.0; - // weight the user's current scores. (see https://osu.ppy.sh/wiki/en/Performance_points/Weighting_system) - const weighted_old_scores = old_scores.map((x, i) => x * Math.pow(0.95, i)); +export const calculate_net_pp = (params: { + scores: ScoresListUserBestResponse[] | number[]; + pp_value: number; + gamemode?: Modes_names; +}): Response => { + if (!Array.isArray(params.scores)) { + return handleErrors(`Provide array of scores or numbers`) as Response; + }; - // change the last score to the new value. - new_scores[new_scores.length - 1].pp = params.pp_value; + if (!isFinite(params.pp_value) || params.pp_value == null) { + return handleErrors(`Specify pp`) as Response; + }; - // sort the array by pp value (descending). - new_scores.sort((a, b) => b.pp - a.pp); - // weight the new scores. (see https://osu.ppy.sh/wiki/en/Performance_points/Weighting_system) - const weighted_new_scores = new_scores.map((x, i) => x.pp * Math.pow(0.95, i)); + const pp_values = typeof params.scores[0] == 'number' ? params.scores : (params.scores as any[]).map(r => r.pp); + pp_values.sort((a, b) => b - a); - // sum up the total pp value of the user's current scores. - const total_pp_old = weighted_old_scores.reduce((a, b) => a + b, 0); + // weight the user's current scores. (see https://osu.ppy.sh/wiki/en/Performance_points/Weighting_system) + const weighted_before = pp_values.slice(0, 100).map((x, i) => x * Math.pow(0.95, i)); + // sum up the total pp value of the user's current scores. + const total_pp_old = weighted_before.reduce((a, b) => a + b, 0); - // sum up the total pp value of the user's new simulated scores. - const total_pp_new = weighted_new_scores.reduce((a, b) => a + b, 0); - // return the delta between the two pp values. - return total_pp_new - total_pp_old; + if (params.pp_value < Math.min(pp_values[pp_values.length - 1])) + return { + pp: 0, + totalNow: total_pp_old, + totalBefore: total_pp_old, + } as Response; + + + // Push new pp_value + pp_values.push(params.pp_value); + pp_values.sort((a, b) => b - a); + + + // weight the new scores. (see https://osu.ppy.sh/wiki/en/Performance_points/Weighting_system) + const weighted_after = pp_values.slice(0, 100).map((x, i) => x * Math.pow(0.95, i)); + // sum up the total pp value of the user's new simulated scores. + const total_pp_new = weighted_after.reduce((a, b) => a + b, 0); + + + return { + pp: total_pp_new - total_pp_old, + totalNow: total_pp_new, + totalBefore: total_pp_old, + } as Response; }; \ No newline at end of file From bfbe60b2e94862dd2c17183e7abaa185fa66391f Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Tue, 14 May 2024 19:03:41 +0300 Subject: [PATCH 164/259] Adapt `v2.users` to the new JSDoc format. --- routes/v2.ts | 156 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 107 insertions(+), 49 deletions(-) diff --git a/routes/v2.ts b/routes/v2.ts index e034798e..de895965 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -489,88 +489,146 @@ import { users_kudosu } from "../api/v2/users_kudosu"; */ export const users = { /** - * ##### Description - * `GET` https://osu.ppy.sh/api/v2/users - * + * ### `GET` [/v2/users](https://osu.ppy.sh/docs/index.html#get-users) * `async` Retrieves a list of users by given parameters. * - * @param ids - List of user ids to retrieve. - * @param [addons] - Additional parameters to include in the request. + *   * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + * ### Parameters + * - `params.ids` - List of user ids to retrieve. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-users) | [Check return types](../types/v2/users_list.ts) */ list: users_list, /** - * ##### Description - * `GET` https://osu.ppy.sh/api/v2/users/{user}/kudosu + * ### `GET` [/v2/users/{user}/kudosu](https://osu.ppy.sh/docs/index.html#get-user-kudosu) + * `async` Retrieves the kudosu history of a given user. * - * `async` Retrieves the kudosu history of a given users. + *   * - * @params ids - List of user ids to retrieve. - * @param [addons] - Additional parameters to include in the request. + * ### Parameters + * - `params.id` - ID of the user to retrieve. + * - `params.limit?` - Maximum number of results to return. + * - `params.offset?` - Result offset for pagination. + * - `addons?` - Additional parameters to include in the request. * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-user-kudosu) | [Check return types](../types/v2/users_kudosu.ts) */ kudosu: users_kudosu, /** - * ##### Description - * `GET` https://osu.ppy.sh/api/v2/events - * + * ### `GET` [/v2/events](https://osu.ppy.sh/docs/index.html#get-events) * `async` Retrieves a list of user events by given parameters. * - * @param params - Parameters to include in the request. - * @param [params.type] - Filter by type of event. - * @param [params.sort] - Sort order of the events by id. - * @param [params.cursor_string] - [Cursor string for pagination.](https://osu.ppy.sh/docs/index.html#cursorstring) - * @param [addons] - Additional parameters to include in the request. + *   * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + * ### Parameters + * - `params.type?` - Filter by type of event. + * - `params.sort?` - Sort order of the events by id. + * - `params.cursor_string?` - [Cursor string for pagination.](https://osu.ppy.sh/docs/index.html#cursorstring) + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-events) | [Check return types](../types/v2/users_events.ts) */ events: users_events, /** - * ##### Description - * `GET` https://osu.ppy.sh/api/v2/users/ - * + * ### `GET` [/v2/users/{user}/{mode?}](https://osu.ppy.sh/docs/index.html#get-user) * `async` Retrieves a user by given parameters. * - * @param {Object} params - Parameters to include in the request. - * @param params.id - ID or username of the user to retrieve. - * @param [params.mode] - Retrieve data for a specific gamemode. - * @param [params.key] - Type of the `params.id` parameter. - * @param [addons] - Additional parameters to include in the request. + *   * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + * ### Parameters + * - `params.id` - ID or username of the user to retrieve. + * - `params.mode?` - Retrieve data for a specific gamemode. + * - `params.key?` - Type of the `params.id` parameter. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-user) | [Check return types](../types/v2/users_details.ts) */ details: users_details, /** - * ##### Description - * `GET` https://osu.ppy.sh/api/v2/users/{user}/beatmapsets/ - * + * ### `GET` [/v2/users/{user}/beatmapsets/{type}](https://osu.ppy.sh/docs/index.html#get-user-beatmaps) * `async` Retrieves a list of user's beatmaps sets by given parameters. * - * @param {Object} params - Parameters to include in the request. - * @param params.type - Filter by type of beatmap set. - * @param params.id - ID of the user to retrieve. - * @param [params.limit] - Maximum number of beatmap sets to return. - * @param [params.offset] - Result offset for pagination. - * @param [addons] - Additional parameters to include in the request. + *   * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + * ### Parameters + * - `params.type` - Filter by type of beatmap set. + * - `params.id` - ID of the user to retrieve. + * - `params.limit?` - Maximum number of beatmap sets to return. + * - `params.offset?` - Result offset for pagination. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-user-beatmaps) | [Check return types](../types/v2/users_beatmaps.ts) */ beatmaps: users_beatmaps, /** - * ##### Description - * `GET` https://osu.ppy.sh/api/v2/users/{user}/activity - * + * ### `GET` [/v2/users/{user}/recent_activity](https://osu.ppy.sh/docs/index.html#get-user-recent-activity) * `async` Retrieves a list of user's recent activities by given parameters. * - * @param {Object} params - Parameters to include in the request. - * @param params.id - ID of the user to retrieve. - * @param [params.limit] - Maximum number of activities to return. - * @param [params.offset] - Result offset for pagination. - * @param [addons] - Additional parameters to include in the request. + *   * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + * ### Parameters + * - `params.id` - ID of the user to retrieve. + * - `params.limit?` - Maximum number of activities to return. + * - `params.offset?` - Result offset for pagination. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-user-recent-activity) | [Check return types](../types/v2/users_activity.ts) */ activity: users_activity, }; From 3304fc60fdfb50b3f904f754ba289541aff35b77 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Tue, 14 May 2024 19:07:08 +0300 Subject: [PATCH 165/259] Limit `params.ids` request size in `v2.users.list()` --- api/v2/users_list.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/api/v2/users_list.ts b/api/v2/users_list.ts index 918ff51b..59a017a8 100644 --- a/api/v2/users_list.ts +++ b/api/v2/users_list.ts @@ -12,6 +12,9 @@ export const users_list = async (ids: number[], addons?: IDefaultParams): Promis return handleErrors(`Specify at least one user id`) as Response; }; + if (ids.length > 50) { + return handleErrors("No more than 50 users can be requested at once.") as Response; + } const data = await request(`https://osu.ppy.sh/api/v2/users`, { method: 'GET', From 0107922a289ea77520adb2d5b0ea54ebc380b949 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Tue, 14 May 2024 19:21:41 +0300 Subject: [PATCH 166/259] support api v2 mods conversion --- tools/mods.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tools/mods.ts b/tools/mods.ts index 9c270e3c..7d334a5c 100644 --- a/tools/mods.ts +++ b/tools/mods.ts @@ -1,5 +1,6 @@ import { IError } from "../types"; import { ModsOrder } from "../types/enums"; +import { Mod } from "../types/mods"; import { ModsResponse } from "../types/tools"; import { handleErrors } from "../utility/handleErrors"; @@ -50,7 +51,7 @@ type Response = ModsResponse & IError; // SWITCH STATEMENT CREATED ON PURPOSE BECAUSE IT'S WAY FASTER -export const calculate_mods = (ModsName: string | number, order?: boolean): Response => { +export const calculate_mods = (ModsName: Mod[] | string | number, order?: boolean): Response => { if (ModsName == null) { return handleErrors(`Specify mods name (HDDT or 72)`) as Response; }; @@ -66,8 +67,17 @@ export const calculate_mods = (ModsName: string | number, order?: boolean): Resp let mods_id = 0; + let ModsArray = []; + + if (Array.isArray(ModsName)) { + ModsArray = ModsName.map(r => r.acronym.toLowerCase()); + } + + else { + ModsArray = ModsName.toLowerCase().match(/.{1,2}/g); + }; + - const ModsArray = ModsName.toLowerCase().match(/.{1,2}/g); if (!Array.isArray(ModsArray)) { return handleErrors(`Can't convert mods (${ModsName}) to array of mods`) as Response; }; From f5bd23bac08ed900da6455a3afe461588a7f7262 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Thu, 16 May 2024 20:15:35 +0300 Subject: [PATCH 167/259] accept both id and name --- api/v2/users_details.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/v2/users_details.ts b/api/v2/users_details.ts index 6e77f6db..06fd2afe 100644 --- a/api/v2/users_details.ts +++ b/api/v2/users_details.ts @@ -8,12 +8,12 @@ type Response = UsersDetailsResponse & IError; export const users_details = async (params: { - id: number; + id?: number | string; mode?: Modes_names; key?: 'id' | 'username'; }, addons?: IDefaultParams): Promise => { if (params.id == null) { - return handleErrors(`Specify user id`) as Response; + return handleErrors(`Specify user id or name`) as Response; }; From 6dd8f587e8ec82afe1c6cd96de55e437d3aef691 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Thu, 16 May 2024 20:16:19 +0300 Subject: [PATCH 168/259] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7000c44a..e26180ca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.32", + "version": "3.0.0-beta.33", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", From 1dd3d62b6d395b98339babbbaf704180b4eb845d Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Sat, 18 May 2024 23:28:36 +0300 Subject: [PATCH 169/259] Adapt `v2.scores` to the new JSDoc format. --- routes/v2.ts | 106 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 84 insertions(+), 22 deletions(-) diff --git a/routes/v2.ts b/routes/v2.ts index de895965..30cf769e 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -646,43 +646,105 @@ import { scores_download } from "../api/v2/scores_download"; */ export const scores = { /** - * ##### Description - * `GET` https://osu.ppy.sh/api/v2/beatmaps/ - * + * ### `GET` [/v2/beatmaps/{beatmap}/scores](https://osu.ppy.sh/docs/index.html#get-beatmap-scores) + * ### `GET` [/v2/beatmaps/{beatmap}/scores/users/{user}](https://osu.ppy.sh/docs/index.html#get-a-user-beatmap-score) + * ### `GET` [/v2/beatmaps/{beatmap}/scores/users/{user}/all](https://osu.ppy.sh/docs/index.html#get-a-user-beatmap-scores) + * ### `GET` [/v2/beatmaps/{beatmap}/solo-scores](https://osu.ppy.sh/docs/index.html#get-beatmap-scores-non-legacy) * `async` Retrieves a list of scores by given parameters. * - * Check documentation for available parameters. + *   + * + * ### Global Parameters + * - `params.mode?` - Retrieve data for a specific gamemode. + * - `params.type` - Type of scores to retrieve. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Parameters for `params.type: 'leaderboard' | 'solo_scores'` + * - `params.leaderboard_type?: Type of leaderboard to retrieve.` + * - `params.beatmap_id` - ID of the beatmap to retrieve data from. + * - `params.mods?` - Retrieve scores for specific mods. + * + *   + * + * ### Parameters for `params.type: 'beatmap_best'` + * - `params.beatmap_id` - ID of the beatmap. + * - `params.user_id` - ID of the user. + * - `params.mods?` - Retrieve scores for specific mods. + * + *   + * + * ### Parameters for `params.type: 'beatmap_all'` + * - `params.beatmap_id` - ID of the beatmap. + * - `params.user_id` - ID of the user. + * + *   + * + * ### Parameters for `params.type:'user_best' | 'user_firsts' | 'user_recent' | 'user_pinned'` + * - `params.user_id` - ID of the user to retrieve data from. + * - `params.include_fails?` - Include failed scores. + * - `params.limit?` - Maximum number of scores to return. + * - `params.offset?` - Result offset for pagination. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-beatmap-scores) | [Check return types](../types/v2/scores_list.ts) * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) */ list: scores_list, /** - * ##### Description - * `GET` https://osu.ppy.sh/api/v2/scores/ - * + * ### `GET` [/v2/scores/{rulesetOrScore}/{score?}](https://osu.ppy.sh/docs/index.html#get-apiv2scoresrulesetorscorescore) * `async` Retrieves a score by given parameters. * - * @param {Object} params - Parameters to include in the request. - * @param params.id - ID of the score to retrieve. - * @param [params.mode] - Gamemode of the score. - * @param [addons] - Additional parameters to include in the request. + *   + * + * ### Parameters + * - `params.id` - ID of the score to retrieve. + * - `params.mode?` - Gamemode of the score. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2scoresrulesetorscorescore) | [Check return types](../types/v2/scores_details.ts) * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) */ details: scores_details, /** - * ##### Description - * `GET` https://osu.ppy.sh/api/v2/scores/ - * + * ### `GET` [/v2/scores/{rulesetOrScore}/{score}/download](https://osu.ppy.sh/docs/index.html#get-apiv2scoresrulesetorscorescoredownload) * `async` Downloads a score by given parameters. * - * @param {Object} params - Parameters to include in the request. - * @param params.id - ID of the score to download. - * @param [params.mode] - Gamemode of the score. - * @param [params.file_path] - Where to save the file. - * @param [addons] - Additional parameters to include in the request. + *   + * + * ### Parameters + * - `params.id` - ID of the score to download. + * - `params.mode?` - Gamemode of the score. + * - `params.file_path?` - Where to save the file. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   * - * @link [See documentation](https://github.com/cyperdark/osu-api-extended/wiki) + * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2scoresrulesetorscorescoredownload) | [Check return types](../types/v2/scores_download.ts) */ download: scores_download, }; From 7f394d9d076f0e47f29292f645c7e6c207ce9cba Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Sat, 18 May 2024 23:31:16 +0300 Subject: [PATCH 170/259] Fix typos in `v2.forums`'s JSDoc. --- routes/v2.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/routes/v2.ts b/routes/v2.ts index 30cf769e..e5e701f4 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -777,7 +777,7 @@ export const forums = { * - `params.limit?` - Maximum number of topics to return. * - `params.sort?` - Sort order of the topics. * - `params.cursor_string?` - [Cursor string for pagination.](https://osu.ppy.sh/docs/index.html#cursorstring) - * - `addons?` - Additional parameters to include in the request. ([See IDefaultParams](../types/index.ts)) + * - `addons?` - Additional parameters to include in the request. * *   * @@ -796,13 +796,13 @@ export const forums = { * ### `POST` [/v2/forums/topics/{topic}/reply](https://osu.ppy.sh/docs/index.html#reply-topic) * ### `PUT/PATCH` [/v2/forums/posts/{post}](https://osu.ppy.sh/docs/index.html#edit-post) * ### `PUT/PATCH` [/v2/forums/topics/{topic}](https://osu.ppy.sh/docs/index.html#edit-topic) - * * `async` Perform actions on forum topics via API. * *   * * ### Global Parameters * - `params.type` - Type of action to perform. + * - `addons?` - Additional parameters to include in the request. * * ### Parameters for `params.type:'create'` * - `params.forum_id` - ID of the forum to create the topic in. From e218521b0fb2ffa31a9c463c39fee85c11c1e615 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Sat, 18 May 2024 23:45:07 +0300 Subject: [PATCH 171/259] Add JSDoc to `v2.search` endpoint. --- routes/v2.ts | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/routes/v2.ts b/routes/v2.ts index e5e701f4..dfac6d9e 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -856,6 +856,50 @@ export const forums = { import { search_all } from '../api/v2/search'; +/** + * ### `GET` [/v2/search](https://osu.ppy.sh/docs/index.html#search) + * `async` Search for users and wiki pages. + * + *   + * + * ### Global Parameters + * - `params.type` - Type of search. + * - `params.query?` - Query to search for. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Parameters for `params.type:'site'` + * - `params.mode?` - Mode of the search. + * - `params.page?` - Page number of the search results. + * + *   + * + * ### Parameters for `params.type:'beatmaps'` + * - `params.mode?` - Gamemode to search for. + * - `params._played?` - Unknown parameter description. + * - `params._nsfw?` - Whether to include NSFW beatmaps. + * - `params.status?` - Filter by status. + * - `params.category?` - Filter by category. + * - `params.genre?` - Filter by genre. + * - `params.language?` - Filter by language. + * - `params.achieved_rank?` - Filter by achieved rank. + * - `params.extra?` - Filter by extra features. + * - `params.sort?` - Sort the results. + * - `params.cursor_string?` - Cursor string. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#search) | [Check return types](../types/v2/search.ts) + * + */ export const search = search_all; From f5a6a7dba463874000b5c274ffe6d115464b9ca4 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Wed, 22 May 2024 23:32:33 +0300 Subject: [PATCH 172/259] Add JSDoc to `v2.assets` endpoints. --- routes/v2.ts | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/routes/v2.ts b/routes/v2.ts index dfac6d9e..df12a3c6 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -908,8 +908,53 @@ import { assets_backgrounds } from "../api/v2/assets_backgrounds"; import { assets_dataFiles } from "../api/v2/assets_dataFiles"; +/** + * ##### Description + * Retrieve data from the assets API. + */ export const assets = { + /** + * ### `GET` [/v2/seasonal-backgrounds](https://osu.ppy.sh/docs/index.html#get-apiv2seasonal-backgrounds) + * `async` Retrieves seasonal or beatmap backgrounds. + * + *   + * + * ### Global Parameters + * - `params.type` - Source of the background. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Parameters for `params.type:'beatmapset'` + * - `params.set_id` - ID of the beatmapset. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2seasonal-backgrounds) | [Check return types](../types/v2/assets_backgrounds.ts) + */ backgrounds: assets_backgrounds, + /** + * ### `GET` `https://data.ppy.sh/` + * `async` Retrieves all urls from the data API. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2seasonal-backgrounds) | [Check return types](../types/v2/assets_backgrounds.ts) + */ dataFiles: assets_dataFiles }; From 11f97ca21d6520dfc11df327f965e5916cffb3ae Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Wed, 22 May 2024 23:32:43 +0300 Subject: [PATCH 173/259] Add JSDoc to `v2.news` endpoints. --- routes/v2.ts | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/routes/v2.ts b/routes/v2.ts index df12a3c6..5eb550a7 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -964,8 +964,56 @@ import { news_list } from "../api/v2/news_list"; import { news_details } from "../api/v2/news_details"; +/** + * ##### Description + * Retrieve data from the news API. + */ export const news = { + /** + * ### `GET` [/v2/news](https://osu.ppy.sh/docs/index.html#get-news-listing) + * `async` Get a list of all the news based on certain criteria. + * + *   + * + * ### Parameters + * - `params.from_year?` - Year to return posts from. + * - `params.limit?` - Maximum number of posts to return. + * - `params.cursor_string?` - [Cursor string for pagination.](https://osu.ppy.sh/docs/index.html#cursorstring) + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-news-listing) | [Check return types](../types/v2/news_list.ts) + */ list: news_list, + /** + * ### `GET` [/v2/news/{news}](https://osu.ppy.sh/docs/index.html#get-news-post) + * `async` Retrieves a single news post based on given parameters. + * + *   + * + * ### Parameters + * - `params.news_id` - ID of the news post. + * - `params.key?` - Type of the id parameter. + * + *   + * + * ### Usage Example + * ``` + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-news-post) | [Check return types](../types/v2/news_details.ts) + */ details: news_details, }; From ebb37f87a324ea1558f7b8cdec6c5abbc7d5be4d Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Wed, 22 May 2024 23:33:59 +0300 Subject: [PATCH 174/259] Change property name in `v2/search.ts`. --- api/v2/search.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/v2/search.ts b/api/v2/search.ts index 05dfe9a1..b6e5e47f 100644 --- a/api/v2/search.ts +++ b/api/v2/search.ts @@ -7,7 +7,7 @@ import { request } from "../../utility/request"; type params = ({ type: 'site'; - mode?: 'all' | 'user' | 'wiki_page'; + location?: 'all' | 'user' | 'wiki_page'; query?: string; page?: number; } | { From 398e52bb52c0e55ec4e433c6df03bdc10423a67d Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Wed, 22 May 2024 23:35:01 +0300 Subject: [PATCH 175/259] Change param name in JSDoc of `v2.search`. --- routes/v2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/v2.ts b/routes/v2.ts index 5eb550a7..1d44fe4b 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -870,7 +870,7 @@ import { search_all } from '../api/v2/search'; *   * * ### Parameters for `params.type:'site'` - * - `params.mode?` - Mode of the search. + * - `params.location?` - Page to search on. * - `params.page?` - Page number of the search results. * *   From 0d89fa49d3312bdc2e565538459f326375231adf Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Wed, 22 May 2024 23:36:54 +0300 Subject: [PATCH 176/259] Change parameters in `v2/news_details.ts`. Changes made according to https://osu.ppy.sh/docs/index.html#get-news-post --- api/v2/news_details.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/api/v2/news_details.ts b/api/v2/news_details.ts index 4ea95f8e..5d9d5c6a 100644 --- a/api/v2/news_details.ts +++ b/api/v2/news_details.ts @@ -8,17 +8,17 @@ type Response = NewsDetailsResponse & IError; export const news_details = async (params: { - news_id: string; - key?: 'id' | null; + news_query: string; + key: 'id' | 'slug' | null; }, addons?: IDefaultParams): Promise => { - if (params.news_id == null) { - return handleErrors(`Specify news id`) as Response + if (params.news_query == null) { + return handleErrors(`Specify a query`) as Response }; - const data = await request(`https://osu.ppy.sh/api/v2/news/${params.news_id}`, { + const data = await request(`https://osu.ppy.sh/api/v2/news/${params.news_query}`, { method: 'GET', - params: { key: params?.key }, + params: { key: (params.key === 'slug' ? undefined : params.key) }, addons, }); From 4af013fff0ff2884ff48558ee40a9888a969f3d4 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Wed, 22 May 2024 23:37:55 +0300 Subject: [PATCH 177/259] Change params in JSDoc of `v2.news_details`. --- routes/v2.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/routes/v2.ts b/routes/v2.ts index 1d44fe4b..290fd603 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -1000,8 +1000,8 @@ export const news = { *   * * ### Parameters - * - `params.news_id` - ID of the news post. - * - `params.key?` - Type of the id parameter. + * - `params.query` - ID or slug of the news post. + * - `params.key` - Type of the query. * *   * From 69ff1005503c538e03c838162b89f3c56f3e5877 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Wed, 22 May 2024 23:40:59 +0300 Subject: [PATCH 178/259] Remove useless param in `v2/notifications_list.ts`. As the API Docs says: "This endpoint returns a list of the user's unread notifications.", meaning only unread notifs will be returned, so no reason for this parameter. --- api/v2/notifications_list.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/api/v2/notifications_list.ts b/api/v2/notifications_list.ts index c7690a21..f3e80112 100644 --- a/api/v2/notifications_list.ts +++ b/api/v2/notifications_list.ts @@ -9,7 +9,6 @@ type Response = NotificationsListResponse & IError; export const notifications_list = async (params: { max_id: string; - unreaded_only: boolean; }, addons?: IDefaultParams): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/notifications`, { method: 'GET', @@ -22,8 +21,6 @@ export const notifications_list = async (params: { if (data.error) return handleErrors(data.error); - if (params.unreaded_only == true && !('error' in data)) - data.notifications = data.notifications.filter((r: any) => r.is_read == false); return data; }; \ No newline at end of file From fd5aa04fdb916e15acbdb93df2d29b51383a7592 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Wed, 22 May 2024 23:44:22 +0300 Subject: [PATCH 179/259] Fix types in `v2/notifications_actions.ts`. As the API says, every parameter passed is optional. (https://osu.ppy.sh/docs/index.html#mark-notifications-as-read) --- api/v2/notification_actions.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/api/v2/notification_actions.ts b/api/v2/notification_actions.ts index 47f037d2..36805c86 100644 --- a/api/v2/notification_actions.ts +++ b/api/v2/notification_actions.ts @@ -9,16 +9,16 @@ type params = ({ // ids: number[]; identities?: { - category: string; - object_id: string - object_type: string + category?: string; + object_id?: string + object_type?: string }[]; notifications?: { - category: string; - id: number; - object_id: string; - object_type: string; + category?: string; + id?: number; + object_id?: string; + object_type?: string; }[] }); @@ -40,9 +40,9 @@ export const notification_actions = async (params: T, addons?: url += '/notifications/mark-read'; method = 'POST'; - if (params.notifications == null && params.identities == null) { - return handleErrors(`Missing on of parameters`) as Response; - }; + // if (params.notifications == null && params.identities == null) { + // return handleErrors(`Missing on of parameters`) as Response; + // }; // params.ids.forEach((r, index) => object[`identities[${index}][id]`] = r); From 6553f719040aa62e14f7bed52119266c32992cca Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Wed, 22 May 2024 23:44:59 +0300 Subject: [PATCH 180/259] Fix typo in param of `v2/notifications_actions.ts`. --- api/v2/notification_actions.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/v2/notification_actions.ts b/api/v2/notification_actions.ts index 36805c86..5f327a72 100644 --- a/api/v2/notification_actions.ts +++ b/api/v2/notification_actions.ts @@ -4,7 +4,7 @@ import { handleErrors } from "../../utility/handleErrors"; type params = ({ - type: 'mark_as_readed'; + type: 'mark_as_read'; // ids: number[]; @@ -24,7 +24,7 @@ type params = ({ type Response = - T extends 'mark_as_readed' + T extends 'mark_as_read' ? "" & IError : IError; @@ -36,7 +36,7 @@ export const notification_actions = async (params: T, addons?: switch (params.type) { - case 'mark_as_readed': + case 'mark_as_read': url += '/notifications/mark-read'; method = 'POST'; From 11fd3c9f5db2d329696814642d989eece67890a8 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Wed, 22 May 2024 23:46:27 +0300 Subject: [PATCH 181/259] Add JSDoc to `v2.notifications` endpoints. --- routes/v2.ts | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/routes/v2.ts b/routes/v2.ts index 290fd603..a34a3c91 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -1024,8 +1024,64 @@ import { notifications_list } from '../api/v2/notifications_list'; import { notification_actions } from '../api/v2/notification_actions'; +/** + * ##### Description + * Retrieve data from the notifications API. + */ export const notifications = { + /** + * ### `GET` [/v2/notifications](https://osu.ppy.sh/docs/index.html#get-notifications) + * `async` Retrieves a list of the user's unread notifications. + * + *   + * + * ### Parameters + * - `params.max_id` - Maximum id fetched. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ``` + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-notifications) | [Check return types](../types/v2/notifications_list.ts) + */ list: notifications_list, + /** + * ### `POST` [/v2/notifications/mark-read](https://osu.ppy.sh/docs/index.html#mark-notifications-as-read) + * `async` Perform certain actions via the notifications API. + * + *   + * + * ### Global Parameters + * - `params.type` - Type of the action. + * + *   + * + * ### Parameters for `params.type:'mark_as_read'` + * - `params.identities[].category?` - Category of the identity. + * - `params.identities[].object_id?` Id of the object that triggered the notification. + * - `params.identities[].object_type?` Type of the object that triggered the notification. + * - `params.notifications[].category?` - Category of the notification. + * - `params.notifications[].object_id?` Id of the object that triggered the notification. + * - `params.notifications[].object_type?` Type of the object that triggered the notification. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#mark-notifications-as-read) | [Check return types](../types/v2/notification_actions.ts) + */ actions: notification_actions, }; From 53897f1099b9f20ba1e2109d091ba3e884f70037 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Wed, 22 May 2024 23:47:18 +0300 Subject: [PATCH 182/259] Add forgotten param in JSDoc of `v2.news.list`; --- routes/v2.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/routes/v2.ts b/routes/v2.ts index a34a3c91..d91c6b40 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -1002,6 +1002,7 @@ export const news = { * ### Parameters * - `params.query` - ID or slug of the news post. * - `params.key` - Type of the query. + * - `addons?` - Additional parameters to include in the request. * *   * From 4cf3d66e5539a8863eafe745c105961003d099a1 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Thu, 23 May 2024 00:00:32 +0300 Subject: [PATCH 183/259] Add JSDoc to `v2.ranking` endpoints. --- routes/v2.ts | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/routes/v2.ts b/routes/v2.ts index d91c6b40..823da42a 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -1091,7 +1091,60 @@ export const notifications = { import { ranking_list } from "../api/v2/ranking_list"; +/** + * ##### Description + * Retrieve data from the ranking API. + */ export const ranking = { + /** + * ### `GET` [/v2/rankings/{mode}/{type}](https://osu.ppy.sh/docs/index.html#get-ranking) + * ### `GET` [/v2/rankings/kudosu](https://osu.ppy.sh/docs/index.html#get-kudosu-ranking) + * + *   + * + * ### Global Parameters + * - `params.type` - Type of ranking search. + * - `params.page?` - Page number of the search results. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Parameters for `params.type:'charts'` + * - `params.spotlight_id?` - ID of the spotlight. + * - `params.mode?` - Gamemode to search for. + * - `params.filter?` - Filter by type. + * + *   + * + * ### Parameters for `params.type:'country'` + * - `params.mode?` - Gamemode to search for. + * - `params.filter?` - Filter by type. + * + *   + * + * #### Parameters for `params.type:'performance'` + * - `params.mode?` - Gamemode to search for. + * - `params.filter?` - Filter by type. + * - `params.country_code?` - Country code to search for. + * - `params.variant?` - Filter by mania variant. + * + *   + * + * ### Parameters for `params.type:'score'` + * - `params.mode?` - Gamemode to search for. + * - `params.filter?` - Filter by type. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-ranking) | [Check return types](../types/v2/ranking_list.ts) + */ list: ranking_list, }; From acad88409c7d03ae361b2bee4cbcfec2d96d2280 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Thu, 23 May 2024 00:02:37 +0300 Subject: [PATCH 184/259] Add JSDoc to `v2.spotlights` endpoints. --- routes/v2.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/routes/v2.ts b/routes/v2.ts index 823da42a..4f32648d 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -1153,7 +1153,31 @@ export const ranking = { import { spotlights_list } from "../api/v2/spotlights_list"; +/** + * ##### Description + * Retrieve data from the spotlights API. + */ export const spotlights = { + /** + * ### `GET` [/v2/spotlights](https://osu.ppy.sh/docs/index.html#get-spotlights) + * `async` Retrieve a list of spotlights. + * + *   + * + * ### Parameters + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-spotlights) | [Check return types](../types/v2/spotlights_list.ts) + */ list: spotlights_list, }; From f24b109357eca99e00d0285f446daa06bfeddf74 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Thu, 23 May 2024 00:03:39 +0300 Subject: [PATCH 185/259] Fix typo in JSDoc of `v2.notifications.actions`. --- routes/v2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/v2.ts b/routes/v2.ts index 4f32648d..bfbf0211 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -1060,6 +1060,7 @@ export const notifications = { * * ### Global Parameters * - `params.type` - Type of the action. + * - `addons?` - Additional parameters to include in the request. * *   * @@ -1070,7 +1071,6 @@ export const notifications = { * - `params.notifications[].category?` - Category of the notification. * - `params.notifications[].object_id?` Id of the object that triggered the notification. * - `params.notifications[].object_type?` Type of the object that triggered the notification. - * - `addons?` - Additional parameters to include in the request. * *   * From 46d0be9f414a82af944d58da701b7deef6ec8c6b Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Thu, 23 May 2024 00:08:50 +0300 Subject: [PATCH 186/259] Add JSDoc to `v2.wiki` endpoints. & add forgotten description for `v2.ranking.list`. --- routes/v2.ts | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/routes/v2.ts b/routes/v2.ts index bfbf0211..5eed0151 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -1099,6 +1099,7 @@ export const ranking = { /** * ### `GET` [/v2/rankings/{mode}/{type}](https://osu.ppy.sh/docs/index.html#get-ranking) * ### `GET` [/v2/rankings/kudosu](https://osu.ppy.sh/docs/index.html#get-kudosu-ranking) + * `async` Retrieves a ranking list based on given parameters. * *   * @@ -1186,7 +1187,33 @@ export const spotlights = { import { wiki_details } from "../api/v2/wiki_details"; +/** + * ##### Description + * Retrieve data from the wiki API. + */ export const wiki = { + /** + * ### `GET` [/v2/wiki/{locale}/{path}](https://osu.ppy.sh/docs/index.html#get-wiki-page) + * `async` Retrieve a wiki page or image data. + * + *   + * + * ### Parameters + * - `params.locale` - Two-letter language code of the wiki page. + * - `params.path_name` - Path of the wiki page. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * #### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-wiki-page) | [Check return types](../types/v2/wiki_details.ts) + */ details: wiki_details, }; From ac794b16848a0bc05691dfb853eff8624e661b6a Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Thu, 23 May 2024 22:18:46 +0300 Subject: [PATCH 187/259] Add `addons` param to `v2/me_download_quota.ts` --- api/v2/me_download_quota.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/api/v2/me_download_quota.ts b/api/v2/me_download_quota.ts index 90fec4b2..5cfa3226 100644 --- a/api/v2/me_download_quota.ts +++ b/api/v2/me_download_quota.ts @@ -1,5 +1,5 @@ import { credentials } from "../../utility/auth"; -import { IError } from "../../types"; +import { IError, IDefaultParams } from "../../types"; import { MedownloadquotaResponse } from "../../types/v2/me_download_quota"; import { request } from "../../utility/request"; import { handleErrors } from "../../utility/handleErrors"; @@ -8,7 +8,7 @@ import { handleErrors } from "../../utility/handleErrors"; type Response = MedownloadquotaResponse & IError; -export const me_download_quota = async (): Promise => { +export const me_download_quota = async (addons?: IDefaultParams): Promise => { if (credentials.method != 'lazer') { return handleErrors(`Login via lazer to use this endpoint`) as Response }; @@ -16,6 +16,7 @@ export const me_download_quota = async (): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/me/download-quota-check`, { method: 'GET', + addons, }); if (data.error) return handleErrors(data.error); From c1cdb043c06ef0ed38fa5f1bfb7635e42a401e75 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Thu, 23 May 2024 22:22:56 +0300 Subject: [PATCH 188/259] Add JSDoc to `v2.me` endpoints. --- routes/v2.ts | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/routes/v2.ts b/routes/v2.ts index 5eed0151..d26c59a4 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -1224,9 +1224,74 @@ import { me_friends } from "../api/v2/me_friends"; import { me_download_quota } from "../api/v2/me_download_quota"; +/** + * ##### Description + * Retrieve data from the me API. + */ export const me = { + /** + * ### `GET` [/v2/me/download-quota-check](https://osu.ppy.sh/docs/index.html#get-apiv2medownload-quota-check) + * `async` Get your download quota. (requires lazer authentication) + * + *   + * + * ### Parameters + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2medownload-quota-check) | [Check return types](../types/v2/me_download_quota.ts) + */ download_quota: me_download_quota, + /** + * ### `GET` [/v2/friends](https://osu.ppy.sh/docs/index.html#get-apiv2friends) + * `async` Get a list of your friends. (requires lazer authentication) + * + *   + * + * ### Parameters + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2friends) | [Check return types](../types/v2/me_friends.ts) + */ friends: me_friends, + /** + * ### `GET` [/v2/me/{mode?}](https://osu.ppy.sh/docs/index.html#get-own-data) + * `async` Get your own data. (requires lazer authentication) + * + *   + * + * ### Parameters + * - `params.mode?` - Gamemode to search for. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-own-data) | [Check return types](../types/v2/me_details.ts) + */ details: me_details, }; From e0cd502947f265e938c08cceeb5508bd6c8fd7fc Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Thu, 23 May 2024 22:30:14 +0300 Subject: [PATCH 189/259] Change params to optional in `v2/matches_list.ts`. --- api/v2/matches_list.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/v2/matches_list.ts b/api/v2/matches_list.ts index 32beb509..cb12c3d6 100644 --- a/api/v2/matches_list.ts +++ b/api/v2/matches_list.ts @@ -8,8 +8,8 @@ type Response = MatchesListResponse & IError; export const matches_list = async (params: { - limit: number; - sort: 'id_desc' | 'id_asc', + limit?: number; + sort?: 'id_desc' | 'id_asc', /** * Use cursor.match_id */ From 69095f8051cf297db6f088e03bbe665b6dc1ac03 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Thu, 23 May 2024 22:36:11 +0300 Subject: [PATCH 190/259] Fix parameters in `v2/me_details.ts`. --- api/v2/me_details.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/v2/me_details.ts b/api/v2/me_details.ts index 285ced0c..0fa85e6a 100644 --- a/api/v2/me_details.ts +++ b/api/v2/me_details.ts @@ -8,14 +8,14 @@ import { handleErrors } from "../../utility/handleErrors"; type Response = MeDetailsResponse & IError; -export const me_details = async (addons?: IDefaultParams & { mode: Modes_names }): Promise => { +export const me_details = async (params: { mode: Modes_names }, addons?: IDefaultParams): Promise => { if (credentials.method != 'lazer') { return handleErrors(`Login via lazer to use this endpoint`) as Response }; let url = 'https://osu.ppy.sh/api/v2/me'; - if (addons?.mode) url += `/${addons.mode}`; + if (params?.mode) url += `/${params.mode}`; const data = await request(url, { method: 'GET', From af892f302ba92e0524068afdaac5d8d0d6b9b466 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Thu, 23 May 2024 22:37:15 +0300 Subject: [PATCH 191/259] Fix parameters in `v2/matches_details.ts`. --- api/v2/matches_details.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/v2/matches_details.ts b/api/v2/matches_details.ts index f75b95f3..3b6af321 100644 --- a/api/v2/matches_details.ts +++ b/api/v2/matches_details.ts @@ -7,13 +7,13 @@ import { request } from "../../utility/request"; type Response = MatchesDetailsResponse & IError; -export const matches_details = async (match_id: number, addons?: IDefaultParams): Promise => { - if (match_id == null) { +export const matches_details = async (params: { match_id: number }, addons?: IDefaultParams): Promise => { + if (params.match_id == null) { return handleErrors(`Specify match id`) as Response; }; - const data = await request(`https://osu.ppy.sh/api/v2/matches/${match_id}`, { + const data = await request(`https://osu.ppy.sh/api/v2/matches/${params.match_id}`, { method: 'GET', addons, }); From 67cb279e2478247d06b20918642be168278e3878 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Thu, 23 May 2024 22:39:17 +0300 Subject: [PATCH 192/259] Add JSDoc to `v2.matches` endpoints. --- routes/v2.ts | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/routes/v2.ts b/routes/v2.ts index d26c59a4..a49d14e8 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -1301,8 +1301,56 @@ import { matches_list } from "../api/v2/matches_list"; import { matches_details } from "../api/v2/matches_details"; +/** + * ##### Description + * Retrieve data from the matches API. + */ export const matches = { + /** + * ### `GET` [/v2/matches](https://osu.ppy.sh/docs/index.html#get-apiv2matches) + * `async` Get a list of matches. + * + *   + * + * ### Parameters + * - `params.after_id` - ID of the match after which the matches will be returned. + * - `params.limit?` - Maximum number of matches to return. + * - `params.sort?` - Sort order of the matches. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2matches) | [Check return types](../types/v2/matches_list.ts) + */ list: matches_list, + /** + * ### `GET` [/v2/matches/{match}](https://osu.ppy.sh/docs/index.html#get-apiv2matchesmatch) + * `async` Get a match by certain criteria. + * + *   + * + * ### Parameters + * - `params.match_id` - ID of the match. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2matchesmatch) | [Check return types](../types/v2/matches_details.ts) + */ details: matches_details, }; From 22ac034f3f05744fc1dc5a9d167354c102150796 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Thu, 23 May 2024 22:53:19 +0300 Subject: [PATCH 193/259] Add `addons` param to `v2/chat_channels_list.ts`. --- api/v2/chat_channels_list.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/v2/chat_channels_list.ts b/api/v2/chat_channels_list.ts index 871ef93a..13089bd4 100644 --- a/api/v2/chat_channels_list.ts +++ b/api/v2/chat_channels_list.ts @@ -1,11 +1,11 @@ -import { IError } from "../../types"; +import {IDefaultParams, IError} from "../../types"; import { chatChannelsListResponse } from "../../types/v2/chat_channels_list"; import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; -export const chat_channels_list = async (): Promise => { +export const chat_channels_list = async (addons?: IDefaultParams): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/chat/channels`, { method: 'GET', }); From 26a4bb42597c8e3f0886c2e0a4bdd13a7209ab40 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Thu, 23 May 2024 23:08:23 +0300 Subject: [PATCH 194/259] Fix param typo in `v2/chat_channels_actions.ts`. --- api/v2/chat_channels_actions.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/v2/chat_channels_actions.ts b/api/v2/chat_channels_actions.ts index 71b8c808..fae51f62 100644 --- a/api/v2/chat_channels_actions.ts +++ b/api/v2/chat_channels_actions.ts @@ -18,7 +18,7 @@ type params = ({ id: number; user_id: number; } | { - type: 'readed'; + type: 'read'; channel_id: number; message_id: number; @@ -32,7 +32,7 @@ type Response = ? chatChannelsActionsJoinResponse & IError : T extends 'leave' ? "" & IError - : T extends 'readed' + : T extends 'read' ? "" & IError : IError; @@ -76,7 +76,7 @@ export const chat_channels_actions = async (params: T, addons? method = 'DELETE'; break; - case 'readed': + case 'read': if (params.channel_id == null || params.message_id == null) { return handleErrors(`Missing required parameters`) as Response; }; From 5f5a215f6f9a9a8188c5c1d091ad8756f8cbad68 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Thu, 23 May 2024 23:08:38 +0300 Subject: [PATCH 195/259] Change param name in `v2/chat_channels_actions.ts`. --- api/v2/chat_channels_actions.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/api/v2/chat_channels_actions.ts b/api/v2/chat_channels_actions.ts index fae51f62..94185f52 100644 --- a/api/v2/chat_channels_actions.ts +++ b/api/v2/chat_channels_actions.ts @@ -10,12 +10,12 @@ type params = ({ is_action: boolean; - id: number; + channel_id: number; message: string; } | { type: 'join' | 'leave'; - id: number; + channel_id: number; user_id: number; } | { type: 'read'; @@ -45,34 +45,34 @@ export const chat_channels_actions = async (params: T, addons? switch (params.type) { case 'send': - if (params.id == null || params.message == null || params.is_action == null) { + if (params.channel_id == null || params.message == null || params.is_action == null) { return handleErrors(`Missing required parameters`) as Response; }; - url += `/chat/channels/${params.id}/messages`; + url += `/chat/channels/${params.channel_id}/messages`; object['message'] = params.message; object['is_action'] = params.is_action; break; case 'join': - if (params.id == null || params.user_id == null) { + if (params.channel_id == null || params.user_id == null) { return handleErrors(`Missing required parameters`) as Response; }; - url += `/chat/channels/${params.id}/users/${params.user_id}`; + url += `/chat/channels/${params.channel_id}/users/${params.user_id}`; method = 'PUT'; break; case 'leave': - if (params.id == null || params.user_id == null) { + if (params.channel_id == null || params.user_id == null) { return handleErrors(`Missing required parameters`) as Response; }; - url += `/chat/channels/${params.id}/users/${params.user_id}`; + url += `/chat/channels/${params.channel_id}/users/${params.user_id}`; method = 'DELETE'; break; From b6d30aa14a1a4513a71a001a6263121eff22d6b3 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Thu, 23 May 2024 23:12:54 +0300 Subject: [PATCH 196/259] Fix typo in param name of `v2/chat_list.ts`. --- api/v2/chat_list.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/v2/chat_list.ts b/api/v2/chat_list.ts index 4a1b539a..7bf16157 100644 --- a/api/v2/chat_list.ts +++ b/api/v2/chat_list.ts @@ -8,7 +8,7 @@ type Response = ChatListResponse[] & IError; export const chat_list = async (params: { - unreaded?: boolean; + unread?: boolean; sort?: 'date_desc' | 'date_asc'; }, addons?: IDefaultParams): Promise => { let data = await request(`https://osu.ppy.sh/api/v2/chat/presence/`, { @@ -25,7 +25,7 @@ export const chat_list = async (params: { data.sort((a: any, b: any) => b.last_message_id - a.last_message_id); - if (params.unreaded == true) + if (params.unread == true) data = data.filter((r: any) => r.last_read_id != r.last_message_id); From 450beb14b95f958b4a435ef8575b127d906bc7c6 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Thu, 23 May 2024 23:28:36 +0300 Subject: [PATCH 197/259] Fix parameters in `v2/chat_details.ts`. --- api/v2/chat_details.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/v2/chat_details.ts b/api/v2/chat_details.ts index 341a6877..1e9ac078 100644 --- a/api/v2/chat_details.ts +++ b/api/v2/chat_details.ts @@ -7,13 +7,13 @@ import { request } from "../../utility/request"; type Response = ChatDetailsResponse & IError; -export const chat_details = async (channel_id: number, addons?: IDefaultParams): Promise => { - if (channel_id == null) { +export const chat_details = async (params: { channel_id: number }, addons?: IDefaultParams): Promise => { + if (params.channel_id == null) { return handleErrors(`Specify channel id`) as Response; }; - const data = await request(`https://osu.ppy.sh/api/v2/chat/channels/${channel_id}`, { + const data = await request(`https://osu.ppy.sh/api/v2/chat/channels/${params.channel_id}`, { method: 'GET', addons, }); From 76a209f07446a915c197cd0909f3b996151468b3 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Thu, 23 May 2024 23:29:40 +0300 Subject: [PATCH 198/259] Add JSDoc to `v2.chat` endpoints. --- routes/v2.ts | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) diff --git a/routes/v2.ts b/routes/v2.ts index a49d14e8..d30be999 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -1366,14 +1366,153 @@ import { chat_details } from "../api/v2/chat_details"; import { chat_actions } from "../api/v2/chat_actions"; +/** + * ##### Description + * Retrieve data from the chat API. + */ export const chat = { + /** + * ##### Description + * Covers API endpoints related to chat channels. + */ channels: { + /** + * ### `GET` [/v2/chat/channels](https://osu.ppy.sh/docs/index.html#get-channel-list) + * `async` Retrieves a list of all joinable public channels. (Requires lazer authentication) + * + *   + * + * ### Parameters + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-channel-list) | [Check return types](../types/v2/chat_channels_list.ts) + */ list: chat_channels_list, + /** + * ### `POST` [/v2/chat/channels/{channel}/messages](https://osu.ppy.sh/docs/index.html#send-message-to-channel) + * ### `PUT` [/v2/chat/channels/{channel}/users/{user}](https://osu.ppy.sh/docs/index.html#join-channel) + * ### `DELETE` [/v2/chat/channels/{channel}/users/{user}](https://osu.ppy.sh/docs/index.html#leave-channel) + * ### `PUT` [/v2/chat/channels/{channel}/mark-as-read/{message}](https://osu.ppy.sh/docs/index.html#mark-channel-as-read) + * `async` Performs a set of actions on a list of channels. (Requires lazer authentication) + * + *   + * + * ### Global Parameters + * - `params.type` - Type of action to perform. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Parameters for `params.type: 'send'` + * - `params.id` - The ID of the channel to send to. + * - `params.message` - The message to send. + * - `params.is_action` - Whether the message is an action. + * + *   + * + * ### Parameters for `params.type: 'join' | 'leave'` + * - `params.id` - The ID of the channel. + * - `params.user_id` - The ID of the user. + * + *   + * + * ### Parameters for `params.type: 'read'` + * - `params.channel_id` - The ID of the channel. + * - `params.message_id` - The ID of the user. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#send-message-to-channel) | [Check return types](../types/v2/chat_channels_actions.ts) + */ actions: chat_channels_actions, }, list: chat_list, + /** + * ### `GET [/v2/chat/channels/{channel}/messages](https://osu.ppy.sh/docs/index.html#get-channel-messages) + * `async` Get a list of messages in a channel. (Requires lazer authentication) + * + *   + * + * ### Parameters + * - `params.id` - The ID of the channel. + * - `params.limit?` - Maximum number of messages to return. + * - `params.since?` - Message id to start returning messages from. + * - `params.until?` - Message id to end returning messages from. + * - `params.return_object?` - Whether to return object. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-channel-messages) | [Check return types](../types/v2/chat_messages.ts) + */ messages: chat_messages, + /** + * ### `GET` [/v2/chat/updates](https://osu.ppy.sh/docs/index.html#get-updates) + * `async` Retrieves the list of channels the current User is in. (Requires lazer authentication) + * + *   + * + * ### Parameters + * - `params.after_id` - ID of the channel after which the channels will be returned. + * - `params.includes` - List of fields to include in the response. + * - `params.history_since` - Silence history since this id. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-updates) | [Check return types](../types/v2/chat_updates.ts) + */ updates: chat_updates, + /** + * ### `GET` [/v2/chat/channels/{channel}](https://osu.ppy.sh/docs/index.html#get-channel) + * `async` Get a specific channel. (Requires lazer authentication) + * + *   + * + * ### Parameters + * - `params.channel_id` - The ID of the channel. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-channel) | [Check return types](../types/v2/chat_channels.ts) + */ details: chat_details, actions: chat_actions, }; From bf96e76aa53d3188c4c22b4bf03cd8b5547e5765 Mon Sep 17 00:00:00 2001 From: ck <2-ck@users.noreply.git.lab> Date: Sun, 26 May 2024 02:08:00 +0300 Subject: [PATCH 199/259] revert back to `news_id` --- api/v2/news_details.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/v2/news_details.ts b/api/v2/news_details.ts index 5d9d5c6a..0e5e9ee4 100644 --- a/api/v2/news_details.ts +++ b/api/v2/news_details.ts @@ -8,15 +8,15 @@ type Response = NewsDetailsResponse & IError; export const news_details = async (params: { - news_query: string; + news_id: string; key: 'id' | 'slug' | null; }, addons?: IDefaultParams): Promise => { - if (params.news_query == null) { + if (params.news_id == null) { return handleErrors(`Specify a query`) as Response }; - const data = await request(`https://osu.ppy.sh/api/v2/news/${params.news_query}`, { + const data = await request(`https://osu.ppy.sh/api/v2/news/${params.news_id}`, { method: 'GET', params: { key: (params.key === 'slug' ? undefined : params.key) }, addons, From 1fdd6f8dd4761cb97e8fc264a89f21fbefd0fccd Mon Sep 17 00:00:00 2001 From: ck <2-ck@users.noreply.git.lab> Date: Sun, 26 May 2024 02:10:42 +0300 Subject: [PATCH 200/259] uncomment params check --- api/v2/notification_actions.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/v2/notification_actions.ts b/api/v2/notification_actions.ts index 5f327a72..30f5919d 100644 --- a/api/v2/notification_actions.ts +++ b/api/v2/notification_actions.ts @@ -40,9 +40,9 @@ export const notification_actions = async (params: T, addons?: url += '/notifications/mark-read'; method = 'POST'; - // if (params.notifications == null && params.identities == null) { - // return handleErrors(`Missing on of parameters`) as Response; - // }; + if (!Array.isArray(params.notifications) && !Array.isArray(params.identities)) { + return handleErrors(`Missing on of parameters`) as Response; + }; // params.ids.forEach((r, index) => object[`identities[${index}][id]`] = r); From 59148a8e6689aed63a21ac1f1f3acdffba17ea70 Mon Sep 17 00:00:00 2001 From: ck <2-ck@users.noreply.git.lab> Date: Sun, 26 May 2024 02:16:01 +0300 Subject: [PATCH 201/259] revert back to filter out `unreaded` --- api/v2/notifications_list.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/api/v2/notifications_list.ts b/api/v2/notifications_list.ts index f3e80112..43dfa097 100644 --- a/api/v2/notifications_list.ts +++ b/api/v2/notifications_list.ts @@ -9,6 +9,7 @@ type Response = NotificationsListResponse & IError; export const notifications_list = async (params: { max_id: string; + unreaded_only: boolean; }, addons?: IDefaultParams): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/notifications`, { method: 'GET', @@ -17,10 +18,11 @@ export const notifications_list = async (params: { }, addons, }); - if (data.error) return handleErrors(data.error); + if (params.unreaded_only == true && !('error' in data)) + data.notifications = data.notifications.filter((r: any) => r.is_read == false); return data; }; \ No newline at end of file From b338ed3635ad6b29478926069814f9e630ac2839 Mon Sep 17 00:00:00 2001 From: ck <2-ck@users.noreply.git.lab> Date: Sun, 26 May 2024 02:17:36 +0300 Subject: [PATCH 202/259] typo --- api/v2/search.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/v2/search.ts b/api/v2/search.ts index b6e5e47f..4d97d901 100644 --- a/api/v2/search.ts +++ b/api/v2/search.ts @@ -49,7 +49,7 @@ export const search_all = async (params: T, addons?: IDefaultP url += '/search'; - object.mode = params.mode; + object.mode = params.location; object.query = params.query; object.page = params.page; break; From 0337ab0dca524429d2dc88be91788c8799e87881 Mon Sep 17 00:00:00 2001 From: ck <2-ck@users.noreply.git.lab> Date: Sun, 26 May 2024 02:21:06 +0300 Subject: [PATCH 203/259] use `user` instead of `id` in params --- api/v2/users_details.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/v2/users_details.ts b/api/v2/users_details.ts index 06fd2afe..7a0ff07b 100644 --- a/api/v2/users_details.ts +++ b/api/v2/users_details.ts @@ -8,16 +8,16 @@ type Response = UsersDetailsResponse & IError; export const users_details = async (params: { - id?: number | string; + user?: number | string; mode?: Modes_names; key?: 'id' | 'username'; }, addons?: IDefaultParams): Promise => { - if (params.id == null) { + if (params.user == null) { return handleErrors(`Specify user id or name`) as Response; }; - const data = await request(`https://osu.ppy.sh/api/v2/users/${params.id}${params.mode ? `/${params.mode}` : ''}`, { + const data = await request(`https://osu.ppy.sh/api/v2/users/${params.user}${params.mode ? `/${params.mode}` : ''}`, { method: 'GET', params: { key: params.key }, addons, From 49c770f07c33c08ea2b808527747f12fbbe7063e Mon Sep 17 00:00:00 2001 From: ck <2-ck@users.noreply.git.lab> Date: Sun, 26 May 2024 02:25:30 +0300 Subject: [PATCH 204/259] Typo fixes & types fixes --- api/v2/beatmaps_download.ts | 8 ++++---- api/v2/users_events.ts | 9 ++++++--- types/index.ts | 17 +++++++++++++---- types/v2/me_details.ts | 10 ++++++++++ types/v2/me_friends.ts | 2 ++ types/v2/ranking_list_charts.ts | 2 ++ types/v2/ranking_list_performance.ts | 2 ++ types/v2/ranking_list_score.ts | 2 ++ types/v2/rooms_scores_all.ts | 10 ++++++---- types/v2/rooms_scores_single.ts | 18 ++++++++++++------ types/v2/rooms_scores_user_highest.ts | 16 ++++++++++------ types/v2/scores_details.ts | 7 +++++-- types/v2/scores_list_beatmap_all.ts | 6 ++++-- types/v2/scores_list_beatmap_best.ts | 8 ++++++-- types/v2/scores_list_leaderboard.ts | 6 ++++-- types/v2/scores_list_solo_scores.ts | 10 +++++----- types/v2/scores_list_user_best.ts | 6 ++++-- types/v2/scores_list_user_firsts.ts | 6 ++++-- types/v2/scores_list_user_pinned.ts | 8 +++++--- types/v2/scores_list_user_recent.ts | 6 ++++-- types/v2/scores_user_beamap.ts | 10 ++++++---- types/v2/users_details.ts | 18 +++++++++--------- types/v2/users_events.ts | 2 +- types/v2/users_list.ts | 14 +++++++++++--- utility/auth.ts | 4 ++-- utility/request.ts | 2 +- 26 files changed, 140 insertions(+), 69 deletions(-) diff --git a/api/v2/beatmaps_download.ts b/api/v2/beatmaps_download.ts index ac3c2d64..f678cfc3 100644 --- a/api/v2/beatmaps_download.ts +++ b/api/v2/beatmaps_download.ts @@ -14,9 +14,9 @@ type params = ({ host: 'osu' | 'osu_direct_mirror' | 'catboy'; file_path: string; - overwrite: boolean; + overwrite?: boolean; - progress_track_fn: (host: string, progress: number) => void; + progress_track_fn?: (host: string, progress: number) => void; } | { type: 'set'; @@ -25,9 +25,9 @@ type params = ({ file_path: string; no_video?: boolean; - overwrite: boolean; + overwrite?: boolean; - progress_track_fn: (host: string, progress: number) => void; + progress_track_fn?: (host: string, progress: number) => void; }); diff --git a/api/v2/users_events.ts b/api/v2/users_events.ts index bfd34484..20852c88 100644 --- a/api/v2/users_events.ts +++ b/api/v2/users_events.ts @@ -4,7 +4,7 @@ import { IDefaultParams, IError } from "../../types"; import { handleErrors } from "../../utility/handleErrors"; -type Response = UsersEventsResponse[] & IError; +type Response = UsersEventsResponse & IError; export const users_events = async ({ sort, cursor_string, type }: { @@ -26,8 +26,11 @@ export const users_events = async ({ sort, cursor_string, type }: { }; - const sorted = data.events.filter((r: any) => type.includes(r.type)); - data.events = sorted; + if (type) { + const sorted = data.events.filter((r: any) => type.includes(r.type)); + data.events = sorted; + }; + return data; }; \ No newline at end of file diff --git a/types/index.ts b/types/index.ts index da138681..04191f22 100644 --- a/types/index.ts +++ b/types/index.ts @@ -44,25 +44,31 @@ export type auth_scopes = ( )[]; -export type auth_params = { - timeout?: number; - tokenPath?: string; -} & ({ +export type auth_params = ({ method: 'v2'; client_id: number | string; client_secret: string; + timeout?: number; + tokenPath?: string; + scopes: auth_scopes; } | { method: 'v1'; api_key: string; + + timeout?: number; + tokenPath?: string; } | { method: 'lazer'; login: string; password: string; + + timeout?: number; + tokenPath?: string; } | { method: 'cli'; @@ -72,6 +78,9 @@ export type auth_params = { redirect_url: string; state: string; + timeout?: number; + tokenPath?: string; + scopes: auth_scopes; }); diff --git a/types/v2/me_details.ts b/types/v2/me_details.ts index 41d021eb..5373715f 100644 --- a/types/v2/me_details.ts +++ b/types/v2/me_details.ts @@ -117,6 +117,8 @@ export interface Statistics { count_100: number count_300: number count_50: number + count_geki: number + count_katu: number count_miss: number level: Level global_rank: number @@ -165,6 +167,8 @@ export interface Osu { count_100: number count_300: number count_50: number + count_geki: number + count_katu: number count_miss: number level: Level2 global_rank: number @@ -200,6 +204,8 @@ export interface Taiko { count_100: number count_300: number count_50: number + count_geki: number + count_katu: number count_miss: number level: Level3 global_rank: any @@ -235,6 +241,8 @@ export interface Fruits { count_100: number count_300: number count_50: number + count_geki: number + count_katu: number count_miss: number level: Level4 global_rank: any @@ -270,6 +278,8 @@ export interface Mania { count_100: number count_300: number count_50: number + count_geki: number + count_katu: number count_miss: number level: Level5 global_rank: any diff --git a/types/v2/me_friends.ts b/types/v2/me_friends.ts index bb86c75c..83f6304c 100644 --- a/types/v2/me_friends.ts +++ b/types/v2/me_friends.ts @@ -46,6 +46,8 @@ export interface Statistics { count_100: number count_300: number count_50: number + count_geki: number + count_katu: number count_miss: number level: Level global_rank?: number diff --git a/types/v2/ranking_list_charts.ts b/types/v2/ranking_list_charts.ts index 9534cd3e..d1a793d3 100644 --- a/types/v2/ranking_list_charts.ts +++ b/types/v2/ranking_list_charts.ts @@ -97,6 +97,8 @@ export interface Ranking { count_100: number count_300: number count_50: number + count_geki: number + count_katu: number count_miss: number level: Level global_rank: any diff --git a/types/v2/ranking_list_performance.ts b/types/v2/ranking_list_performance.ts index 5b4a46e3..58947093 100644 --- a/types/v2/ranking_list_performance.ts +++ b/types/v2/ranking_list_performance.ts @@ -12,6 +12,8 @@ export interface Ranking { count_100: number count_300: number count_50: number + count_geki: number + count_katu: number count_miss: number level: Level global_rank: number diff --git a/types/v2/ranking_list_score.ts b/types/v2/ranking_list_score.ts index 55ff7387..c68acc2b 100644 --- a/types/v2/ranking_list_score.ts +++ b/types/v2/ranking_list_score.ts @@ -12,6 +12,8 @@ export interface Ranking { count_100: number count_300: number count_50: number + count_geki: number + count_katu: number count_miss: number level: Level global_rank: number diff --git a/types/v2/rooms_scores_all.ts b/types/v2/rooms_scores_all.ts index 6d9dcda2..0d351813 100644 --- a/types/v2/rooms_scores_all.ts +++ b/types/v2/rooms_scores_all.ts @@ -59,16 +59,18 @@ export interface MaximumStatistics { } export interface Statistics { - ok: number - great: number + perfect?: number + good?: number + ok?: number + great?: number + meh?: number + miss?: number ignore_hit: number ignore_miss: number large_bonus: number small_bonus: number large_tick_hit: number slider_tail_hit: number - meh?: number - miss?: number large_tick_miss?: number } diff --git a/types/v2/rooms_scores_single.ts b/types/v2/rooms_scores_single.ts index c466eae4..0ff62a8f 100644 --- a/types/v2/rooms_scores_single.ts +++ b/types/v2/rooms_scores_single.ts @@ -46,8 +46,12 @@ export interface MaximumStatistics { } export interface Statistics { - ok: number - great: number + perfect?: number + good?: number + ok?: number + great?: number + meh?: number + miss?: number ignore_hit: number ignore_miss: number large_bonus: number @@ -157,10 +161,12 @@ export interface MaximumStatistics2 { } export interface Statistics2 { - ok: number - meh: number - miss: number - great: number + perfect?: number + good?: number + ok?: number + great?: number + meh?: number + miss?: number ignore_hit: number ignore_miss: number large_bonus: number diff --git a/types/v2/rooms_scores_user_highest.ts b/types/v2/rooms_scores_user_highest.ts index 17ab0b87..e6879cfa 100644 --- a/types/v2/rooms_scores_user_highest.ts +++ b/types/v2/rooms_scores_user_highest.ts @@ -46,10 +46,12 @@ export interface MaximumStatistics { } export interface Statistics { - ok: number - meh: number - miss: number - great: number + perfect?: number + good?: number + ok?: number + great?: number + meh?: number + miss?: number ignore_hit: number ignore_miss: number large_bonus: number @@ -148,10 +150,12 @@ export interface MaximumStatistics2 { } export interface Statistics2 { - ok: number + perfect?: number + good?: number + ok?: number + great?: number meh?: number miss?: number - great: number ignore_hit: number ignore_miss: number large_bonus: number diff --git a/types/v2/scores_details.ts b/types/v2/scores_details.ts index ac9231e2..40889976 100644 --- a/types/v2/scores_details.ts +++ b/types/v2/scores_details.ts @@ -45,9 +45,12 @@ export interface MaximumStatistics { export interface Statistics { - ok: number + perfect?: number + good?: number + ok?: number + great?: number + meh?: number miss?: number - great: number ignore_hit?: number large_tick_hit?: number slider_tail_hit?: number diff --git a/types/v2/scores_list_beatmap_all.ts b/types/v2/scores_list_beatmap_all.ts index 2d0ed0df..f7c43e19 100644 --- a/types/v2/scores_list_beatmap_all.ts +++ b/types/v2/scores_list_beatmap_all.ts @@ -39,8 +39,10 @@ export interface MaximumStatistics { export interface Statistics { - ok: number - great: number + perfect?: number + good?: number + ok?: number + great?: number meh?: number miss?: number } diff --git a/types/v2/scores_list_beatmap_best.ts b/types/v2/scores_list_beatmap_best.ts index cb410655..19dc8a85 100644 --- a/types/v2/scores_list_beatmap_best.ts +++ b/types/v2/scores_list_beatmap_best.ts @@ -44,8 +44,12 @@ export interface MaximumStatistics { } export interface Statistics { - ok: number - great: number + perfect?: number + good?: number + ok?: number + great?: number + meh?: number + miss?: number } export interface CurrentUserAttributes { diff --git a/types/v2/scores_list_leaderboard.ts b/types/v2/scores_list_leaderboard.ts index dcb705df..f8e2128b 100644 --- a/types/v2/scores_list_leaderboard.ts +++ b/types/v2/scores_list_leaderboard.ts @@ -42,10 +42,12 @@ export interface MaximumStatistics { export interface Statistics { + perfect?: number + good?: number ok?: number - great: number - miss?: number + great?: number meh?: number + miss?: number ignore_hit?: number ignore_miss?: number slider_tail_hit?: number diff --git a/types/v2/scores_list_solo_scores.ts b/types/v2/scores_list_solo_scores.ts index fadad585..66732488 100644 --- a/types/v2/scores_list_solo_scores.ts +++ b/types/v2/scores_list_solo_scores.ts @@ -42,14 +42,14 @@ export interface MaximumStatistics { } export interface Statistics { + perfect?: number + good?: number + ok?: number great?: number + meh?: number + miss?: number ignore_hit?: number slider_tail_hit?: number - ok?: number - miss?: number - good?: number - perfect?: number - meh?: number ignore_miss?: number } diff --git a/types/v2/scores_list_user_best.ts b/types/v2/scores_list_user_best.ts index a69e135e..ed1895a1 100644 --- a/types/v2/scores_list_user_best.ts +++ b/types/v2/scores_list_user_best.ts @@ -47,10 +47,12 @@ export interface MaximumStatistics { } export interface Statistics { + perfect?: number + good?: number ok?: number - great: number - miss?: number + great?: number meh?: number + miss?: number ignore_hit?: number ignore_miss?: number small_bonus?: number diff --git a/types/v2/scores_list_user_firsts.ts b/types/v2/scores_list_user_firsts.ts index b19fc79d..ede4b2d6 100644 --- a/types/v2/scores_list_user_firsts.ts +++ b/types/v2/scores_list_user_firsts.ts @@ -41,10 +41,12 @@ export interface MaximumStatistics { } export interface Statistics { + perfect?: number + good?: number ok?: number - miss?: number - great: number + great?: number meh?: number + miss?: number } export interface CurrentUserAttributes { diff --git a/types/v2/scores_list_user_pinned.ts b/types/v2/scores_list_user_pinned.ts index 13ddb5c1..7282ba82 100644 --- a/types/v2/scores_list_user_pinned.ts +++ b/types/v2/scores_list_user_pinned.ts @@ -42,10 +42,12 @@ export interface MaximumStatistics { export interface Statistics { - ok: number + perfect?: number + good?: number + ok?: number + great?: number meh?: number - miss: number - great: number + miss?: number } export interface CurrentUserAttributes { diff --git a/types/v2/scores_list_user_recent.ts b/types/v2/scores_list_user_recent.ts index 08f33c30..b5233e30 100644 --- a/types/v2/scores_list_user_recent.ts +++ b/types/v2/scores_list_user_recent.ts @@ -42,10 +42,12 @@ export interface MaximumStatistics { export interface Statistics { - ok: number + perfect?: number + good?: number + ok?: number + great?: number meh?: number miss?: number - great: number } export interface CurrentUserAttributes { diff --git a/types/v2/scores_user_beamap.ts b/types/v2/scores_user_beamap.ts index d23e05f8..e3c1f991 100644 --- a/types/v2/scores_user_beamap.ts +++ b/types/v2/scores_user_beamap.ts @@ -38,10 +38,12 @@ export interface MaximumStatistics { } export interface Statistics { - ok?: number; - great: number; - meh?: number; - miss?: number; + perfect?: number + good?: number + ok?: number + great?: number + meh?: number + miss?: number ignore_hit?: number; ignore_miss?: number; small_bonus?: number; diff --git a/types/v2/users_details.ts b/types/v2/users_details.ts index 52f99e65..37e129d3 100644 --- a/types/v2/users_details.ts +++ b/types/v2/users_details.ts @@ -10,25 +10,25 @@ export interface UsersDetailsResponse { is_supporter: boolean last_visit: string pm_friends_only: boolean - profile_colour?: string + profile_colour: string username: string cover_url: string - discord?: string + discord: string has_supported: boolean - interests?: string + interests: string join_date: string - location?: string + location: string max_blocks: number max_friends: number - occupation?: string + occupation: string playmode: string - playstyle?: string[] + playstyle: string[] post_count: number profile_order: string[] - title: any + title: string title_url: any - twitter?: string - website?: string + twitter: string + website: string country: Country cover: Cover kudosu: Kudosu diff --git a/types/v2/users_events.ts b/types/v2/users_events.ts index b5d5eb7d..514c9ef7 100644 --- a/types/v2/users_events.ts +++ b/types/v2/users_events.ts @@ -26,7 +26,7 @@ export interface Event { created_at: string; createdAt: string; id: number; - type: ActionType; + type: 'achievement' | 'beatmapPlaycount' | 'beatmapsetApprove' | 'beatmapsetDelete' | 'beatmapsetRevive' | 'beatmapsetUpdate' | 'beatmapsetUpload' | 'rank' | 'userSupportAgain' | 'userSupportFirst' | 'userSupportGift' | 'usernameChange'; scoreRank?: string; rank?: number; mode?: Modes_names; diff --git a/types/v2/users_list.ts b/types/v2/users_list.ts index 3d36eed3..60098410 100644 --- a/types/v2/users_list.ts +++ b/types/v2/users_list.ts @@ -52,6 +52,8 @@ export interface Osu { count_100: number count_300: number count_50: number + count_geki: number + count_katu: number count_miss: number level: Level global_rank: number @@ -87,9 +89,11 @@ export interface Taiko { count_100: number count_300: number count_50: number + count_geki: number + count_katu: number count_miss: number level: Level2 - global_rank?: number + global_rank: number global_rank_exp: any pp: number pp_exp: number @@ -122,9 +126,11 @@ export interface Fruits { count_100: number count_300: number count_50: number + count_geki: number + count_katu: number count_miss: number level: Level3 - global_rank?: number + global_rank: number global_rank_exp: any pp: number pp_exp: number @@ -157,9 +163,11 @@ export interface Mania { count_100: number count_300: number count_50: number + count_geki: number + count_katu: number count_miss: number level: Level4 - global_rank?: number + global_rank: number global_rank_exp: any pp: number pp_exp: number diff --git a/utility/auth.ts b/utility/auth.ts index bd9e28f2..9c45e221 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -56,8 +56,8 @@ export const cache = { v1: '', v2: '', - 'ratelimit-remaining': 0, - 'ratelimit-limit': 0, + 'ratelimit-remaining': 1200, + 'ratelimit-limit': 1200, }; diff --git a/utility/request.ts b/utility/request.ts index adcaabc5..79322fac 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -78,7 +78,7 @@ export const request: RequestType = (url, { method, headers, data, params = {}, if (addons.legacy_only != null) - params.legacy_only = params.legacy_only == true ? 1 : 0; + params.legacy_only = addons.legacy_only == true ? 1 : 0; const generate_query = sanitize_query(params); From 6ddb5112fce18f87f93c9eb9244b61515ff8b9c4 Mon Sep 17 00:00:00 2001 From: ck <2-ck@users.noreply.git.lab> Date: Sun, 26 May 2024 02:26:01 +0300 Subject: [PATCH 205/259] new option `include_variants` in users_list --- api/v2/users_list.ts | 9 +++++---- types/v2/users_details.ts | 9 +++++++++ types/v2/users_list.ts | 10 ++++++++++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/api/v2/users_list.ts b/api/v2/users_list.ts index 59a017a8..c17c707f 100644 --- a/api/v2/users_list.ts +++ b/api/v2/users_list.ts @@ -7,19 +7,20 @@ import { handleErrors } from "../../utility/handleErrors"; type Response = UsersLisResponse[] & IError; -export const users_list = async (ids: number[], addons?: IDefaultParams): Promise => { - if ((ids || [])?.length == 0) { +export const users_list = async (params: { ids: number[], include_variants?: boolean }, addons?: IDefaultParams): Promise => { + if ((params.ids || [])?.length == 0) { return handleErrors(`Specify at least one user id`) as Response; }; - if (ids.length > 50) { + if (params.ids.length > 50) { return handleErrors("No more than 50 users can be requested at once.") as Response; } const data = await request(`https://osu.ppy.sh/api/v2/users`, { method: 'GET', params: { - 'ids[]': ids + 'ids[]': params.ids, + include_variant_statistics: params.include_variants, }, addons }); diff --git a/types/v2/users_details.ts b/types/v2/users_details.ts index 37e129d3..ca4bcb75 100644 --- a/types/v2/users_details.ts +++ b/types/v2/users_details.ts @@ -150,6 +150,7 @@ export interface Statistics { grade_counts: GradeCounts country_rank: number rank: Rank + variants: Variant[] } export interface Level { @@ -169,6 +170,14 @@ export interface Rank { country: number } +export interface Variant { + mode: string + variant: string + country_rank: number + global_rank: number + pp: number +} + export interface UserAchievement { achieved_at: string achievement_id: number diff --git a/types/v2/users_list.ts b/types/v2/users_list.ts index 60098410..455114b3 100644 --- a/types/v2/users_list.ts +++ b/types/v2/users_list.ts @@ -181,6 +181,7 @@ export interface Mania { replays_watched_by_others: number is_ranked: boolean grade_counts: GradeCounts4 + variants: Variant[] } export interface Level4 { @@ -195,3 +196,12 @@ export interface GradeCounts4 { sh: number a: number } + + +export interface Variant { + mode: string + variant: string + country_rank: number + global_rank: number + pp: number +} \ No newline at end of file From ef94a2788d442d8e728ed66415d93c9fea6ed187 Mon Sep 17 00:00:00 2001 From: ck <2-ck@users.noreply.git.lab> Date: Sun, 26 May 2024 02:26:45 +0300 Subject: [PATCH 206/259] new tool `convertHits` --- tools/index.ts | 2 +- tools/objects.ts | 105 +++++++++++++++++++++++++++++++++++++++++++---- types/tools.ts | 15 +++++++ 3 files changed, 114 insertions(+), 8 deletions(-) diff --git a/tools/index.ts b/tools/index.ts index d269f97e..e9ebd877 100644 --- a/tools/index.ts +++ b/tools/index.ts @@ -5,7 +5,7 @@ export { calculate_accuracy } from "./accuracy"; export { calculate_mods } from "./mods"; export { country_details } from "./country"; export { calculate_rank } from "./rank"; -export { calculate_total_objects } from "./objects"; +export { calculate_total_objects, convert_hits } from "./objects"; export { calculate_net_pp } from "./net-pp"; diff --git a/tools/objects.ts b/tools/objects.ts index e3528373..04f53948 100644 --- a/tools/objects.ts +++ b/tools/objects.ts @@ -1,6 +1,6 @@ import { IError } from "../types"; import { GamemodeEnum } from "../types/enums"; -import { TotalObjectsResponse } from "../types/tools"; +import { ConvertHitsResponse, TotalObjectsResponse } from "../types/tools"; import { handleErrors } from "../utility/handleErrors"; @@ -18,6 +18,13 @@ type Hits = { ok?: any; meh?: any; miss?: any; + + count_100?: any; + count_300?: any; + count_50?: any; + count_geki?: any; + count_katu?: any; + count_miss?: any; }; type Response = TotalObjectsResponse & IError; @@ -30,12 +37,12 @@ export const calculate_total_objects = (hits: Hits, mode: GamemodeEnum | string }; - const geki = parseInt(hits?.geki || hits.perfect || '0'); - const h300 = parseInt(hits?.[300] || hits.great || '0'); - const katu = parseInt(hits?.katu || hits.good || '0'); - const h100 = parseInt(hits?.[100] || hits.ok || '0'); - const h50 = parseInt(hits?.[50] || hits.meh || '0'); - const h0 = parseInt(hits?.[0] || hits.miss || '0'); + const geki = parseInt(hits?.geki || hits.count_geki || hits.perfect || '0'); + const h300 = parseInt(hits?.[300] || hits.count_300 || hits.great || '0'); + const katu = parseInt(hits?.katu || hits.count_katu || hits.good || '0'); + const h100 = parseInt(hits?.[100] || hits.count_100 || hits.ok || '0'); + const h50 = parseInt(hits?.[50] || hits.count_50 || hits.meh || '0'); + const h0 = parseInt(hits?.[0] || hits.count_miss || hits.miss || '0'); let total_objects = 0; @@ -69,5 +76,89 @@ export const calculate_total_objects = (hits: Hits, mode: GamemodeEnum | string return { amount: total_objects, mode: mode, + hits: { + geki: geki, + 300: h300, + katu: katu, + 100: h100, + 50: h50, + 0: h0, + } } as Response; +}; + + + +type ResponseConvert = ConvertHitsResponse & IError; + + +export const convert_hits = (hits: Hits, mode: GamemodeEnum | string | number): ResponseConvert => { + if (Object.keys(hits).length == 0) { + return handleErrors('Provide hits (300, 100, 50, etc)') as ResponseConvert; + }; + + + const geki = parseInt(hits?.geki || hits.count_geki || hits.perfect || '0'); + const h300 = parseInt(hits?.[300] || hits.count_300 || hits.great || '0'); + const katu = parseInt(hits?.katu || hits.count_katu || hits.good || '0'); + const h100 = parseInt(hits?.[100] || hits.count_100 || hits.ok || '0'); + const h50 = parseInt(hits?.[50] || hits.count_50 || hits.meh || '0'); + const h0 = parseInt(hits?.[0] || hits.count_miss || hits.miss || '0'); + + let geki_fc = parseInt(hits?.geki || hits.count_geki || hits.perfect || '0'); + let h300_fc = parseInt(hits?.[300] || hits.count_300 || hits.great || '0'); + let katu_fc = parseInt(hits?.katu || hits.count_katu || hits.good || '0'); + let h100_fc = parseInt(hits?.[100] || hits.count_100 || hits.ok || '0'); + let h50_fc = parseInt(hits?.[50] || hits.count_50 || hits.meh || '0'); + let h0_fc = parseInt(hits?.[0] || hits.count_miss || hits.miss || '0'); + + + switch (mode) { + case 'osu': + case GamemodeEnum.osu: + h300_fc = h300 + h0; + h0_fc = 0; + break; + + case 'taiko': + case GamemodeEnum.taiko: + h300_fc = h300 + h0; + h0_fc = 0; + break; + + case 'fruits': + case GamemodeEnum.fruits: + h300_fc = h300 + h0; + h0_fc = 0; + break; + + case 'mania': + case GamemodeEnum.mania: + h300_fc = h300 + h0; + h0_fc = 0; + break; + + default: + return handleErrors(`Unsupported gamemode: ${mode}}`) as ResponseConvert; + }; + + + return { + hits: { + geki: geki, + 300: h300, + katu: katu, + 100: h100, + 50: h50, + 0: h0, + }, + fc: { + geki: geki_fc, + 300: h300_fc, + katu: katu_fc, + 100: h100_fc, + 50: h50_fc, + 0: h0_fc, + } + } as ResponseConvert; }; \ No newline at end of file diff --git a/types/tools.ts b/types/tools.ts index 6f1e979f..78a7548b 100644 --- a/types/tools.ts +++ b/types/tools.ts @@ -20,4 +20,19 @@ export interface RankResponse { export type TotalObjectsResponse = { amount: number; mode: string; + hits: TotalObjectsHits +}; + +export type ConvertHitsResponse = { + hits: TotalObjectsHits + fc: TotalObjectsHits +}; + +export interface TotalObjectsHits { + geki: number; + 300: number; + katu: number; + 100: number; + 50: number; + 0: number; }; \ No newline at end of file From 2e8b0671c018f64c3a5776fdc5ddfc90b64a7822 Mon Sep 17 00:00:00 2001 From: ck <2-ck@users.noreply.git.lab> Date: Sun, 26 May 2024 02:27:05 +0300 Subject: [PATCH 207/259] order mods --- tools/mods.ts | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/tools/mods.ts b/tools/mods.ts index 7d334a5c..4d9ff7bb 100644 --- a/tools/mods.ts +++ b/tools/mods.ts @@ -67,8 +67,10 @@ export const calculate_mods = (ModsName: Mod[] | string | number, order?: boolea let mods_id = 0; - let ModsArray = []; + const convertedParts = []; + + let ModsArray = []; if (Array.isArray(ModsName)) { ModsArray = ModsName.map(r => r.acronym.toLowerCase()); } @@ -88,103 +90,139 @@ export const calculate_mods = (ModsName: Mod[] | string | number, order?: boolea switch (mod_name) { case 'nf': mods_id += 1; + convertedParts.push('NF'); break; case 'ez': mods_id += 2; + convertedParts.push('EZ'); break; case 'td': mods_id += 4; + convertedParts.push('TD'); break; case 'hd': mods_id += 8; + convertedParts.push('HD'); break; case 'hr': mods_id += 16; + convertedParts.push('HR'); break; case 'sd': mods_id += 32; + convertedParts.push('SD'); break; case 'dt': mods_id += 64; + convertedParts.push('DT'); break; case 'rx': mods_id += 128; + convertedParts.push('RX'); break; case 'ht': mods_id += 256; + convertedParts.push('HT'); break; case 'nc': mods_id += 576; + convertedParts.push('NC'); break; case 'fl': mods_id += 1024; + convertedParts.push('FL'); break; case 'at': mods_id += 2048; + convertedParts.push('AT'); break; case 'so': mods_id += 4096; + convertedParts.push('SO'); break; case 'ap': mods_id += 8192; + convertedParts.push('AP'); break; case 'pf': mods_id += 16416; + convertedParts.push('PF'); break; case '4k': mods_id += 32768; + convertedParts.push('4K'); break; case '5k': mods_id += 65536; + convertedParts.push('5K'); break; case '6k': mods_id += 131072; + convertedParts.push('6K'); break; case '7k': mods_id += 262144; + convertedParts.push('7K'); break; case '8k': mods_id += 524288; + convertedParts.push('8K'); break; case 'fi': mods_id += 1048576; + convertedParts.push('FI'); break; case 'rd': mods_id += 2097152; + convertedParts.push('RD'); break; - case 'lm': + case 'cn': mods_id += 4194304; + convertedParts.push('CN'); break; case 'target': mods_id += 8388608; + convertedParts.push('TG'); break; case '9k': mods_id += 16777216; + convertedParts.push('9K'); break; case 'keycoop': mods_id += 33554432; + convertedParts.push('10K'); break; case '1k': mods_id += 67108864; + convertedParts.push('1K'); break; case '3k': mods_id += 134217728; + convertedParts.push('3K'); break; case '2k': mods_id += 268435456; + convertedParts.push('2K'); break; case 'scorev2': mods_id += 536870912; + convertedParts.push('v2'); break; case 'mr': mods_id += 1073741824; + convertedParts.push('MR'); + break; + + default: + convertedParts.push(mod_name.toUpperCase()); break; }; }; + convertedParts.sort((a, b) => ModsOrder[a.toLowerCase()] - ModsOrder[b.toLowerCase()]); return { number: mods_id, - name: ModsName, + name: convertedParts.join(''), } as Response; }; \ No newline at end of file From 7c99b36797a2209b1a8d194122bc40e208d96762 Mon Sep 17 00:00:00 2001 From: ck <2-ck@users.noreply.git.lab> Date: Sun, 26 May 2024 02:27:21 +0300 Subject: [PATCH 208/259] typo fix --- api/v2/notifications_list.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/v2/notifications_list.ts b/api/v2/notifications_list.ts index 43dfa097..45fb4123 100644 --- a/api/v2/notifications_list.ts +++ b/api/v2/notifications_list.ts @@ -9,7 +9,7 @@ type Response = NotificationsListResponse & IError; export const notifications_list = async (params: { max_id: string; - unreaded_only: boolean; + unread_only: boolean; }, addons?: IDefaultParams): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/notifications`, { method: 'GET', @@ -21,7 +21,7 @@ export const notifications_list = async (params: { if (data.error) return handleErrors(data.error); - if (params.unreaded_only == true && !('error' in data)) + if (params.unread_only == true && !('error' in data)) data.notifications = data.notifications.filter((r: any) => r.is_read == false); return data; From 17abc6f8e406b1b17016f3ffe3213a2f25835d8d Mon Sep 17 00:00:00 2001 From: ck Date: Tue, 4 Jun 2024 15:03:53 +0300 Subject: [PATCH 209/259] version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e26180ca..72f78595 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.33", + "version": "3.0.0-beta.34", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", From 2d468bf439a35fbde9c44bc523e01290b02b9fda Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Wed, 19 Jun 2024 15:17:30 +0300 Subject: [PATCH 210/259] Fix infinite whie loop --- tools/mods.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/mods.ts b/tools/mods.ts index 4d9ff7bb..0d57a96b 100644 --- a/tools/mods.ts +++ b/tools/mods.ts @@ -25,6 +25,8 @@ export const ModsToName = (modsNumber: number, order?: boolean): string => { convertedParts.push(bitValues[Math.log2(bit)]); }; bit <<= 1; + + if (bit == 0) break; }; convertedParts.sort((a, b) => ModsOrder[a.toLowerCase()] - ModsOrder[b.toLowerCase()]); @@ -41,6 +43,8 @@ export const ModsToName = (modsNumber: number, order?: boolean): string => { convertedParts += bitValues[Math.log2(bit)]; } bit <<= 1; + + if (bit == 0) break; }; return convertedParts; @@ -212,8 +216,8 @@ export const calculate_mods = (ModsName: Mod[] | string | number, order?: boolea mods_id += 1073741824; convertedParts.push('MR'); break; - - default: + + default: convertedParts.push(mod_name.toUpperCase()); break; }; From 76052451375ebec782cd9472265d9a496b29faed Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 29 Jul 2024 14:07:25 +0300 Subject: [PATCH 211/259] add daily challange types --- package.json | 2 +- types/v2/users_details.ts | 30 +++++++++++++++++++++++------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 72f78595..04cab910 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.34", + "version": "3.0.0-beta.35", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/types/v2/users_details.ts b/types/v2/users_details.ts index ca4bcb75..d45a01dd 100644 --- a/types/v2/users_details.ts +++ b/types/v2/users_details.ts @@ -8,26 +8,27 @@ export interface UsersDetailsResponse { is_deleted: boolean is_online: boolean is_supporter: boolean - last_visit: string + last_visit?: string pm_friends_only: boolean profile_colour: string username: string cover_url: string - discord: string + discord?: string has_supported: boolean interests: string join_date: string location: string max_blocks: number max_friends: number - occupation: string + occupation?: string playmode: string playstyle: string[] post_count: number + profile_hue: number profile_order: string[] - title: string + title?: string title_url: any - twitter: string + twitter?: string website: string country: Country cover: Cover @@ -38,6 +39,7 @@ export interface UsersDetailsResponse { badges: Badge[] beatmap_playcounts_count: number comments_count: number + daily_challenge_user_stats: DailyChallengeUserStats favourite_beatmapset_count: number follower_count: number graveyard_beatmapset_count: number @@ -64,6 +66,7 @@ export interface UsersDetailsResponse { rankHistory: RankHistory2 ranked_and_approved_beatmapset_count: number unranked_beatmapset_count: number + is_restricted?: boolean } export interface UserAuth extends UsersDetailsResponse { @@ -80,7 +83,7 @@ export interface Country { export interface Cover { custom_url: string url: string - id: any + id?: string } export interface Kudosu { @@ -108,6 +111,19 @@ export interface Group { playmodes: any } +export interface DailyChallengeUserStats { + daily_streak_best: number + daily_streak_current: number + last_update?: string + last_weekly_streak?: string + playcount: number + top_10p_placements: number + top_50p_placements: number + user_id: number + weekly_streak_best: number + weekly_streak_current: number +} + export interface MonthlyPlaycount { start_date: string count: number @@ -150,7 +166,7 @@ export interface Statistics { grade_counts: GradeCounts country_rank: number rank: Rank - variants: Variant[] + variants?: Variant[] } export interface Level { From c9e5f84ba6ea0ea816f9fc37c56317e791a25fc5 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Tue, 17 Sep 2024 09:56:10 +0300 Subject: [PATCH 212/259] fix inconsistancy --- utility/auth.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/utility/auth.ts b/utility/auth.ts index 9c45e221..2181f8bf 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -210,12 +210,12 @@ const lazer_login = async (login: string, password: string): Promise => { +const authorize_cli = async (client_id: number | string, client_secret: string, redirect_url: string, scopes: auth_scopes, state?: string): Promise => { const cl = readln.createInterface(process.stdin, process.stdout); const question = (q: string) => new Promise((res, rej) => cl.question(q + ': ', (answer: string) => res(answer))); - const url = build_url({ client_id, redirect_uri, scopes, state }); + const url = build_url({ client_id, redirect_url, scopes, state }); const start = (process.platform == 'darwin' ? 'open' : process.platform == 'win32' ? 'start' : 'xdg-open'); execSync(start + ' ' + url.replace(/&/g, '^&')); @@ -231,7 +231,7 @@ const authorize_cli = async (client_id: number | string, client_secret: string, grant_type: 'authorization_code', client_id: client_id, client_secret: client_secret, - redirect_uri: redirect_uri, + redirect_uri: redirect_url, code, }) }); @@ -244,16 +244,16 @@ const authorize_cli = async (client_id: number | string, client_secret: string, }; -export const build_url = ({ client_id, redirect_uri, scopes, state }: { +export const build_url = ({ client_id, redirect_url, scopes, state }: { client_id: number | string, - redirect_uri: string, + redirect_url: string, scopes: auth_scopes, state?: string }): string => { const url = new URL('https://osu.ppy.sh/oauth/authorize'); const params: any = { client_id: client_id, - redirect_uri: redirect_uri, + redirect_uri: redirect_url, response_type: 'code', scope: scopes.join(' '), }; From 6bd3d3506ed1b74fb716708e90ab5dfce6fe5410 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Sat, 3 Aug 2024 21:35:25 +0300 Subject: [PATCH 213/259] Add JSDoc to `v2.session` endpoints. --- routes/v2.ts | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/routes/v2.ts b/routes/v2.ts index d30be999..ca9ca511 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -1521,8 +1521,34 @@ export const chat = { import { session_actions } from "../api/v2/session_actions"; - +/** + * ##### Description + * Retrieve data from the session API. + */ export const session = { + /** + * ### `POST` [/v2/session/verify](https://osu.ppy.sh/docs/index.html#post-apiv2sessionverify) + * ### `POST` [/v2/session/verify/reissue](https://osu.ppy.sh/docs/index.html#post-apiv2sessionverifyreissue) + * ### `DELETE` [/v2/oauth/tokens/current](https://osu.ppy.sh/docs/index.html#revoke-current-token) + * `async` Perform session actions via endpoint. + * + *   + * + * ### Parameters + * - `params.type` - Type of the action to perform. + * - `addons` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#post-apiv2sessionverify) | [Check return types](../types/v2/session_actions.ts) + */ actions: session_actions, }; From 04628f5132603d9cd280a9655916be974d19745a Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Sat, 3 Aug 2024 21:35:46 +0300 Subject: [PATCH 214/259] Add JSDoc to `v2.session` endpoints. --- routes/v2.ts | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/routes/v2.ts b/routes/v2.ts index ca9ca511..dc14da6e 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -1559,8 +1559,37 @@ import { rooms_details } from "../api/v2/rooms_details"; import { rooms_leaderboard } from "../api/v2/rooms_leaderboard"; import { rooms_scores } from "../api/v2/rooms_scores"; - +/** + * ##### Description + * Retrieve data from the rooms API. + */ export const rooms = { + /** + * ### `GET` [/v2/rooms](https://osu.ppy.sh/docs/index.html#get-multiplayer-rooms) + * `async` Retrieve a list of multiplayer rooms. + * + *   + * + * ### Parameters + * - `params.type?` - Type of rooms to retrieve. + * - `params.status?` - Status of the rooms to retrieve. + * - `params.query?` - Query to search for. + * - `params.limit?` - Number of rooms to return. + * - `params.sort?` - Sort order of the rooms. + * - `params.cursor_string?` - [Cursor string for pagination.](https://osu.ppy.sh/docs/index.html#cursorstring) + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-multiplayer-rooms) | [Check return types](../types/v2/rooms_list.ts) + */ list: rooms_list, scores: rooms_scores, details: rooms_details, From fc2cb3365fe5b1c6f5f83507b7ead61778cbddcc Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Sat, 3 Aug 2024 21:37:35 +0300 Subject: [PATCH 215/259] Add JSDoc to `v2.rooms` endpoints. --- routes/v2.ts | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/routes/v2.ts b/routes/v2.ts index dc14da6e..f6f15cf4 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -1591,7 +1591,79 @@ export const rooms = { * [See documentation](https://osu.ppy.sh/docs/index.html#get-multiplayer-rooms) | [Check return types](../types/v2/rooms_list.ts) */ list: rooms_list, + /** + * ### `GET` [/v2/rooms/{room}/playlist/{playlist}/scores](https://osu.ppy.sh/docs/index.html#get-scores) + * ### `GET` [/v2/rooms/{room}/playlist/{playlist}/scores/{score}](https://osu.ppy.sh/docs/index.html#get-a-score) + * ### `GET` [/v2/rooms/{room}/playlist/{playlist}/scores/users/{user}](https://osu.ppy.sh/docs/index.html#get-user-high-score) + * `async` Retrieve a list of scores from playlists. + * + *   + * + * ### Global Parameters + * - `params.type` - Type of retrieval. + * - `params.id` - ID of the room. + * - `params.playlist_id` - ID of the playlist. + * + * ### Parameters for `params.type: 'all'` + * - `params.limit?` - Maximum number of scores to return. + * - `params.sort?` - Sort order of the scores. + * - `params.cursor_string?` - [Cursor string for pagination.](https://osu.ppy.sh/docs/index.html#cursorstring) + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-scores) | [Check return types](../types/v2/rooms_scores.ts) + */ scores: rooms_scores, + /** + * ### `GET` [/v2/rooms/{room}](https://osu.ppy.sh/docs/index.html#get-apiv2roomsroom) + * `async` Retrieve a room by given parameters. + * + *   + * + * ### Parameters + * - `params.id` - ID of the room to retrieve. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2roomsroom) | [Check return types](../types/v2/rooms_details.ts) + */ details: rooms_details, + /** + * ### `GET` [/v2/rooms/{room}/leaderboard](https://osu.ppy.sh/docs/index.html#get-apiv2roomsroomleaderboard) + * `async` Retrieve a leaderboard from a room. + * + *   + * + * ### Parameters + * - `params.id` - ID of the room. + * - `params.limit?` - Maximum number of scores to return. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * // TBA + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2roomsroomleaderboard) | [Check return types](../types/v2/rooms_leaderboard.ts) + */ leaderboard: rooms_leaderboard, }; \ No newline at end of file From 24a7558b21227162bb266777aa7e6d1a99bb69e7 Mon Sep 17 00:00:00 2001 From: GabuTheDev <107962621+GabuTheDev@users.noreply.github.com> Date: Sat, 3 Aug 2024 21:38:08 +0300 Subject: [PATCH 216/259] Rename `v2.rooms_list` param from `show` to `status` --- api/v2/rooms_list.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/v2/rooms_list.ts b/api/v2/rooms_list.ts index 0e3c9145..ccf29781 100644 --- a/api/v2/rooms_list.ts +++ b/api/v2/rooms_list.ts @@ -9,7 +9,7 @@ type Response = RoomsListResponse & IError; export const rooms_list = async (params: { type?: 'playlists' | 'realtime'; - show?: 'all' | 'active' | 'ended' | 'participated' | 'owned'; + status?: 'all' | 'active' | 'ended' | 'participated' | 'owned'; query?: string; @@ -26,7 +26,7 @@ export const rooms_list = async (params: { method: 'GET', params: { type_group: params.type, - mode: params.show, + mode: params.status, sort: params.sort, limit: params.limit, cursor_string: params.cursor_string, From fa6f115216f0cffad7436a6c8279600e5a3fa515 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 30 Sep 2024 15:57:31 +0300 Subject: [PATCH 217/259] use `type` instead of method in `auth.login` --- api/v2/me_details.ts | 2 +- api/v2/me_download_quota.ts | 2 +- api/v2/me_friends.ts | 2 +- types/index.ts | 8 ++++---- utility/auth.ts | 37 ++++++++++++++++++++++++------------- 5 files changed, 31 insertions(+), 20 deletions(-) diff --git a/api/v2/me_details.ts b/api/v2/me_details.ts index 0fa85e6a..db79dce7 100644 --- a/api/v2/me_details.ts +++ b/api/v2/me_details.ts @@ -9,7 +9,7 @@ type Response = MeDetailsResponse & IError; export const me_details = async (params: { mode: Modes_names }, addons?: IDefaultParams): Promise => { - if (credentials.method != 'lazer') { + if (credentials.type != 'lazer') { return handleErrors(`Login via lazer to use this endpoint`) as Response }; diff --git a/api/v2/me_download_quota.ts b/api/v2/me_download_quota.ts index 5cfa3226..80fc5e2e 100644 --- a/api/v2/me_download_quota.ts +++ b/api/v2/me_download_quota.ts @@ -9,7 +9,7 @@ type Response = MedownloadquotaResponse & IError; export const me_download_quota = async (addons?: IDefaultParams): Promise => { - if (credentials.method != 'lazer') { + if (credentials.type != 'lazer') { return handleErrors(`Login via lazer to use this endpoint`) as Response }; diff --git a/api/v2/me_friends.ts b/api/v2/me_friends.ts index 90849592..7101a99a 100644 --- a/api/v2/me_friends.ts +++ b/api/v2/me_friends.ts @@ -9,7 +9,7 @@ type Response = MeFriendsResponse[] & IError; export const me_friends = async (addons?: IDefaultParams): Promise => { - if (credentials.method != 'lazer') { + if (credentials.type != 'lazer') { return handleErrors(`Login via lazer to use this endpoint`) as Response }; diff --git a/types/index.ts b/types/index.ts index 04191f22..784112b5 100644 --- a/types/index.ts +++ b/types/index.ts @@ -45,7 +45,7 @@ export type auth_scopes = ( export type auth_params = ({ - method: 'v2'; + type: 'v2'; client_id: number | string; client_secret: string; @@ -55,14 +55,14 @@ export type auth_params = ({ scopes: auth_scopes; } | { - method: 'v1'; + type: 'v1'; api_key: string; timeout?: number; tokenPath?: string; } | { - method: 'lazer'; + type: 'lazer'; login: string; password: string; @@ -70,7 +70,7 @@ export type auth_params = ({ timeout?: number; tokenPath?: string; } | { - method: 'cli'; + type: 'cli'; client_id: number | string; client_secret: string; diff --git a/utility/auth.ts b/utility/auth.ts index 2181f8bf..f0d11548 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -5,7 +5,7 @@ import path from "path"; import fs from "fs"; -import { auth_params, auth_response, auth_scopes, lazer_auth_response, Modes_names } from '../types/index'; +import { auth_params, auth_response, auth_scopes, IError, lazer_auth_response, Modes_names } from '../types/index'; import { UserAuth } from '../types/v2/users_details'; import { handleErrors } from './handleErrors'; @@ -17,7 +17,7 @@ export const settings = { export const credentials: { - method: any; + type: any; api_key: string; @@ -34,7 +34,7 @@ export const credentials: { scopes: auth_scopes; } = { - method: '' as any, + type: '' as any, api_key: '', @@ -61,40 +61,51 @@ export const cache = { }; +type ResponseLogin = + T extends 'v2' + ? Promise + : T extends 'v1' + ? string + : T extends 'lazer' + ? Promise + : T extends 'cli' + ? Promise + : null; -export const login = (params: auth_params) => { - credentials.method = params.method; + +export const login = (params: auth_params): ResponseLogin => { + credentials.type = params.type; if (params.tokenPath) credentials.tokenPath = params.tokenPath; if (params.timeout) settings.timeout = params.timeout; - if (params.method == 'v1') { + if (params.type == 'v1') { credentials.api_key = params.api_key; cache.v1 = params.api_key; - return cache.v1; + return cache.v1 as ResponseLogin; }; - if (params.method == 'v2') { + if (params.type == 'v2') { credentials.client_id = params.client_id; credentials.client_secret = params.client_secret; if (params.scopes) credentials.scopes = params.scopes; - return client_login(params.client_id, params.client_secret, params.scopes || ['public']); + return client_login(params.client_id, params.client_secret, params.scopes || ['public']) as ResponseLogin; }; - if (params.method == 'lazer') { + if (params.type == 'lazer') { credentials.login = params.login; credentials.password = params.password; - return lazer_login(params.login, params.password); + return lazer_login(params.login, params.password) as ResponseLogin; }; - if (params.method == 'cli') { + if (params.type == 'cli') { credentials.client_id = params.client_id; credentials.client_secret = params.client_secret; if (params.scopes) credentials.scopes = params.scopes; @@ -102,7 +113,7 @@ export const login = (params: auth_params) => { credentials.redirect_url = params.redirect_url; credentials.state = params.state; - return authorize_cli(params.client_id, params.client_secret, params.redirect_url, params.scopes || ['public'], params.state); + return authorize_cli(params.client_id, params.client_secret, params.redirect_url, params.scopes || ['public'], params.state) as ResponseLogin; }; From 9dd10d24a6c77f63498b9feb839703af28349c95 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 30 Sep 2024 22:07:19 +0300 Subject: [PATCH 218/259] fix issues --- utility/handleErrors.ts | 7 ++++--- utility/request.ts | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/utility/handleErrors.ts b/utility/handleErrors.ts index e0b91981..009ee366 100644 --- a/utility/handleErrors.ts +++ b/utility/handleErrors.ts @@ -1,11 +1,12 @@ import { settings } from '../utility/auth'; -export const handleErrors = (message: string): any => { +export const handleErrors = (message: string | Error): any => { + const error = message instanceof Error ? message : new Error(message); if (settings.throwErrors) { - throw new Error(message); + throw error; }; - return { error: new Error(message) }; + return { error }; }; \ No newline at end of file diff --git a/utility/request.ts b/utility/request.ts index 79322fac..428f8f0f 100644 --- a/utility/request.ts +++ b/utility/request.ts @@ -133,7 +133,7 @@ export const request: RequestType = (url, { method, headers, data, params = {}, }; - if ('error' in parse) { + if ('error' in parse && Object.keys(parse).length == 1) { if (parse.error === null) { return resolve({ error: `osu returned empty error, double check your parameters (request)` }); }; From 9aee7e2cf3fc7d74f68a56517b43dab2c578ee78 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 30 Sep 2024 22:28:32 +0300 Subject: [PATCH 219/259] add examples to `v2` routes --- api/v2/assets_backgrounds.ts | 6 +- api/v2/beatmaps_discussions_posts.ts | 4 +- api/v2/beatmaps_discussions_votes.ts | 2 +- api/v2/changelogs_details.ts | 6 +- api/v2/changelogs_list.ts | 24 +- api/v2/chat_actions.ts | 16 +- api/v2/chat_channels_actions.ts | 14 +- api/v2/chat_channels_list.ts | 1 + api/v2/chat_details.ts | 2 +- api/v2/chat_list.ts | 2 +- api/v2/chat_messages.ts | 6 +- api/v2/chat_updates.ts | 6 +- api/v2/forums_topics_actions.ts | 56 +- api/v2/forums_topics_details.ts | 2 +- api/v2/matches_details.ts | 2 +- api/v2/matches_list.ts | 6 +- api/v2/news_list.ts | 6 +- api/v2/notification_actions.ts | 6 +- api/v2/notifications_list.ts | 4 +- api/v2/ranking_list.ts | 28 +- api/v2/rooms_details.ts | 6 +- api/v2/rooms_leaderboard.ts | 4 +- api/v2/rooms_list.ts | 19 +- api/v2/rooms_scores.ts | 12 +- api/v2/scores_details.ts | 2 +- api/v2/scores_download.ts | 2 +- api/v2/scores_list.ts | 38 +- api/v2/search.ts | 32 +- api/v2/session_actions.ts | 27 +- api/v2/users_activity.ts | 4 +- api/v2/users_beatmaps.ts | 4 +- api/v2/users_details.ts | 2 +- api/v2/users_kudosu.ts | 2 +- api/v2/users_list.ts | 2 +- api/v2/wiki_details.ts | 4 +- routes/v2.ts | 1302 ++++++++++++++++++++++++-- utility/auth.ts | 4 + 37 files changed, 1440 insertions(+), 225 deletions(-) diff --git a/api/v2/assets_backgrounds.ts b/api/v2/assets_backgrounds.ts index 4d8a6f57..197c8796 100644 --- a/api/v2/assets_backgrounds.ts +++ b/api/v2/assets_backgrounds.ts @@ -20,7 +20,7 @@ type Response = export const assets_backgrounds = (params: T, addons?: IDefaultParams): Response => { - if (params.type == 'seasonal') { + if (params?.type == 'seasonal') { return request(`https://osu.ppy.sh/api/v2/seasonal-backgrounds`, { method: 'GET', addons, @@ -28,7 +28,7 @@ export const assets_backgrounds = (params: T, addons?: IDefaul }; - if (params.type == 'beatmapset') { + if (params?.type == 'beatmapset') { if (params.set_id == null) { return handleErrors('Specify beatmapset id') as Response; }; @@ -49,5 +49,5 @@ export const assets_backgrounds = (params: T, addons?: IDefaul }; - return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; + return handleErrors(`Unsupported type: ${(params as any)?.type}`) as Response; }; \ No newline at end of file diff --git a/api/v2/beatmaps_discussions_posts.ts b/api/v2/beatmaps_discussions_posts.ts index 3f90def9..fe4e9dfd 100644 --- a/api/v2/beatmaps_discussions_posts.ts +++ b/api/v2/beatmaps_discussions_posts.ts @@ -14,13 +14,13 @@ export const beatmaps_discussions_posts = async (params: { limit?: number; cursor_string?: string; }, addons?: IDefaultParams): Promise => { - if (params.discussion_id) { + if (params?.discussion_id) { // @ts-ignore params.beatmapset_discussion_id = params.discussion_id; delete params.discussion_id; }; - if (Array.isArray(params.types)) { + if (Array.isArray(params?.types)) { // @ts-ignore params['types[]'] = params.types; delete params.types; diff --git a/api/v2/beatmaps_discussions_votes.ts b/api/v2/beatmaps_discussions_votes.ts index 465da32a..04c308ad 100644 --- a/api/v2/beatmaps_discussions_votes.ts +++ b/api/v2/beatmaps_discussions_votes.ts @@ -16,7 +16,7 @@ export const beatmaps_discussions_votes = async (params: { limit?: number; cursor_string?: string; }, addons?: IDefaultParams): Promise => { - if (params.discussion_id) { + if (params?.discussion_id) { // @ts-ignore params.beatmapset_discussion_id = params.discussion_id; delete params.discussion_id; diff --git a/api/v2/changelogs_details.ts b/api/v2/changelogs_details.ts index 5242540b..2730cd5a 100644 --- a/api/v2/changelogs_details.ts +++ b/api/v2/changelogs_details.ts @@ -8,14 +8,14 @@ type Response = changelogsDetailsResponse[] & IError; export const changelogs_details = async (params: { - stream_name: string; + stream_name: 'stable40' | 'beta40' | 'cuttingedge' | 'lazer' | 'web'; build_version: string; }, addons?: IDefaultParams): Promise => { - if (params.stream_name == null) { + if (params?.stream_name == null) { return handleErrors(`Specify stream name`) as Response; }; - if (params.build_version == null) { + if (params?.build_version == null) { return handleErrors(`Specify build version`) as Response; }; diff --git a/api/v2/changelogs_list.ts b/api/v2/changelogs_list.ts index fe6e2a8b..99f47a1e 100644 --- a/api/v2/changelogs_list.ts +++ b/api/v2/changelogs_list.ts @@ -10,7 +10,7 @@ type params = ({ from_build?: string; to_build?: string; - stream_name?: string; + stream_name?: 'stable40' | 'beta40' | 'cuttingedge' | 'lazer' | 'web'; max_id?: string; message_formats?: ('html' | 'markdown')[]; @@ -18,7 +18,7 @@ type params = ({ type: 'lookup'; message_formats: ('html' | 'markdown')[]; - changelog: string; + changelog: 'stable40' | 'beta40' | 'cuttingedge' | 'lazer' | 'web'; key: string; }); @@ -37,32 +37,32 @@ export const changelogs_list = async (params: T, addons?: IDef let method = 'GET'; - switch (params.type) { + switch (params?.type) { case 'all': url += '/changelog'; - object.from = params.from_build; - object.to = params.to_build; + if (params?.from_build != null) object.from = params.from_build; + if (params?.to_build != null) object.to = params.to_build; - object.stream = params.stream_name; - object.max_id = params.max_id; - object['message_formats[]'] = params.message_formats; + if (params?.stream_name != null) object.stream = params.stream_name; + if (params?.max_id != null) object.max_id = params.max_id; + if (params?.message_formats != null) object['message_formats[]'] = params.message_formats; break; case 'lookup': url += `/changelog/${params.changelog}`; - if (params.changelog == null) { + if (params?.changelog != null == null) { return handleErrors(`Specify changelog stream`) as Response; }; - object['message_formats[]'] = params.message_formats; - object['key'] = params.key; + if (params?.message_formats != null) object['message_formats[]'] = params.message_formats; + if (params?.key != null) object['key'] = params.key; break; default: - return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; + return handleErrors(`Unsupported type: ${(params as any)?.type}`) as Response; }; diff --git a/api/v2/chat_actions.ts b/api/v2/chat_actions.ts index 867daaa2..f2f47abc 100644 --- a/api/v2/chat_actions.ts +++ b/api/v2/chat_actions.ts @@ -36,7 +36,7 @@ export const chat_actions = async (params: T, addons?: IDefaul let method = 'POST'; - switch (params.type) { + switch (params?.type) { case 'new': url += `/chat/new`; method = 'POST'; @@ -46,18 +46,18 @@ export const chat_actions = async (params: T, addons?: IDefaul }; - object['is_action'] = params.is_action; - object['target_id'] = params.user_id; - object['message'] = params.message; - if (params.uuid) object['uuid'] = params.uuid; + if (params?.is_action != null) object['is_action'] = params.is_action; + if (params?.user_id != null) object['target_id'] = params.user_id; + if (params?.message != null) object['message'] = params.message; + if (params?.uuid) object['uuid'] = params.uuid; break; case 'keepalive': url += `/chat/ack`; method = 'POST'; - object['history_since'] = params.history_since; - object['since'] = params.since; + if (params?.history_since != null) object['history_since'] = params.history_since; + if (params?.since != null) object['since'] = params.since; break; default: @@ -74,6 +74,6 @@ export const chat_actions = async (params: T, addons?: IDefaul if (data.error) return handleErrors(data.error) as Response; - if (params.type == 'keepalive') return data.silences as Response; + if (params?.type == 'keepalive') return data.silences as Response; return data as Response; }; \ No newline at end of file diff --git a/api/v2/chat_channels_actions.ts b/api/v2/chat_channels_actions.ts index 94185f52..66b7a88e 100644 --- a/api/v2/chat_channels_actions.ts +++ b/api/v2/chat_channels_actions.ts @@ -43,21 +43,21 @@ export const chat_channels_actions = async (params: T, addons? let method = 'POST'; - switch (params.type) { + switch (params?.type) { case 'send': - if (params.channel_id == null || params.message == null || params.is_action == null) { + if (params?.channel_id == null || params?.message == null || params?.is_action == null) { return handleErrors(`Missing required parameters`) as Response; }; url += `/chat/channels/${params.channel_id}/messages`; - object['message'] = params.message; - object['is_action'] = params.is_action; + if (params?.message != null) object['message'] = params.message; + if (params?.is_action != null) object['is_action'] = params.is_action; break; case 'join': - if (params.channel_id == null || params.user_id == null) { + if (params?.channel_id == null || params?.user_id == null) { return handleErrors(`Missing required parameters`) as Response; }; @@ -67,7 +67,7 @@ export const chat_channels_actions = async (params: T, addons? break; case 'leave': - if (params.channel_id == null || params.user_id == null) { + if (params?.channel_id == null || params?.user_id == null) { return handleErrors(`Missing required parameters`) as Response; }; @@ -77,7 +77,7 @@ export const chat_channels_actions = async (params: T, addons? break; case 'read': - if (params.channel_id == null || params.message_id == null) { + if (params?.channel_id == null || params?.message_id == null) { return handleErrors(`Missing required parameters`) as Response; }; diff --git a/api/v2/chat_channels_list.ts b/api/v2/chat_channels_list.ts index 13089bd4..98cce435 100644 --- a/api/v2/chat_channels_list.ts +++ b/api/v2/chat_channels_list.ts @@ -8,6 +8,7 @@ import { request } from "../../utility/request"; export const chat_channels_list = async (addons?: IDefaultParams): Promise => { const data = await request(`https://osu.ppy.sh/api/v2/chat/channels`, { method: 'GET', + addons, }); if (data.error) return handleErrors(data.error); diff --git a/api/v2/chat_details.ts b/api/v2/chat_details.ts index 1e9ac078..dcc715df 100644 --- a/api/v2/chat_details.ts +++ b/api/v2/chat_details.ts @@ -8,7 +8,7 @@ type Response = ChatDetailsResponse & IError; export const chat_details = async (params: { channel_id: number }, addons?: IDefaultParams): Promise => { - if (params.channel_id == null) { + if (params?.channel_id == null) { return handleErrors(`Specify channel id`) as Response; }; diff --git a/api/v2/chat_list.ts b/api/v2/chat_list.ts index 7bf16157..0a0b54c1 100644 --- a/api/v2/chat_list.ts +++ b/api/v2/chat_list.ts @@ -25,7 +25,7 @@ export const chat_list = async (params: { data.sort((a: any, b: any) => b.last_message_id - a.last_message_id); - if (params.unread == true) + if (params?.unread == true) data = data.filter((r: any) => r.last_read_id != r.last_message_id); diff --git a/api/v2/chat_messages.ts b/api/v2/chat_messages.ts index adfd15e9..dc4d5269 100644 --- a/api/v2/chat_messages.ts +++ b/api/v2/chat_messages.ts @@ -8,18 +8,18 @@ type Response = ChatMessagesResponse[] & IError; export const chat_messages = async (params: { - id: number; + channel_id: number; limit?: number; since?: number; until?: number; return_object?: boolean; }, addons?: IDefaultParams): Promise => { - if (params.id == null) { + if (params?.channel_id == null) { return handleErrors(`Specify channel id`) as Response; }; - const data = await request(`https://osu.ppy.sh/api/v2/chat/channels/${params.id}/messages`, { + const data = await request(`https://osu.ppy.sh/api/v2/chat/channels/${params.channel_id}/messages`, { method: 'GET', params, addons, diff --git a/api/v2/chat_updates.ts b/api/v2/chat_updates.ts index 7563752e..f87fc4c4 100644 --- a/api/v2/chat_updates.ts +++ b/api/v2/chat_updates.ts @@ -15,9 +15,9 @@ export const chat_updates = async (params: { const data = await request(`https://osu.ppy.sh/api/v2/chat/updates`, { method: 'GET', params: { - 'history_since': params.history_since, - 'includes[]': params.includes, - 'since': params.after_id, + 'history_since': params?.history_since, + 'includes[]': params?.includes, + 'since': params?.after_id, }, addons, }); diff --git a/api/v2/forums_topics_actions.ts b/api/v2/forums_topics_actions.ts index 89c3b11a..7940d088 100644 --- a/api/v2/forums_topics_actions.ts +++ b/api/v2/forums_topics_actions.ts @@ -69,15 +69,15 @@ export const forums_topics_actions = async (params: T, addons? switch (params.type) { case 'create': - if (params.forum_id == null) { + if (params?.forum_id == null) { return handleErrors(`Specify forum id`) as Response; }; - if (params.title == null) { + if (params?.title == null) { return handleErrors(`Specify title`) as Response; }; - if (params.message == null) { + if (params?.message == null) { return handleErrors(`Specify message`) as Response; }; @@ -85,37 +85,37 @@ export const forums_topics_actions = async (params: T, addons? urls.push(`https://osu.ppy.sh/api/v2/forums/topics`); methods.push('POST'); - object['forum_id'] = params.forum_id; + if (params?.forum_id != null) object['forum_id'] = params.forum_id; - object['title'] = params.title; - object['body'] = params.message; + if (params?.title != null) object['title'] = params.title; + if (params?.message != null) object['body'] = params.message; - if (params.enable_poll != null) object['with_poll'] = params.enable_poll; - if (params.enable_poll != true) { + if (params?.enable_poll != null) object['with_poll'] = params.enable_poll; + if (params?.enable_poll != true) { body.push(object); break; }; - object['forum_topic_poll[vote_change]'] = params.poll.allow_vote_change; - object['forum_topic_poll[hide_results]'] = params.poll.hide_results; + if (params?.poll?.allow_vote_change != null) object['forum_topic_poll[vote_change]'] = params.poll.allow_vote_change; + if (params?.poll?.hide_results != null) object['forum_topic_poll[hide_results]'] = params.poll.hide_results; - object['forum_topic_poll[title]'] = params.poll.title; - object['forum_topic_poll[options]'] = params.poll.options; + if (params?.poll?.title != null) object['forum_topic_poll[title]'] = params.poll.title; + if (params?.poll?.options != null) object['forum_topic_poll[options]'] = params.poll.options; - object['forum_topic_poll[max_options]'] = params.poll.max_votes_per_user; - object['forum_topic_poll[length_days]'] = params.poll.duration_days; + if (params?.poll?.max_votes_per_user != null) object['forum_topic_poll[max_options]'] = params.poll.max_votes_per_user; + if (params?.poll?.duration_days != null) object['forum_topic_poll[length_days]'] = params.poll.duration_days; body.push(object); break; case 'reply': - if (params.post_id == null) { + if (params?.post_id == null) { return handleErrors(`Specify post id`) as Response; }; - if (params.message == null) { + if (params?.message == null || params?.message?.trim() == '') { return handleErrors(`Specify message`) as Response; }; @@ -123,17 +123,17 @@ export const forums_topics_actions = async (params: T, addons? urls.push(`https://osu.ppy.sh/api/v2/forums/topics/${params.post_id}/reply`); methods.push('POST'); - object['body'] = params.message; + if (params?.message) object['body'] = params.message; body.push(object); break; case 'edit_post': - if (params.post_id == null) { + if (params?.post_id == null) { return handleErrors(`Specify post id`) as Response; }; - if (params.message == null) { + if (params?.message == null) { return handleErrors(`Specify message`) as Response; }; @@ -141,18 +141,18 @@ export const forums_topics_actions = async (params: T, addons? urls.push(`https://osu.ppy.sh/api/v2/forums/posts/${params.post_id}`); methods.push('PATCH'); - object['body'] = params.message; + if (params?.message) object['body'] = params.message; body.push(object); break; case 'edit_topic': - if (params.topic_id && (params.title != null && params.title != '')) { - if (params.topic_id == null) { + if (params?.topic_id && (params?.title != null && params?.title != '')) { + if (params?.topic_id == null) { return handleErrors(`Specify topic id`) as Response; }; - if (params.title == null) { + if (params?.title == null || params?.title?.trim() == '') { return handleErrors(`Specify title`) as Response; }; @@ -160,7 +160,7 @@ export const forums_topics_actions = async (params: T, addons? urls.push(`https://osu.ppy.sh/api/v2/forums/topics/${params.topic_id}`); methods.push('PUT'); - object = { + if (params?.title) object = { forum_topic: { 'topic_title': params.title, }, @@ -173,12 +173,12 @@ export const forums_topics_actions = async (params: T, addons? }; - if (params.post_id && (params.message != null && params.message != '')) { - if (params.post_id == null) { + if (params?.post_id && (params?.message != null && params?.message != '')) { + if (params?.post_id == null) { return handleErrors(`Specify post id`) as Response; }; - if (params.message == null) { + if (params?.message == null) { return handleErrors(`Specify message`) as Response; }; @@ -186,7 +186,7 @@ export const forums_topics_actions = async (params: T, addons? urls.push(`https://osu.ppy.sh/api/v2/forums/posts/${params.post_id}`); methods.push('PUT'); - object['body'] = params.message; + if (params?.message) object['body'] = params.message; body.push(object); fields.push('post'); diff --git a/api/v2/forums_topics_details.ts b/api/v2/forums_topics_details.ts index 2ae8a0e5..21dba364 100644 --- a/api/v2/forums_topics_details.ts +++ b/api/v2/forums_topics_details.ts @@ -18,7 +18,7 @@ export const forums_topics_details = async (params: { cursor_string?: string, }, addons?: IDefaultParams): Promise => { - if (params.id == null) { + if (params?.id == null) { return handleErrors(`Specify topic id`) as Response }; diff --git a/api/v2/matches_details.ts b/api/v2/matches_details.ts index 3b6af321..3ac94ef7 100644 --- a/api/v2/matches_details.ts +++ b/api/v2/matches_details.ts @@ -8,7 +8,7 @@ type Response = MatchesDetailsResponse & IError; export const matches_details = async (params: { match_id: number }, addons?: IDefaultParams): Promise => { - if (params.match_id == null) { + if (params?.match_id == null) { return handleErrors(`Specify match id`) as Response; }; diff --git a/api/v2/matches_list.ts b/api/v2/matches_list.ts index cb12c3d6..37b151cc 100644 --- a/api/v2/matches_list.ts +++ b/api/v2/matches_list.ts @@ -18,9 +18,9 @@ export const matches_list = async (params: { const data = await request(`https://osu.ppy.sh/api/v2/matches`, { method: 'GET', params: { - limit: params.limit, - sort: params.sort, - 'cursor[match_id]': params.after_id, + limit: params?.limit, + sort: params?.sort, + 'cursor[match_id]': params?.after_id, }, addons, }); diff --git a/api/v2/news_list.ts b/api/v2/news_list.ts index 7e83dec9..e4449604 100644 --- a/api/v2/news_list.ts +++ b/api/v2/news_list.ts @@ -13,9 +13,9 @@ export const news_list = async (params: { cursor_string?: string; } = {}, addons?: IDefaultParams): Promise => { const object: any = { - year: params.from_year, - limit: params.limit, - cursor_string: params.cursor_string, + year: params?.from_year, + limit: params?.limit, + cursor_string: params?.cursor_string, }; diff --git a/api/v2/notification_actions.ts b/api/v2/notification_actions.ts index 30f5919d..4870b1cd 100644 --- a/api/v2/notification_actions.ts +++ b/api/v2/notification_actions.ts @@ -35,7 +35,7 @@ export const notification_actions = async (params: T, addons?: let method = 'GET'; - switch (params.type) { + switch (params?.type) { case 'mark_as_read': url += '/notifications/mark-read'; method = 'POST'; @@ -46,11 +46,11 @@ export const notification_actions = async (params: T, addons?: // params.ids.forEach((r, index) => object[`identities[${index}][id]`] = r); - if (Array.isArray(params.notifications)) { + if (Array.isArray(params?.notifications)) { object['notifications'] = params.notifications; }; - if (Array.isArray(params.identities)) { + if (Array.isArray(params?.identities)) { object['identities'] = params.identities; }; break; diff --git a/api/v2/notifications_list.ts b/api/v2/notifications_list.ts index 45fb4123..d616ba41 100644 --- a/api/v2/notifications_list.ts +++ b/api/v2/notifications_list.ts @@ -14,14 +14,14 @@ export const notifications_list = async (params: { const data = await request(`https://osu.ppy.sh/api/v2/notifications`, { method: 'GET', params: { - max_id: params.max_id + max_id: params?.max_id }, addons, }); if (data.error) return handleErrors(data.error); - if (params.unread_only == true && !('error' in data)) + if (params?.unread_only == true && !('error' in data)) data.notifications = data.notifications.filter((r: any) => r.is_read == false); return data; diff --git a/api/v2/ranking_list.ts b/api/v2/ranking_list.ts index 9ad3e2a6..e1596aff 100644 --- a/api/v2/ranking_list.ts +++ b/api/v2/ranking_list.ts @@ -55,7 +55,7 @@ type Response = export const ranking_list = async (params: T, addons?: IDefaultParams): Promise> => { - if (params.type != 'kudosu' && params.mode == null) { + if (params?.type != 'kudosu' && params?.mode == null) { return handleErrors('Gamemode not specified') as Response; }; @@ -64,44 +64,44 @@ export const ranking_list = async (params: T, addons?: IDefaul let url = 'https://osu.ppy.sh/api/v2'; let method = 'GET'; - switch (params.type) { + switch (params?.type) { case 'charts': url += `/rankings/${params.mode}/${params.type}`; - object['cursor[page]'] = params.page; - object.filter = params.filter; - object.spotlight = params.spotlight_id; + if (params?.page != null) object['cursor[page]'] = params.page; + if (params?.filter != null) object.filter = params.filter; + if (params?.spotlight_id != null) object.spotlight = params.spotlight_id; break; case 'country': url += `/rankings/${params.mode}/${params.type}`; - object['cursor[page]'] = params.page; - object.filter = params.filter; + if (params?.page != null) object['cursor[page]'] = params.page; + if (params?.filter != null) object.filter = params.filter; break; case 'performance': url += `/rankings/${params.mode}/${params.type}`; - object['cursor[page]'] = params.page; - object.filter = params.filter; - object.country = params.country_code; - object.variant = params.variant; + if (params?.page != null) object['cursor[page]'] = params.page; + if (params?.filter != null) object.filter = params.filter; + if (params?.country_code != null) object.country = params.country_code; + if (params?.variant != null) object.variant = params.variant; break; case 'score': url += `/rankings/${params.mode}/${params.type}`; - object['cursor[page]'] = params.page; - object.filter = params.filter; + if (params?.page != null) object['cursor[page]'] = params.page; + if (params?.filter != null) object.filter = params.filter; break; case 'kudosu': url += `/rankings/kudosu`; - object.page = params.page; + if (params?.page != null) object.page = params.page; break; default: diff --git a/api/v2/rooms_details.ts b/api/v2/rooms_details.ts index f35547ce..a0797a52 100644 --- a/api/v2/rooms_details.ts +++ b/api/v2/rooms_details.ts @@ -7,13 +7,13 @@ import { request } from "../../utility/request"; type Response = RoomsDetailsResponse & IError; -export const rooms_details = async (id: number | 'latest', addons?: IDefaultParams): Promise => { - if (id == null) { +export const rooms_details = async (params: { id: number | 'latest' }, addons?: IDefaultParams): Promise => { + if (params.id == null) { return handleErrors(`Specify room id`) as Response; }; - const data = await request(`https://osu.ppy.sh/api/v2/rooms/${id}`, { + const data = await request(`https://osu.ppy.sh/api/v2/rooms/${params.id}`, { method: 'GET', addons, }); diff --git a/api/v2/rooms_leaderboard.ts b/api/v2/rooms_leaderboard.ts index 3d55da6d..0653c43a 100644 --- a/api/v2/rooms_leaderboard.ts +++ b/api/v2/rooms_leaderboard.ts @@ -11,14 +11,14 @@ export const rooms_leaderboard = async (params: { id: number; limit?: number; }, addons?: IDefaultParams): Promise => { - if (params.id == null) { + if (params?.id == null) { return handleErrors(`Specify room id`) as Response; }; const data = await request(`https://osu.ppy.sh/api/v2/rooms/${params.id}/leaderboard`, { method: 'GET', - params: { limit: params.limit }, + params: { limit: params?.limit }, addons, }); diff --git a/api/v2/rooms_list.ts b/api/v2/rooms_list.ts index ccf29781..567617ef 100644 --- a/api/v2/rooms_list.ts +++ b/api/v2/rooms_list.ts @@ -22,23 +22,24 @@ export const rooms_list = async (params: { addons = { apiVersion: '99999999' } - const data = await request(`https://osu.ppy.sh/api/v2/rooms`, { + let data = await request(`https://osu.ppy.sh/api/v2/rooms`, { method: 'GET', params: { - type_group: params.type, - mode: params.status, - sort: params.sort, - limit: params.limit, - cursor_string: params.cursor_string, + type_group: params?.type, + mode: params?.status, + sort: params?.sort, + limit: params?.limit, + cursor_string: params?.cursor_string, }, addons, }); if (data.error) return handleErrors(data.error); - - if (params?.query && !('error' in data)) - data.rooms = data.rooms.filter((r: any) => r.name.toLowerCase().includes(params.query.trim().toLowerCase())) + if (params?.query && !('error' in data)) { + if (data.rooms) data.rooms = data.rooms.filter((r: any) => r.name.toLowerCase().includes(params?.query.trim().toLowerCase())) + else data = data.filter((r: any) => r.name.toLowerCase().includes(params?.query.trim().toLowerCase())) + }; return data; diff --git a/api/v2/rooms_scores.ts b/api/v2/rooms_scores.ts index 503a1f8c..ad35c473 100644 --- a/api/v2/rooms_scores.ts +++ b/api/v2/rooms_scores.ts @@ -47,22 +47,22 @@ export const rooms_scores = async (params: T, addons?: IDefaul let method = 'GET'; - if (params.id == null) { + if (params?.id == null) { return handleErrors(`Specify room id`) as Response; }; - if (params.playlist_id == null) { + if (params?.playlist_id == null) { return handleErrors(`Specify playlist id`) as Response; }; - switch (params.type) { + switch (params?.type) { case 'all': url += `/rooms/${params.id}/playlist/${params.playlist_id}/scores`; - object.limit = params.limit; - object.sort = params.sort; - object.cursor_string = params.cursor_string; + if (params?.limit != null) object.limit = params.limit; + if (params?.sort != null) object.sort = params.sort; + if (params?.cursor_string != null) object.cursor_string = params.cursor_string; break; case 'single': diff --git a/api/v2/scores_details.ts b/api/v2/scores_details.ts index 5a5af16c..94c93494 100644 --- a/api/v2/scores_details.ts +++ b/api/v2/scores_details.ts @@ -11,7 +11,7 @@ export const scores_details = async (params: { id: number; mode?: Modes_names; }, addons?: IDefaultParams): Promise => { - if (params.id == null) { + if (params?.id == null) { return handleErrors(`Specify score id`) as Response; }; diff --git a/api/v2/scores_download.ts b/api/v2/scores_download.ts index bcc065dc..df5ae470 100644 --- a/api/v2/scores_download.ts +++ b/api/v2/scores_download.ts @@ -12,7 +12,7 @@ export const scores_download = async (params: { mode?: Modes_names; file_path?: string; }): Promise => { - if (params.id == null) { + if (params?.id == null) { return handleErrors(`Specify score id`) as Response; }; diff --git a/api/v2/scores_list.ts b/api/v2/scores_list.ts index fefd8618..fb8258b2 100644 --- a/api/v2/scores_list.ts +++ b/api/v2/scores_list.ts @@ -20,13 +20,13 @@ type params = { beatmap_id: number; mods?: string[]; } | { - type: 'beatmap_best'; + type: 'user_beatmap_best'; beatmap_id: number; user_id: number; mods?: string[]; } | { - type: 'beatmap_all'; + type: 'user_beatmap_all'; beatmap_id: number; user_id: number; @@ -68,7 +68,7 @@ export const scores_list = async (params: T, addons?: IDefault let method = 'GET'; - switch (params.type) { + switch (params?.type) { case 'leaderboard': if (params.beatmap_id == null) { return handleErrors(`Specify beatmap id`) as Response; @@ -79,11 +79,11 @@ export const scores_list = async (params: T, addons?: IDefault object['type'] = params.leaderboard_type; - object['mode'] = params.mode; - object['mods[]'] = params.mods; + if (params?.mode != null) object['mode'] = params.mode; + if (Array.isArray(params?.mods)) object['mods[]'] = params.mods; break; - case 'beatmap_best': + case 'user_beatmap_best': if (params.beatmap_id == null) { return handleErrors(`Specify beatmap id`) as Response; }; @@ -96,11 +96,11 @@ export const scores_list = async (params: T, addons?: IDefault url += `/beatmaps/${params.beatmap_id}/scores/users/${params.user_id}`; - object['mode'] = params.mode; - object['mods[]'] = params.mods; + if (params?.mode != null) object['mode'] = params.mode; + if (Array.isArray(params?.mods)) object['mods[]'] = params.mods; break; - case 'beatmap_all': + case 'user_beatmap_all': if (params.beatmap_id == null) { return handleErrors(`Specify beatmap id`) as Response; }; @@ -113,7 +113,7 @@ export const scores_list = async (params: T, addons?: IDefault url += `/beatmaps/${params.beatmap_id}/scores/users/${params.user_id}/all`; - object['mode'] = params.mode; + if (params?.mode != null) object['mode'] = params.mode; break; case 'user_best': @@ -128,10 +128,10 @@ export const scores_list = async (params: T, addons?: IDefault url += `/users/${params.user_id}/scores/${params.type.replace('user_', '')}`; - object['mode'] = params.mode; - object['limit'] = params.limit; - object['offset'] = params.offset; - object['include_fails'] = params.include_fails == true ? 1 : params.include_fails == false ? 0 : undefined; + if (params?.mode != null) object['mode'] = params.mode; + if (params?.limit != null) object['limit'] = params.limit; + if (params?.offset != null) object['offset'] = params.offset; + if (params?.include_fails != null) object['include_fails'] = params.include_fails == true ? 1 : params.include_fails == false ? 0 : undefined; break; case 'solo_scores': @@ -143,9 +143,9 @@ export const scores_list = async (params: T, addons?: IDefault url += `/beatmaps/${params.beatmap_id}/solo-scores`; - object['type'] = params.leaderboard_type; - object['mode'] = params.mode; - object['mods[]'] = params.mods; + if (params?.leaderboard_type) object['type'] = params.leaderboard_type; + if (params?.mode) object['mode'] = params.mode; + if (Array.isArray(params?.mods)) object['mods[]'] = params.mods; break; default: @@ -162,11 +162,11 @@ export const scores_list = async (params: T, addons?: IDefault if (data.error) return handleErrors(data.error) as Response; - if (['leaderboard', 'beatmap_all'].includes(params.type)) { + if (['leaderboard', 'user_beatmap_all'].includes(params.type)) { data.scores.forEach((r: any, index: number) => r.index = index); return data.scores as Response; }; - if (params.type != 'beatmap_best') data.forEach((r: any, index: number) => r.index = index); + if (params.type != 'user_beatmap_best') data.forEach((r: any, index: number) => r.index = index); return data as Response; }; \ No newline at end of file diff --git a/api/v2/search.ts b/api/v2/search.ts index 4d97d901..d605d5a5 100644 --- a/api/v2/search.ts +++ b/api/v2/search.ts @@ -44,36 +44,36 @@ export const search_all = async (params: T, addons?: IDefaultP let url = 'https://osu.ppy.sh/api/v2'; - switch (params.type) { + switch (params?.type) { case 'site': url += '/search'; - object.mode = params.location; - object.query = params.query; - object.page = params.page; + if (params?.location != null) object.mode = params.location; + if (params?.query != null) object.query = params.query; + if (params?.page != null) object.page = params.page; break; case 'beatmaps': url += '/beatmapsets/search'; - if (params._played != null) object.played = params._played ? 'played' : 'unplayed'; - if (params._nsfw != null) object.nsfw = params._nsfw; + if (params?._played != null) object.played = params._played ? 'played' : 'unplayed'; + if (params?._nsfw != null) object.nsfw = params._nsfw; - if (params.query != null) object.q = params.query; - if (params.mode != null) object.m = typeof params.mode == 'number' ? params.mode : GamemodeEnum[params.mode]; - if (params.status != null) object.s = params.status; - if (params.category != null) object.c = params.category.join('.'); + if (params?.query != null) object.q = params.query; + if (params?.mode != null) object.m = typeof params.mode == 'number' ? params.mode : GamemodeEnum[params.mode]; + if (params?.status != null) object.s = params.status; + if (params?.category != null) object.c = params.category.join('.'); - if (params.genre != null) object.g = typeof params.genre == 'number' ? params.genre : Genres_enum[params.genre]; - if (params.language != null) object.l = typeof params.language == 'number' ? params.language : Languages_enum[params.language]; + if (params?.genre != null) object.g = typeof params.genre == 'number' ? params.genre : Genres_enum[params.genre]; + if (params?.language != null) object.l = typeof params.language == 'number' ? params.language : Languages_enum[params.language]; - if (params.achieved_rank != null) object.r = params.achieved_rank.join('.'); + if (params?.achieved_rank != null) object.r = params.achieved_rank.join('.'); - if (params.extra != null) object.e = params.extra.join('.'); + if (params?.extra != null) object.e = params.extra.join('.'); - if (params.sort != null) object.sort = params.sort; - if (params.cursor_string != null) object.cursor_string = params.cursor_string; + if (params?.sort != null) object.sort = params.sort; + if (params?.cursor_string != null) object.cursor_string = params.cursor_string; break; }; diff --git a/api/v2/session_actions.ts b/api/v2/session_actions.ts index db3cd92e..1eff4af6 100644 --- a/api/v2/session_actions.ts +++ b/api/v2/session_actions.ts @@ -5,6 +5,7 @@ import { handleErrors } from "../../utility/handleErrors"; type params = ({ type: 'verify'; + code: string, } | { type: 'reissue'; } | { @@ -14,11 +15,11 @@ type params = ({ type Response = T extends 'verify' - ? any & IError + ? "" & IError : T extends 'reissue' - ? any & IError + ? { message: string } & IError : T extends 'delete' - ? any & IError + ? '' & IError : IError; @@ -27,11 +28,27 @@ export const session_actions = async (params: T, addons?: IDef let url = 'https://osu.ppy.sh/api/v2'; let method = 'POST'; + const headers: any = {}; + let body: any = ''; - switch (params.type) { + + switch (params?.type) { case 'verify': + if (params?.code == null) { + return handleErrors(`Specify verification code`) as Response; + }; + url += `/session/verify`; + + const boundary = `----WebKitFormBoundary${Math.random().toString(16).substring(2)}`; + body += `--${boundary}\r\n`; + body += 'Content-Disposition: form-data; name="verification_key"\r\n\r\n'; + body += `${params.code}\r\n`; + body += `--${boundary}--\r\n`; + + headers['Content-Type'] = `multipart/form-data; boundary=${boundary}`; + headers['Content-Length'] = Buffer.byteLength(body); break; case 'reissue': @@ -49,6 +66,8 @@ export const session_actions = async (params: T, addons?: IDef const data = await request(url, { method: method, + data: body, + headers: headers, addons, }); diff --git a/api/v2/users_activity.ts b/api/v2/users_activity.ts index 9972cef4..6251fc2e 100644 --- a/api/v2/users_activity.ts +++ b/api/v2/users_activity.ts @@ -12,8 +12,8 @@ export const users_activity = async (params: { limit?: number; offset?: number; }, addons?: IDefaultParams): Promise => { - if (params.id == null) { - return handleErrors(`Specify activity id`) as Response; + if (params?.id == null) { + return handleErrors(`Specify user id`) as Response; }; diff --git a/api/v2/users_beatmaps.ts b/api/v2/users_beatmaps.ts index d2c47c8f..44f34b72 100644 --- a/api/v2/users_beatmaps.ts +++ b/api/v2/users_beatmaps.ts @@ -14,11 +14,11 @@ export const users_beatmaps = async (params: { limit?: number; offset?: number; }, addons?: IDefaultParams): Promise => { - if (params.id == null) { + if (params?.id == null) { return handleErrors(`Specify user id`) as Response; }; - if (params.type == null) { + if (params?.type == null) { return handleErrors(`Specify beatmaps type`) as Response; }; diff --git a/api/v2/users_details.ts b/api/v2/users_details.ts index 7a0ff07b..b30f9717 100644 --- a/api/v2/users_details.ts +++ b/api/v2/users_details.ts @@ -12,7 +12,7 @@ export const users_details = async (params: { mode?: Modes_names; key?: 'id' | 'username'; }, addons?: IDefaultParams): Promise => { - if (params.user == null) { + if (params?.user == null) { return handleErrors(`Specify user id or name`) as Response; }; diff --git a/api/v2/users_kudosu.ts b/api/v2/users_kudosu.ts index f2287604..39e3ffb2 100644 --- a/api/v2/users_kudosu.ts +++ b/api/v2/users_kudosu.ts @@ -12,7 +12,7 @@ export const users_kudosu = async (params: { limit?: number; offset?: number; }, addons?: IDefaultParams): Promise => { - if (params.id == null) { + if (params?.id == null) { return handleErrors(`Specify user id`) as Response; }; diff --git a/api/v2/users_list.ts b/api/v2/users_list.ts index c17c707f..8c4ba5f8 100644 --- a/api/v2/users_list.ts +++ b/api/v2/users_list.ts @@ -8,7 +8,7 @@ type Response = UsersLisResponse[] & IError; export const users_list = async (params: { ids: number[], include_variants?: boolean }, addons?: IDefaultParams): Promise => { - if ((params.ids || [])?.length == 0) { + if ((params?.ids || [])?.length == 0) { return handleErrors(`Specify at least one user id`) as Response; }; diff --git a/api/v2/wiki_details.ts b/api/v2/wiki_details.ts index afa7cf15..ac5a7fd7 100644 --- a/api/v2/wiki_details.ts +++ b/api/v2/wiki_details.ts @@ -11,11 +11,11 @@ export const wiki_details = async (params: { locale: string; path_name: string; }, addons?: IDefaultParams): Promise => { - if (params.locale == null) { + if (params?.locale == null) { return handleErrors(`Specify locale code. Example: en`) as Response; }; - if (params.path_name == null) { + if (params?.path_name == null) { return handleErrors(`Specify wiki page path`) as Response; }; diff --git a/routes/v2.ts b/routes/v2.ts index f6f15cf4..c4856ca6 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -36,9 +36,29 @@ export const beatmaps = { *   * * ### Usage Example - * ```js - * // TBA - * ``` + * ```js + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.beatmaps.packs.list({ + * type: 'loved' + * }); + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); + * ``` * *   * @@ -59,7 +79,25 @@ export const beatmaps = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.beatmaps.packs.details('ST265'); + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -124,14 +162,36 @@ export const beatmaps = { *   * * ##### Parameters - * - `params.type` - The type to search for. + * - `params.type` - 'difficulty' or 'set'. * - `params.id` - The ID to search for. * *   * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.beatmaps.details({ + * type: 'set', + * id: 2182218 + * }); + * + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -159,6 +219,31 @@ export const beatmaps = { * *   * + * ### Usage Example + * ```js + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.beatmaps.events.list({ types: ['approve'] }); + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); + * ``` + * + *   + * * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2beatmapsetsevents) | [Check return types](../types/v2/beatmaps_events_list.ts) */ list: beatmaps_events_list, @@ -190,7 +275,40 @@ export const beatmaps = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * // only for downloading sets from osu host + * await auth.login({ + * type: 'lazer', + * login: login, + * password: password, + * tokenPath: './test.json' // please use for caching + * }); + * + * + * const progress_update = (...args) => { + * console.log(args); + * }; + * const set_id = 320118; + * + * + * const result = await v2.beatmaps.download({ + * type: 'set', + * host: 'gatari', + * id: set_id, + * file_path: `./cache/${set_id}.osz`, + * progress_track_fn: progress_update + * }); + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -225,7 +343,25 @@ export const beatmaps = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.beatmaps.discussions.list({ beatmapset_id: 2084849 }); + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -250,9 +386,26 @@ export const beatmaps = { * *   * - * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.beatmaps.discussions.posts(); + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -280,7 +433,25 @@ export const beatmaps = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.beatmaps.discussions.votes({ discussion_id: 4533908 }); + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -336,7 +507,27 @@ export const changelogs = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * const result = await v2.changelogs.list({ + * type: 'all', + * stream_name: 'web', + * }); + * // or + * const result = await v2.changelogs.list({ + * type: 'lookup', + * changelog: 'lazer' + * }); + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -359,7 +550,26 @@ export const changelogs = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * const result = await v2.changelogs.details({ + * stream_name: 'web', + * build_version: '2024.930.0' + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -401,7 +611,27 @@ export const comments = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * const result = await v2.comments.list({ + * type: 'news_post', + * id: 1430, + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -423,7 +653,24 @@ export const comments = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * const result = const result = await v2.comments.details(3035523); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -502,7 +749,32 @@ export const users = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.users.list({ + * ids: [2, 8928855, 7562902, 10083439], + * include_variants: true + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -526,7 +798,29 @@ export const users = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.users.kudosu({ id: 4830261 }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -550,7 +844,29 @@ export const users = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.users.events() + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -574,7 +890,29 @@ export const users = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.users.details({ user: 9893708, mode: 'osu', key: 'id' }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -599,7 +937,29 @@ export const users = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.users.beatmaps({ type: 'ranked', id: 4378277 }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -623,7 +983,29 @@ export const users = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.users.activity({ id: 11367222 }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -668,14 +1050,14 @@ export const scores = { * *   * - * ### Parameters for `params.type: 'beatmap_best'` + * ### Parameters for `params.type: 'user_beatmap_best'` * - `params.beatmap_id` - ID of the beatmap. * - `params.user_id` - ID of the user. * - `params.mods?` - Retrieve scores for specific mods. * *   * - * ### Parameters for `params.type: 'beatmap_all'` + * ### Parameters for `params.type: 'user_beatmap_all'` * - `params.beatmap_id` - ID of the beatmap. * - `params.user_id` - ID of the user. * @@ -691,7 +1073,51 @@ export const scores = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.scores.list({ + * type: 'user_beatmap_all', + * // or + * type: 'user_beatmap_best', + * beatmap_id: 1141858, + * user_id: 7562902 + * }); + * // or + * const result = await v2.scores.list({ + * type: 'leaderboard', + * beatmap_id: 1141858 + * }); + * // or + * const result = await v2.scores.list({ + * type: 'user_best', + * // or + * type: 'user_firsts', + * // or + * type: 'user_pinned', + * // or + * type: 'user_recent', + * user_id: 7562902, + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -715,7 +1141,31 @@ export const scores = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.scores.details({ + * id: 3321956713, + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -739,7 +1189,33 @@ export const scores = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'lazer', + * login: login, + * password: password, + * tokenPath: './test.json' // please use for caching + * }); + * + * const result = await v2.scores.download({ + * id: 3427873257, + * file_path: './cache/replay.osr' + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -783,7 +1259,32 @@ export const forums = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.forums.topics.details({ + * id: 881367 + * }); + * + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -840,7 +1341,61 @@ export const forums = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'lazer', + * login: login, + * password: password, + * tokenPath: './test.json' // please use for caching + * }); + * + * const result = await v2.forums.topics.actions({ + * type: 'create', + * + * forum_id: 52, + * + * title: 'hi', + * message: 'test', + * }); + * // or + * const result = await v2.forums.topics.actions({ + * type: 'reply', + * topic_id: 1888959, + * message: 'test' + * }); + * //or + * const result = await v2.forums.topics.actions({ + * type: 'edit_topic', + * + * topic_id: 986201, + * title: 'New title', + * + * post_id: 7270325, + * message: 'edited body/message', + + * }); + * // or + * const result = await v2.forums.topics.actions({ + * type: 'edit_post', + * + * post_id: 9500788, + * message: 'asdsadsada', + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -892,7 +1447,38 @@ import { search_all } from '../api/v2/search'; * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.search({ + * type: 'site', + * mode: 'all', + * query: 'mrekk' + * }); + * // or + * const result = await v2.search({ + * type: 'beatmaps', + * query: 'hyikrwa' + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -932,7 +1518,30 @@ export const assets = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * const result = await v2.assets.backgrounds({ + * type: 'seasonal' + * }); + * // or + * const result = v2.assets.backgrounds({ + * type: 'beatmapset', + * set_id: 2130552, + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -948,7 +1557,29 @@ export const assets = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.assets.dataFiles(); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -985,7 +1616,29 @@ export const news = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.news.list(); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -1007,8 +1660,33 @@ export const news = { *   * * ### Usage Example - * ``` - * // TBA + * ```js + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.news.details({ + * news_id: 1440, + * key: 'id' + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -1043,8 +1721,31 @@ export const notifications = { *   * * ### Usage Example - * ``` - * // TBA + * ```js + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'lazer', + * login: login, + * password: password, + * tokenPath: './test.json' // please use for caching + * }); + * + * const result = await v2.notifications.list(); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -1076,7 +1777,7 @@ export const notifications = { * * ### Usage Example * ```js - * // TBA + * not working atm * ``` * *   @@ -1139,7 +1840,38 @@ export const ranking = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.ranking.list({ + * type: 'performance', + * // or + * type: 'charts', + * // or + * type: 'country', + * // or + * type: 'score', + * mode: 'osu' + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -1172,7 +1904,29 @@ export const spotlights = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.spotlights.list(); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -1207,7 +1961,26 @@ export const wiki = { * * #### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * const result = await v2.wiki.details({ + * locale: 'EN', + * path_name: 'Main_page' + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -1242,7 +2015,30 @@ export const me = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'lazer', + * login, + * password + * tokenPath: './test.json' // please use for caching + * }); + * + * const result = await v2.me.download_quota(); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -1263,7 +2059,30 @@ export const me = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'lazer', + * login, + * password + * tokenPath: './test.json' // please use for caching + * }); + * + * const result = await v2.me.friends(); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -1285,7 +2104,29 @@ export const me = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.me.details(); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -1322,7 +2163,32 @@ export const matches = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.matches.list({ + * limit: 10, + * sort: 'id_asc' + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -1344,7 +2210,29 @@ export const matches = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * await v2.matches.details({ match_id: 16155689 }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -1389,7 +2277,29 @@ export const chat = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.chat.channels.list(); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -1433,7 +2343,57 @@ export const chat = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'lazer', + * login, + * password + * tokenPath: './test.json' // please use for caching + * }); + * + * const result = await v2.chat.channels.actions({ + * type: 'send', + * + * id: 5, + * is_action: false, + * message: '.' + * }); + * // or + * const result = await v2.chat.channels.actions({ + * type: 'join', + * + * id: 6, + * user_id: 9893708, + * }); + * // or + * const result = await v2.chat.channels.actions({ + * type: 'leave', + * + * id: 6, + * user_id: 9893708, + * }); + * // or + * const result = await v2.chat.channels.actions({ + * type: 'readed', + * + * channel_id: 45145743, + * message_id: 3626657177, + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -1450,7 +2410,7 @@ export const chat = { *   * * ### Parameters - * - `params.id` - The ID of the channel. + * - `params.channel_id` - The ID of the channel. * - `params.limit?` - Maximum number of messages to return. * - `params.since?` - Message id to start returning messages from. * - `params.until?` - Message id to end returning messages from. @@ -1461,7 +2421,30 @@ export const chat = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'lazer', + * login, + * password + * tokenPath: './test.json' // please use for caching + * }); + * + * const result = await v2.chat.messages({ id: 24594482 }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -1485,7 +2468,33 @@ export const chat = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'lazer', + * login, + * password + * tokenPath: './test.json' // please use for caching + * }); + * + * const result = await v2.chat.updates({ + * after_id: 3641891943, + * includes: ['presence', 'silences'] + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -1506,7 +2515,30 @@ export const chat = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'lazer', + * login, + * password + * tokenPath: './test.json' // please use for caching + * }); + * + * const result = await v2.chat.details({ channel_id: 24594482 }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -1536,13 +2568,48 @@ export const session = { * * ### Parameters * - `params.type` - Type of the action to perform. + * - `params.code` - verification code from email (only for `params.type: verify`) * - `addons` - Additional parameters to include in the request. * *   * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'lazer', + * login, + * password, + * tokenPath: './test.json' // please use for caching + * }); + * + * const result = await v2.session.actions({ + * type: 'verify', + * code: '7aah1f7e' + * }); + * // or + * const result = await v2.session.actions({ + * type: 'reissue', + * }); + * // or + * const result = await v2.session.actions({ + * type: 'delete', + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -1583,7 +2650,38 @@ export const rooms = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'lazer', + * login, + * password, + * tokenPath: './test.json' + * }); + * + * const result = await v2.rooms.list({ + * type: 'realtime', + * query: 'te', + * }); + * // or + * const result = await v2.rooms.list({ + * type: 'playlists', + * query: 'te', + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -1613,7 +2711,51 @@ export const rooms = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'lazer', + * login, + * password, + * tokenPath: './test.json' + * }); + * + * const result = await v2.rooms.scores({ + * type: 'all', + * + * id: 582709, + * playlist_id: 5302678, + * }); + * // or + * const result = await v2.rooms.scores({ + * type: 'single', + * + * id: 582709, + * playlist_id: 5302678, + * score_id: 2414452489, + * }); + * // or + * const result = await v2.rooms.scores({ + * type: 'user_highest', + * + * id: 582709, + * playlist_id: 5302678, + * user_id: 35015585, + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -1635,7 +2777,31 @@ export const rooms = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.rooms.details({ + * id: 582709, + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   @@ -1658,7 +2824,31 @@ export const rooms = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.rooms.leaderboard({ + * id: 582265, + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   diff --git a/utility/auth.ts b/utility/auth.ts index f0d11548..cf1478f1 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -74,6 +74,10 @@ type ResponseLogin = export const login = (params: auth_params): ResponseLogin => { + if (params?.type == null) { + return handleErrors('Specify login type'); + }; + credentials.type = params.type; if (params.tokenPath) credentials.tokenPath = params.tokenPath; From e4c4496e2cbe3e376d8a0e18171c97313f865d39 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 30 Sep 2024 22:36:31 +0300 Subject: [PATCH 220/259] fix beatmaps download --- api/v2/beatmaps_download.ts | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/api/v2/beatmaps_download.ts b/api/v2/beatmaps_download.ts index f678cfc3..9420a6f6 100644 --- a/api/v2/beatmaps_download.ts +++ b/api/v2/beatmaps_download.ts @@ -21,7 +21,7 @@ type params = ({ type: 'set'; id: number; - host: 'osu' | 'beatconnect' | 'nerinyan' | 'osu_direct_mirror' | 'sayobot' | 'gatari' | 'ripple' | 'catboy', + host: 'osu' | 'beatconnect' | 'nerinyan' | 'osu_direct_mirror' | 'sayobot' | 'gatari' | 'ripple' | 'catboy' | 'mino' | 'akatsuki', file_path: string; no_video?: boolean; @@ -79,13 +79,14 @@ export const beatmaps_download = async (params: T, addons?: ID // DOESNT WORK FOR SOME REASON case 'nerinyan': url = `https://api.nerinyan.moe/d/${params.id}${params.no_video ? '?nv=1' : ''}`; - headers = { - Accept: 'application/x-osu-beatmap-archive' - }; + headers['Accept'] = 'application/x-osu-beatmap-archive'; + headers['Referer'] = 'https://nerinyan.moe/'; + headers['User-Agent'] = `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36`; break; case 'osu_direct_mirror': - url = `https://api.osu.direct/d/${params.id}` + url = `https://osu.direct/api/d/${params.id}` + // headers['User-Agent'] = `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36`; break; case 'gatari': @@ -98,18 +99,20 @@ export const beatmaps_download = async (params: T, addons?: ID headers['Referer'] = 'https://ripple.moe/'; break; - // case 'akatsuki': - // url = `https://akatsuki.gg/d/${params.id}`; - // headers['Referer'] = 'https://akatsuki.gg/'; - // break; + case 'akatsuki': + url = `https://akatsuki.gg/d/${params.id}`; + headers['Referer'] = 'https://akatsuki.gg/'; + break; + case 'mino': case 'catboy': url = `https://catboy.best/d/${params.id}`; headers['Referer'] = 'https://catboy.best/'; + headers['User-Agent'] = `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36`; break; case 'osu': - if ((addons.authKey || cache.v2) == null) { + if ((addons?.authKey || cache.v2) == null) { return handleErrors('osu is not authorized') as Response; }; @@ -119,7 +122,7 @@ export const beatmaps_download = async (params: T, addons?: ID break; default: - return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; + return handleErrors(`Unsupported host: ${(params as any).host}`) as Response; }; From ae23f31e9cb69196b54c74df213ede2c0c67fcfd Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 30 Sep 2024 23:04:59 +0300 Subject: [PATCH 221/259] fix types --- api/v2/beatmaps_details.ts | 4 +- api/v2/beatmaps_discussions_posts.ts | 4 +- api/v2/beatmaps_discussions_votes.ts | 4 +- routes/v2.ts | 28 ++-- ...ulty.ts => beatmaps_details_difficulty.ts} | 0 ...details_set.ts => beatmaps_details_set.ts} | 0 types/v2/beatmaps_discussions_list.ts | 131 +++++++++++++++++- types/v2/beatmaps_discussions_posts.ts | 99 +++++++++++++ types/v2/beatmaps_discussions_votes.ts | 69 +++++++++ 9 files changed, 316 insertions(+), 23 deletions(-) rename types/v2/{beamaps_details_difficulty.ts => beatmaps_details_difficulty.ts} (100%) rename types/v2/{beamaps_details_set.ts => beatmaps_details_set.ts} (100%) create mode 100644 types/v2/beatmaps_discussions_posts.ts create mode 100644 types/v2/beatmaps_discussions_votes.ts diff --git a/api/v2/beatmaps_details.ts b/api/v2/beatmaps_details.ts index f519a858..64bbca7f 100644 --- a/api/v2/beatmaps_details.ts +++ b/api/v2/beatmaps_details.ts @@ -1,6 +1,6 @@ import { IDefaultParams, IError } from "../../types"; -import { BeamapsDetailsDifficulty } from "../../types/v2/beamaps_details_difficulty"; -import { BeamapsDetailsSet } from "../../types/v2/beamaps_details_set"; +import { BeamapsDetailsDifficulty } from "../../types/v2/beatmaps_details_difficulty"; +import { BeamapsDetailsSet } from "../../types/v2/beatmaps_details_set"; import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; diff --git a/api/v2/beatmaps_discussions_posts.ts b/api/v2/beatmaps_discussions_posts.ts index fe4e9dfd..3ca9ba6b 100644 --- a/api/v2/beatmaps_discussions_posts.ts +++ b/api/v2/beatmaps_discussions_posts.ts @@ -1,5 +1,5 @@ import { IDefaultParams, IError } from "../../types"; -import { BeatmapsDiscussionsListResponse } from "../../types/v2/beatmaps_discussions_list"; +import { BeatmapsDiscussionsPostsResponse } from "../../types/v2/beatmaps_discussions_posts"; import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -13,7 +13,7 @@ export const beatmaps_discussions_posts = async (params: { limit?: number; cursor_string?: string; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { if (params?.discussion_id) { // @ts-ignore params.beatmapset_discussion_id = params.discussion_id; diff --git a/api/v2/beatmaps_discussions_votes.ts b/api/v2/beatmaps_discussions_votes.ts index 04c308ad..db598867 100644 --- a/api/v2/beatmaps_discussions_votes.ts +++ b/api/v2/beatmaps_discussions_votes.ts @@ -1,5 +1,5 @@ import { IDefaultParams, IError } from "../../types"; -import { BeatmapsDiscussionsListResponse } from "../../types/v2/beatmaps_discussions_list"; +import { BeatmapsDiscussionsVotesResponse } from "../../types/v2/beatmaps_discussions_votes"; import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -15,7 +15,7 @@ export const beatmaps_discussions_votes = async (params: { limit?: number; cursor_string?: string; -}, addons?: IDefaultParams): Promise => { +}, addons?: IDefaultParams): Promise => { if (params?.discussion_id) { // @ts-ignore params.beatmapset_discussion_id = params.discussion_id; diff --git a/routes/v2.ts b/routes/v2.ts index c4856ca6..42a85b91 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -196,7 +196,7 @@ export const beatmaps = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-beatmap) | [Check return types](../types/v2/beatmaps_details.ts) + * [See documentation](https://osu.ppy.sh/docs/index.html#get-beatmap) | [Check return types](../types/v2/beatmaps_details_set.ts) */ details: beatmaps_details, /** @@ -244,7 +244,7 @@ export const beatmaps = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2beatmapsetsevents) | [Check return types](../types/v2/beatmaps_events_list.ts) + * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2beatmapsetsevents) | [Check return types](../types/v2/beatmaps_events.ts) */ list: beatmaps_events_list, }, @@ -313,7 +313,7 @@ export const beatmaps = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2beatmapsetsbeatmapsetdownload) | [Check return types](../types/v2/beatmaps_download.ts) + * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2beatmapsetsbeatmapsetdownload) */ download: beatmaps_download, /** @@ -532,7 +532,7 @@ export const changelogs = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-changelog-listing) | [Check return types](../types/v2/changelogs_list.ts) + * [See documentation](https://osu.ppy.sh/docs/index.html#get-changelog-listing) | [Check return types](../types/v2/changelogs_list_all.ts) */ list: changelogs_list, /** @@ -1122,7 +1122,7 @@ export const scores = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-beatmap-scores) | [Check return types](../types/v2/scores_list.ts) + * [See documentation](https://osu.ppy.sh/docs/index.html#get-beatmap-scores) | [Check return types](../types/v2/scores_list_user_recent.ts) * */ list: scores_list, @@ -1401,7 +1401,7 @@ export const forums = { *   * * - * [See documentation](https://osu.ppy.sh/docs/index.html#forum) | [Check return types](../) + * [See documentation](https://osu.ppy.sh/docs/index.html#forum) | [Check return types](../types/v2/forums_topics_actions_reply.ts) */ actions: forums_topics_actions, }, @@ -1483,7 +1483,7 @@ import { search_all } from '../api/v2/search'; * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#search) | [Check return types](../types/v2/search.ts) + * [See documentation](https://osu.ppy.sh/docs/index.html#search) | [Check return types](../types/v2/search_all.ts) * */ export const search = search_all; @@ -1584,7 +1584,7 @@ export const assets = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2seasonal-backgrounds) | [Check return types](../types/v2/assets_backgrounds.ts) + * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2seasonal-backgrounds) | [Check return types](../types/v2/assets_datafiles.ts) */ dataFiles: assets_dataFiles }; @@ -1782,7 +1782,7 @@ export const notifications = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#mark-notifications-as-read) | [Check return types](../types/v2/notification_actions.ts) + * [See documentation](https://osu.ppy.sh/docs/index.html#mark-notifications-as-read) */ actions: notification_actions, }; @@ -1876,7 +1876,7 @@ export const ranking = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-ranking) | [Check return types](../types/v2/ranking_list.ts) + * [See documentation](https://osu.ppy.sh/docs/index.html#get-ranking) | [Check return types](../types/v2/ranking_list_performance.ts) */ list: ranking_list, }; @@ -2398,7 +2398,7 @@ export const chat = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#send-message-to-channel) | [Check return types](../types/v2/chat_channels_actions.ts) + * [See documentation](https://osu.ppy.sh/docs/index.html#send-message-to-channel) */ actions: chat_channels_actions, }, @@ -2543,7 +2543,7 @@ export const chat = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-channel) | [Check return types](../types/v2/chat_channels.ts) + * [See documentation](https://osu.ppy.sh/docs/index.html#get-channel) | [Check return types](../types/v2/chat_details.ts) */ details: chat_details, actions: chat_actions, @@ -2614,7 +2614,7 @@ export const session = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#post-apiv2sessionverify) | [Check return types](../types/v2/session_actions.ts) + * [See documentation](https://osu.ppy.sh/docs/index.html#post-apiv2sessionverify) */ actions: session_actions, }; @@ -2760,7 +2760,7 @@ export const rooms = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-scores) | [Check return types](../types/v2/rooms_scores.ts) + * [See documentation](https://osu.ppy.sh/docs/index.html#get-scores) | [Check return types](../types/v2/rooms_scores_all.ts) */ scores: rooms_scores, /** diff --git a/types/v2/beamaps_details_difficulty.ts b/types/v2/beatmaps_details_difficulty.ts similarity index 100% rename from types/v2/beamaps_details_difficulty.ts rename to types/v2/beatmaps_details_difficulty.ts diff --git a/types/v2/beamaps_details_set.ts b/types/v2/beatmaps_details_set.ts similarity index 100% rename from types/v2/beamaps_details_set.ts rename to types/v2/beatmaps_details_set.ts diff --git a/types/v2/beatmaps_discussions_list.ts b/types/v2/beatmaps_discussions_list.ts index b71ba45c..4d0ba656 100644 --- a/types/v2/beatmaps_discussions_list.ts +++ b/types/v2/beatmaps_discussions_list.ts @@ -1,9 +1,107 @@ export interface BeatmapsDiscussionsListResponse { + beatmaps: Beatmap[] + beatmapsets: Beatmapset[] discussions: Discussion[] + included_discussions: any[] + reviews_config: ReviewsConfig users: User[] - votes: Vote[] - cursor?: Cursor - cursor_string?: string + cursor: Cursor + cursor_string: string +} + +export interface Beatmap { + beatmapset_id: number + difficulty_rating: number + id: number + mode: string + status: string + total_length: number + user_id: number + version: string + accuracy: number + ar: number + bpm: number + convert: boolean + count_circles: number + count_sliders: number + count_spinners: number + cs: number + deleted_at?: string + drain: number + hit_length: number + is_scoreable: boolean + last_updated: string + mode_int: number + passcount: number + playcount: number + ranked: number + url: string + checksum?: string +} + +export interface Beatmapset { + artist: string + artist_unicode: string + covers: Covers + creator: string + favourite_count: number + hype: any + id: number + nsfw: boolean + offset: number + play_count: number + preview_url: string + source: string + spotlight: boolean + status: string + title: string + title_unicode: string + track_id: any + user_id: number + video: boolean + bpm: number + can_be_hyped: boolean + deleted_at: any + discussion_enabled: boolean + discussion_locked: boolean + is_scoreable: boolean + last_updated: string + legacy_thread_url: string + nominations_summary: NominationsSummary + ranked: number + ranked_date: string + storyboard: boolean + submitted_date: string + tags: string + availability: Availability + has_favourited: boolean +} + +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} + +export interface NominationsSummary { + current: number + eligible_main_rulesets: string[] + required_meta: RequiredMeta +} + +export interface RequiredMeta { + main_ruleset: number + non_main_ruleset: number +} + +export interface Availability { + download_disabled: boolean + more_information: any } export interface Discussion { @@ -23,6 +121,33 @@ export interface Discussion { deleted_at: any last_post_at: string kudosu_denied: boolean + current_user_attributes: CurrentUserAttributes + starting_post: StartingPost +} + +export interface CurrentUserAttributes { + vote_score: number + can_moderate_kudosu: boolean + can_resolve: boolean + can_reopen: boolean + can_destroy: boolean +} + +export interface StartingPost { + beatmapset_discussion_id: number + created_at: string + deleted_at: any + deleted_by_id: any + id: number + last_editor_id?: number + message: string + system: boolean + updated_at: string + user_id: number +} + +export interface ReviewsConfig { + max_blocks: number } export interface User { diff --git a/types/v2/beatmaps_discussions_posts.ts b/types/v2/beatmaps_discussions_posts.ts new file mode 100644 index 00000000..bcc24e23 --- /dev/null +++ b/types/v2/beatmaps_discussions_posts.ts @@ -0,0 +1,99 @@ +export interface BeatmapsDiscussionsPostsResponse { + beatmapsets: Beatmapset[] + discussions: Discussion[] + posts: Post[] + users: User[] + cursor: Cursor + cursor_string: string +} + +export interface Beatmapset { + artist: string + artist_unicode: string + covers: Covers + creator: string + favourite_count: number + hype?: Hype + id: number + nsfw: boolean + offset: number + play_count: number + preview_url: string + source: string + spotlight: boolean + status: string + title: string + title_unicode: string + track_id: any + user_id: number + video: boolean +} + +export interface Covers { + cover: string + "cover@2x": string + card: string + "card@2x": string + list: string + "list@2x": string + slimcover: string + "slimcover@2x": string +} + +export interface Hype { + current: number + required: number +} + +export interface Discussion { + id: number + beatmapset_id: number + beatmap_id?: number + user_id: number + deleted_by_id: any + message_type: string + parent_id: any + timestamp?: number + resolved: boolean + can_be_resolved: boolean + can_grant_kudosu: boolean + created_at: string + updated_at: string + deleted_at: any + last_post_at: string + kudosu_denied: boolean +} + +export interface Post { + beatmapset_discussion_id: number + created_at: string + deleted_at: any + deleted_by_id: any + id: number + last_editor_id: any + message: string + system: boolean + updated_at: string + user_id: number +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour?: string + username: string +} + +export interface Cursor { + page: number + limit: number +} diff --git a/types/v2/beatmaps_discussions_votes.ts b/types/v2/beatmaps_discussions_votes.ts new file mode 100644 index 00000000..dc399176 --- /dev/null +++ b/types/v2/beatmaps_discussions_votes.ts @@ -0,0 +1,69 @@ +export interface BeatmapsDiscussionsVotesResponse { + discussions: Discussion[] + users: User[] + votes: Vote[] + cursor?: Cursor + cursor_string?: string +} + +export interface Discussion { + id: number + beatmapset_id: number + beatmap_id?: number + user_id: number + deleted_by_id: any + message_type: string + parent_id: any + timestamp?: number + resolved: boolean + can_be_resolved: boolean + can_grant_kudosu: boolean + created_at: string + updated_at: string + deleted_at: any + last_post_at: string + kudosu_denied: boolean +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour?: string + username: string + groups: Group[] +} + +export interface Group { + colour: string + has_listing: boolean + has_playmodes: boolean + id: number + identifier: string + is_probationary: boolean + name: string + short_name: string + playmodes: string[] +} + +export interface Vote { + beatmapset_discussion_id: number + created_at: string + id: number + score: number + updated_at: string + user_id: number +} + +export interface Cursor { + page: number + limit: number +} From d3d62804867169565c5a2939a14a3b806141e29b Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 30 Sep 2024 23:10:25 +0300 Subject: [PATCH 222/259] add requirements for lazer routes --- api/v2/beatmaps_download.ts | 6 +++++- api/v2/chat_channels_actions.ts | 6 ++++++ api/v2/chat_details.ts | 5 +++++ api/v2/chat_messages.ts | 5 +++++ api/v2/chat_updates.ts | 6 ++++++ api/v2/forums_topics_actions.ts | 6 ++++++ api/v2/notifications_list.ts | 6 ++++++ api/v2/rooms_details.ts | 5 +++++ api/v2/rooms_leaderboard.ts | 5 +++++ api/v2/rooms_list.ts | 5 +++++ api/v2/rooms_scores.ts | 6 ++++++ api/v2/scores_download.ts | 5 +++++ api/v2/session_actions.ts | 9 +++++++++ routes/v2.ts | 14 ++++++++------ 14 files changed, 82 insertions(+), 7 deletions(-) diff --git a/api/v2/beatmaps_download.ts b/api/v2/beatmaps_download.ts index 9420a6f6..aa95c9c0 100644 --- a/api/v2/beatmaps_download.ts +++ b/api/v2/beatmaps_download.ts @@ -1,6 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { download } from "../../utility/request"; -import { cache } from "../../utility/auth"; +import { cache, credentials } from "../../utility/auth"; import path from "path"; import fs from "fs"; import { handleErrors } from "../../utility/handleErrors"; @@ -112,6 +112,10 @@ export const beatmaps_download = async (params: T, addons?: ID break; case 'osu': + if (credentials.type != 'lazer') { + return handleErrors(`Login via lazer to use this endpoint`) as Response + }; + if ((addons?.authKey || cache.v2) == null) { return handleErrors('osu is not authorized') as Response; }; diff --git a/api/v2/chat_channels_actions.ts b/api/v2/chat_channels_actions.ts index 66b7a88e..4d90e274 100644 --- a/api/v2/chat_channels_actions.ts +++ b/api/v2/chat_channels_actions.ts @@ -3,6 +3,7 @@ import { IDefaultParams, IError } from "../../types"; import { chatChannelsActionsSendResponse } from "../../types/v2/chat_channels_actions_send"; import { chatChannelsActionsJoinResponse } from "../../types/v2/chat_channels_actions_join"; import { handleErrors } from "../../utility/handleErrors"; +import { credentials } from "../../utility/auth"; type params = ({ @@ -38,6 +39,11 @@ type Response = export const chat_channels_actions = async (params: T, addons?: IDefaultParams): Promise> => { + if (credentials.type != 'lazer') { + return handleErrors(`Login via lazer to use this endpoint`) as Response; + }; + + const object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; let method = 'POST'; diff --git a/api/v2/chat_details.ts b/api/v2/chat_details.ts index dcc715df..084bb01d 100644 --- a/api/v2/chat_details.ts +++ b/api/v2/chat_details.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { ChatDetailsResponse } from "../../types/v2/chat_details"; +import { credentials } from "../../utility/auth"; import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -8,6 +9,10 @@ type Response = ChatDetailsResponse & IError; export const chat_details = async (params: { channel_id: number }, addons?: IDefaultParams): Promise => { + if (credentials.type != 'lazer') { + return handleErrors(`Login via lazer to use this endpoint`) as Response + }; + if (params?.channel_id == null) { return handleErrors(`Specify channel id`) as Response; }; diff --git a/api/v2/chat_messages.ts b/api/v2/chat_messages.ts index dc4d5269..7d11af37 100644 --- a/api/v2/chat_messages.ts +++ b/api/v2/chat_messages.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { ChatMessagesResponse } from "../../types/v2/chat_messages"; +import { credentials } from "../../utility/auth"; import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -14,6 +15,10 @@ export const chat_messages = async (params: { until?: number; return_object?: boolean; }, addons?: IDefaultParams): Promise => { + if (credentials.type != 'lazer') { + return handleErrors(`Login via lazer to use this endpoint`) as Response + }; + if (params?.channel_id == null) { return handleErrors(`Specify channel id`) as Response; }; diff --git a/api/v2/chat_updates.ts b/api/v2/chat_updates.ts index f87fc4c4..2fd8257c 100644 --- a/api/v2/chat_updates.ts +++ b/api/v2/chat_updates.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { ChatUpdatesResponse } from "../../types/v2/chat_updates"; +import { credentials } from "../../utility/auth"; import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -12,6 +13,11 @@ export const chat_updates = async (params: { includes: ('presence' | 'silences' | 'messages')[]; history_since: number; }, addons?: IDefaultParams): Promise => { + if (credentials.type != 'lazer') { + return handleErrors(`Login via lazer to use this endpoint`) as Response + }; + + const data = await request(`https://osu.ppy.sh/api/v2/chat/updates`, { method: 'GET', params: { diff --git a/api/v2/forums_topics_actions.ts b/api/v2/forums_topics_actions.ts index 7940d088..765ecd8c 100644 --- a/api/v2/forums_topics_actions.ts +++ b/api/v2/forums_topics_actions.ts @@ -5,6 +5,7 @@ import { ForumsTopicsActionsReplyResponse } from "../../types/v2/forums_topics_a import { ForumsTopicsActionsEditTopicResponse } from "../../types/v2/forums_topics_actions_edit_topic"; import { ForumsTopicsActionsEditPostResponse } from "../../types/v2/forums_topics_actions_edit_post"; import { handleErrors } from "../../utility/handleErrors"; +import { credentials } from "../../utility/auth"; type params = ({ @@ -59,6 +60,11 @@ type Response = export const forums_topics_actions = async (params: T, addons?: IDefaultParams): Promise> => { + if (credentials.type != 'lazer') { + return handleErrors(`Login via lazer to use this endpoint`) as Response; + }; + + let object: any = {}; const body: any[] = []; diff --git a/api/v2/notifications_list.ts b/api/v2/notifications_list.ts index d616ba41..770461e9 100644 --- a/api/v2/notifications_list.ts +++ b/api/v2/notifications_list.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { NotificationsListResponse } from "../../types/v2/notifications_list"; +import { credentials } from "../../utility/auth"; import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -11,6 +12,11 @@ export const notifications_list = async (params: { max_id: string; unread_only: boolean; }, addons?: IDefaultParams): Promise => { + if (credentials.type != 'lazer') { + return handleErrors(`Login via lazer to use this endpoint`) as Response + }; + + const data = await request(`https://osu.ppy.sh/api/v2/notifications`, { method: 'GET', params: { diff --git a/api/v2/rooms_details.ts b/api/v2/rooms_details.ts index a0797a52..910b5c82 100644 --- a/api/v2/rooms_details.ts +++ b/api/v2/rooms_details.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { RoomsDetailsResponse } from "../../types/v2/rooms_details"; +import { credentials } from "../../utility/auth"; import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -8,6 +9,10 @@ type Response = RoomsDetailsResponse & IError; export const rooms_details = async (params: { id: number | 'latest' }, addons?: IDefaultParams): Promise => { + if (credentials.type != 'lazer') { + return handleErrors(`Login via lazer to use this endpoint`) as Response + }; + if (params.id == null) { return handleErrors(`Specify room id`) as Response; }; diff --git a/api/v2/rooms_leaderboard.ts b/api/v2/rooms_leaderboard.ts index 0653c43a..7fff2006 100644 --- a/api/v2/rooms_leaderboard.ts +++ b/api/v2/rooms_leaderboard.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { RoomsLeaderboardResponse } from "../../types/v2/rooms_leaderboard"; +import { credentials } from "../../utility/auth"; import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -11,6 +12,10 @@ export const rooms_leaderboard = async (params: { id: number; limit?: number; }, addons?: IDefaultParams): Promise => { + if (credentials.type != 'lazer') { + return handleErrors(`Login via lazer to use this endpoint`) as Response + }; + if (params?.id == null) { return handleErrors(`Specify room id`) as Response; }; diff --git a/api/v2/rooms_list.ts b/api/v2/rooms_list.ts index 567617ef..ac5bf0c2 100644 --- a/api/v2/rooms_list.ts +++ b/api/v2/rooms_list.ts @@ -1,5 +1,6 @@ import { IDefaultParams, IError } from "../../types"; import { RoomsListResponse } from "../../types/v2/rooms_list"; +import { credentials } from "../../utility/auth"; import { handleErrors } from "../../utility/handleErrors"; import { request } from "../../utility/request"; @@ -18,6 +19,10 @@ export const rooms_list = async (params: { cursor_string?: string; }, addons?: IDefaultParams): Promise => { + if (credentials.type != 'lazer') { + return handleErrors(`Login via lazer to use this endpoint`) as Response + }; + if (addons == null) addons = { apiVersion: '99999999' } diff --git a/api/v2/rooms_scores.ts b/api/v2/rooms_scores.ts index ad35c473..932f4f09 100644 --- a/api/v2/rooms_scores.ts +++ b/api/v2/rooms_scores.ts @@ -4,6 +4,7 @@ import { RoomsScoresSingleResponse } from "../../types/v2/rooms_scores_single"; import { RoomScoresUserHighestResponse } from "../../types/v2/rooms_scores_user_highest"; import { RoomsScoresAllResponse } from "../../types/v2/rooms_scores_all"; import { handleErrors } from "../../utility/handleErrors"; +import { credentials } from "../../utility/auth"; type params = ({ @@ -42,6 +43,11 @@ type Response = export const rooms_scores = async (params: T, addons?: IDefaultParams): Promise> => { + if (credentials.type != 'lazer') { + return handleErrors(`Login via lazer to use this endpoint`) as Response; + }; + + let object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; let method = 'GET'; diff --git a/api/v2/scores_download.ts b/api/v2/scores_download.ts index df5ae470..da573227 100644 --- a/api/v2/scores_download.ts +++ b/api/v2/scores_download.ts @@ -1,5 +1,6 @@ import { IError, Modes_names } from "../../types"; import { ScoresDownloadResponse } from "../../types/v2/scores_download"; +import { credentials } from "../../utility/auth"; import { handleErrors } from "../../utility/handleErrors"; import { download } from "../../utility/request"; @@ -12,6 +13,10 @@ export const scores_download = async (params: { mode?: Modes_names; file_path?: string; }): Promise => { + if (credentials.type != 'lazer') { + return handleErrors(`Login via lazer to use this endpoint`) as Response + }; + if (params?.id == null) { return handleErrors(`Specify score id`) as Response; }; diff --git a/api/v2/session_actions.ts b/api/v2/session_actions.ts index 1eff4af6..bb7eecc9 100644 --- a/api/v2/session_actions.ts +++ b/api/v2/session_actions.ts @@ -1,6 +1,7 @@ import { request } from "../../utility/request"; import { IDefaultParams, IError } from "../../types"; import { handleErrors } from "../../utility/handleErrors"; +import { credentials } from "../../utility/auth"; type params = ({ @@ -34,6 +35,10 @@ export const session_actions = async (params: T, addons?: IDef switch (params?.type) { case 'verify': + if (credentials.type != 'lazer') { + return handleErrors(`Login via lazer to use this endpoint`); + }; + if (params?.code == null) { return handleErrors(`Specify verification code`) as Response; }; @@ -52,6 +57,10 @@ export const session_actions = async (params: T, addons?: IDef break; case 'reissue': + if (credentials.type != 'lazer') { + return handleErrors(`Login via lazer to use this endpoint`); + }; + url += `/session/verify/reissue`; break; diff --git a/routes/v2.ts b/routes/v2.ts index 42a85b91..ba5930fa 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -2782,9 +2782,10 @@ export const rooms = { * async function main() { * try { * await auth.login({ - * type: 'v2', - * client_id: CLIENT_ID, - * client_secret: CLIENT_SECRET, + * type: 'lazer', + * login, + * password, + * tokenPath: './test.json' * }); * * const result = await v2.rooms.details({ @@ -2829,9 +2830,10 @@ export const rooms = { * async function main() { * try { * await auth.login({ - * type: 'v2', - * client_id: CLIENT_ID, - * client_secret: CLIENT_SECRET, + * type: 'lazer', + * login, + * password, + * tokenPath: './test.json' * }); * * const result = await v2.rooms.leaderboard({ From a2ba6e4a9e22fd27422c9e41d44a4699934b93af Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 30 Sep 2024 23:15:31 +0300 Subject: [PATCH 223/259] remove deprecated route --- routes/v2.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/routes/v2.ts b/routes/v2.ts index ba5930fa..fa875ee6 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -2402,7 +2402,6 @@ export const chat = { */ actions: chat_channels_actions, }, - list: chat_list, /** * ### `GET [/v2/chat/channels/{channel}/messages](https://osu.ppy.sh/docs/index.html#get-channel-messages) * `async` Get a list of messages in a channel. (Requires lazer authentication) From db0ca1175063d01e37dd212bd9bb316cc8763be4 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 30 Sep 2024 23:21:11 +0300 Subject: [PATCH 224/259] update `key` for `users_details` to support `@` --- api/v2/users_details.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/api/v2/users_details.ts b/api/v2/users_details.ts index b30f9717..333b150e 100644 --- a/api/v2/users_details.ts +++ b/api/v2/users_details.ts @@ -10,16 +10,19 @@ type Response = UsersDetailsResponse & IError; export const users_details = async (params: { user?: number | string; mode?: Modes_names; - key?: 'id' | 'username'; + key?: 'id' | 'username' | '@'; }, addons?: IDefaultParams): Promise => { if (params?.user == null) { return handleErrors(`Specify user id or name`) as Response; }; + let key = params?.key; + if (key == 'username') key = '@'; + const data = await request(`https://osu.ppy.sh/api/v2/users/${params.user}${params.mode ? `/${params.mode}` : ''}`, { method: 'GET', - params: { key: params.key }, + params: { key: key }, addons, }); From b05baa92c8a6470a3342d75e1aa636398559e4b8 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Mon, 30 Sep 2024 23:25:50 +0300 Subject: [PATCH 225/259] oops --- routes/v2.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/routes/v2.ts b/routes/v2.ts index fa875ee6..2766796d 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -2247,7 +2247,6 @@ export const matches = { import { chat_channels_list } from "../api/v2/chat_channels_list"; import { chat_channels_actions } from "../api/v2/chat_channels_actions"; -import { chat_list } from "../api/v2/chat_list"; import { chat_messages } from "../api/v2/chat_messages"; import { chat_updates } from "../api/v2/chat_updates"; import { chat_details } from "../api/v2/chat_details"; From d2e8689fb252d00db92b515d5bec534555cb0d8b Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 4 Oct 2024 21:59:16 +0300 Subject: [PATCH 226/259] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 04cab910..3d475487 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.35", + "version": "3.0.0-beta.36", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", From e22b559dd44f120e10d827e0b19ba10db6525eee Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Fri, 4 Oct 2024 23:09:07 +0300 Subject: [PATCH 227/259] add jsdoc to tools --- api/v2/beatmaps_download.ts | 75 ++++++++++++++++++++++++++++++ tools/accuracy.ts | 60 +++++++++++++++++++++--- tools/country.ts | 35 +++++++++++++- tools/index.ts | 49 +++++++++++++++----- tools/mods.ts | 57 +++++++++++++++++++---- tools/net-pp.ts | 59 ++++++++++++++++++------ tools/objects.ts | 91 ++++++++++++++++++++++++++++++++++--- tools/rank.ts | 46 ++++++++++++++++++- types/tools.ts | 1 + 9 files changed, 423 insertions(+), 50 deletions(-) diff --git a/api/v2/beatmaps_download.ts b/api/v2/beatmaps_download.ts index aa95c9c0..ba4561ca 100644 --- a/api/v2/beatmaps_download.ts +++ b/api/v2/beatmaps_download.ts @@ -41,6 +41,81 @@ type Response = { } & IError; +/** + * `async` Downloads a beatmap or beatmap set by given ID. (Supports different hosts) + * + *   + * + * ### Available hosts + * - `type:'difficulty'`: osu, osu_direct_mirror, catboy + * - `type:'set'`: osu, beatconnect, nerinyan, osu_direct_mirror, sayobot, gatari, ripple, catboy + * + *   + * + * ### Global Parameters + * - `params.type` - Type of the beatmap. + * - `params.id` - ID of the beatmap or beatmap set. + * - `params.host` - Host of the download source. + * - `params.file_path` - Path to the save location. + * - `params.overwrite` - Whether to overwrite the file if it already exists. + * + *   + * + * ### Parameters for `params.type:'set'` + * - `params.no_video?` - Whether to include video in the download. + * + *   + * + * ### Usage Example + * ```js + * const { auth, v2, tools } = require('osu-api-extended'); + * + * async function main() { + * try { + * // only for downloading sets from osu host + * await auth.login({ + * type: 'lazer', + * login: login, + * password: password, + * tokenPath: './test.json' // please use for caching + * }); + * + * + * const progress_update = (...args) => { + * console.log(args); + * }; + * const set_id = 320118; + * + * + * const result = await v2.beatmaps.download({ + * type: 'set', + * host: 'gatari', + * id: set_id, + * file_path: `./cache/${set_id}.osz`, + * progress_track_fn: progress_update + * }); + * // or + * const result = await tools.download_beatmaps({ + * type: 'set', + * host: 'gatari', + * id: set_id, + * file_path: `./cache/${set_id}.osz`, + * progress_track_fn: progress_update + * }); + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); + * ``` + * + *   + * + * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2beatmapsetsbeatmapsetdownload) + */ export const beatmaps_download = async (params: T, addons?: IDefaultParams): Promise => { const { dir } = path.parse(params.file_path); if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); diff --git a/tools/accuracy.ts b/tools/accuracy.ts index 248db655..e7865b5b 100644 --- a/tools/accuracy.ts +++ b/tools/accuracy.ts @@ -18,24 +18,70 @@ type Hits = { ok?: any; meh?: any; miss?: any; + + count_geki?: any; + count_300?: any; + count_katu?: any; + count_100?: any; + count_50?: any; + count_miss?: any; }; type Response = AccuracyResponse & IError; - +/** + * Calculate accuracy from play hits + * + *   + * + * ### Parameters + * - `hits.geki` or `hits.perfect` or `hits.count_geki` - Amount of geki's + * - `hits[300]` or `hits.great` or `hits.count_300` - Amount of 300's + * - `hits.katu` or `hits.good` or `hits.count_katu` - Amount of katu's + * - `hits[100]` or `hits.ok` or `hits.count_100` - Amount of 100's + * - `hits[50]` or `hits.meh` or `hits.count_50` - Amount of 50's + * - `hits[0]` or `hits.miss` or `hits.count_miss` - Amount of misses + * + * - `mode` - Number/Name of the gamemode + * + *   + * + * ### Usage Example + * ```js + * const { tools } = require('osu-api-extended'); + * + * function main() { + * try { + * const hits = { 300: 123, 100: 12, 50: 1, 0: 1 }; + * const result = tools.calculate_accuracy(hits, 'osu'); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); + * ``` + */ export const calculate_accuracy = (hits: Hits, mode: GamemodeEnum | string | number): Response => { if (Object.keys(hits).length == 0) { return handleErrors('Provide hits (300, 100, 50, etc)') as Response; }; - const geki = parseInt(hits?.geki || hits.perfect || '0'); - const h300 = parseInt(hits?.[300] || hits.great || '0'); - const katu = parseInt(hits?.katu || hits.good || '0'); - const h100 = parseInt(hits?.[100] || hits.ok || '0'); - const h50 = parseInt(hits?.[50] || hits.meh || '0'); - const h0 = parseInt(hits?.[0] || hits.miss || '0'); + const geki = parseInt(hits?.geki || hits.count_geki || hits.perfect || '0'); + const h300 = parseInt(hits?.[300] || hits.count_300 || hits.great || '0'); + const katu = parseInt(hits?.katu || hits.count_katu || hits.good || '0'); + const h100 = parseInt(hits?.[100] || hits.count_100 || hits.ok || '0'); + const h50 = parseInt(hits?.[50] || hits.count_50 || hits.meh || '0'); + const h0 = parseInt(hits?.[0] || hits.count_miss || hits.miss || '0'); let accuracy = 0.0; let fc_accuracy = 0.0; diff --git a/tools/country.ts b/tools/country.ts index 4a734ce1..6c0944bd 100644 --- a/tools/country.ts +++ b/tools/country.ts @@ -6,7 +6,40 @@ import { handleErrors } from "../utility/handleErrors"; type Response = CountryResponse & IError; - +/** + * Get country name and code by providing country name/code + * + *   + * + * ### Parameters + * - `name` - Name of the country or country code + * + *   + * + * ### Usage Example + * ```js + * const { tools } = require('osu-api-extended'); + * + * function main() { + * try { + * const result = tools.country_details('US'); + * // or + * const result = tools.country_details('United States'); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); + * ``` + */ export const country_details = (name: string): Response => { if (name == null || name == '') { return handleErrors('Specify country code or country name') as Response; diff --git a/tools/index.ts b/tools/index.ts index e9ebd877..89360ed3 100644 --- a/tools/index.ts +++ b/tools/index.ts @@ -1,11 +1,11 @@ import { handleErrors } from "../utility/handleErrors"; -export { beatmaps_download } from "../api/v2/beatmaps_download"; +export { beatmaps_download as download_beatmaps } from "../api/v2/beatmaps_download"; export { calculate_accuracy } from "./accuracy"; export { calculate_mods } from "./mods"; export { country_details } from "./country"; export { calculate_rank } from "./rank"; -export { calculate_total_objects, convert_hits } from "./objects"; +export { calculate_total_passed_objects, calculate_hits } from "./objects"; export { calculate_net_pp } from "./net-pp"; @@ -14,14 +14,45 @@ export const calculate_pp = () => { return handleErrors('Use rosu-pp-js instead'); }; - -export const build_url = ({ _direct, type, mode, value }: { +/** + * Create link for `user`, `score`, `editor_timing` and others + * + *   + * + * ### Parameters + * - `params._direct?` - Return osu direct link for type `beatmap` and `beatmapset` + * - `params.mode?` - Return legacy link for type `score` + * - `params.type` - Type of the link + * - `params.value` - Link url value, for example `beatmap id` or `user id` + * + *   + * + * ### Usage Example + * ```js + * const { tools } = require('osu-api-extended'); + * + * function main() { + * try { + * const result = tools.build_url({ type: 'beatmap', value: 4397592 }); + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); + * ``` + */ +export const build_url = (params: { _direct?: boolean; - mode: 'osu' | 'fruits' | 'mania' | 'taiko'; + mode?: 'osu' | 'fruits' | 'mania' | 'taiko'; - type: 'beatmap' | 'beatmapset' | 'editor_timing' | 'news' | 'match' | 'avatar' | 'user' | 'badge' | 'score' | 'beatmapset_download'; + type: 'beatmap' | 'beatmapset' | 'editor_timing' | 'news' | 'match' | 'avatar' | 'user' | 'badge' | 'score'; value: any; }) => { + const { _direct, type, mode, value } = params || {}; + switch (type) { case 'beatmap': return _direct == true ? `osu://b/${value}` : `https://osu.ppy.sh/b/${value}`; @@ -57,12 +88,8 @@ export const build_url = ({ _direct, type, mode, value }: { return `https://osu.ppy.sh/scores/${mode ? "/" + mode : ''}${value}`; - case 'beatmapset_download': - return `https://osu.ppy.sh/scores/${mode ? "/" + mode : ''}${value}`; - - default: - return ''; + return `Unsupported type: ${params?.type}`; }; }; diff --git a/tools/mods.ts b/tools/mods.ts index 0d57a96b..941d0965 100644 --- a/tools/mods.ts +++ b/tools/mods.ts @@ -54,17 +54,53 @@ export const ModsToName = (modsNumber: number, order?: boolean): string => { type Response = ModsResponse & IError; -// SWITCH STATEMENT CREATED ON PURPOSE BECAUSE IT'S WAY FASTER -export const calculate_mods = (ModsName: Mod[] | string | number, order?: boolean): Response => { - if (ModsName == null) { +/** + * Calculate mods number/name from number/name + * + *   + * + * ### Parameters + * - `mods` - Number / Name / Array of { acronym: "EZ" } + * - `order?` - Transform mods from DTHD to HDDT + * + *   + * + * ### Usage Example + * ```js + * const { tools } = require('osu-api-extended'); + * + * function main() { + * try { + * const result = tools.calculate_mods('HDDT'); + * // or + * const result = tools.calculate_mods(72); + * // or + * const result = tools.calculate_mods([{ acronym: "EZ" }]); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); + * ``` + */ +export const calculate_mods = (mods: Mod[] | string | number, order?: boolean): Response => { + if (mods == null) { return handleErrors(`Specify mods name (HDDT or 72)`) as Response; }; - if (typeof ModsName == 'number') { - const name = ModsToName(ModsName, order); + if (typeof mods == 'number') { + const name = ModsToName(mods, order); return { - number: ModsName, + number: mods, name: name, } as any; }; @@ -75,20 +111,21 @@ export const calculate_mods = (ModsName: Mod[] | string | number, order?: boolea let ModsArray = []; - if (Array.isArray(ModsName)) { - ModsArray = ModsName.map(r => r.acronym.toLowerCase()); + if (Array.isArray(mods)) { + ModsArray = mods.map(r => r.acronym.toLowerCase()); } else { - ModsArray = ModsName.toLowerCase().match(/.{1,2}/g); + ModsArray = mods.toLowerCase().match(/.{1,2}/g); }; if (!Array.isArray(ModsArray)) { - return handleErrors(`Can't convert mods (${ModsName}) to array of mods`) as Response; + return handleErrors(`Can't convert mods (${mods}) to array of mods`) as Response; }; + // SWITCH STATEMENT CREATED ON PURPOSE BECAUSE IT'S WAY FASTER for (let i = 0; i < ModsArray.length; i++) { const mod_name = ModsArray[i]; switch (mod_name) { diff --git a/tools/net-pp.ts b/tools/net-pp.ts index 2e9c78c4..2e706cf9 100644 --- a/tools/net-pp.ts +++ b/tools/net-pp.ts @@ -11,21 +11,54 @@ type Response = { } & IError; -export const calculate_net_pp = (params: { - scores: ScoresListUserBestResponse[] | number[]; - pp_value: number; - gamemode?: Modes_names; -}): Response => { - if (!Array.isArray(params.scores)) { - return handleErrors(`Provide array of scores or numbers`) as Response; +/** + * Calculate how much pp would you gain from a play + * + *   + * + * ### Parameters + * - `scores` - Plays pp or Array of scores + * - `pp` - Amount of play pp + * + *   + * + * ### Usage Example + * ```js + * const { tools } = require('osu-api-extended'); + * + * function main() { + * try { + * const plays = [1000, 900, 800, 700]; + * const scores = [{ id: 123, pp: 1000 }, { id: 123, pp: 555 }, { id: 123, pp: 234 }, { id: 123, pp: 100 }]; + * const result = tools.calculate_net_pp(plays, 400); + * // or + * const result = tools.calculate_net_pp(scores, 400); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); + * ``` + */ +export const calculate_net_pp = (scores: ScoresListUserBestResponse[] | number[], pp: number): Response => { + if (!Array.isArray(scores)) { + return handleErrors(`Provide array of scores or plays pp`) as Response; }; - if (!isFinite(params.pp_value) || params.pp_value == null) { - return handleErrors(`Specify pp`) as Response; + if (!isFinite(pp) || pp == null) { + return handleErrors(`Specify play pp`) as Response; }; - const pp_values = typeof params.scores[0] == 'number' ? params.scores : (params.scores as any[]).map(r => r.pp); + const pp_values = typeof scores[0] == 'number' ? scores : (scores as any[]).map(r => r.pp); pp_values.sort((a, b) => b - a); // weight the user's current scores. (see https://osu.ppy.sh/wiki/en/Performance_points/Weighting_system) @@ -34,7 +67,7 @@ export const calculate_net_pp = (params: { const total_pp_old = weighted_before.reduce((a, b) => a + b, 0); - if (params.pp_value < Math.min(pp_values[pp_values.length - 1])) + if (pp_values.length >= 100 && pp < Math.min(pp_values[pp_values.length - 1])) return { pp: 0, totalNow: total_pp_old, @@ -42,8 +75,8 @@ export const calculate_net_pp = (params: { } as Response; - // Push new pp_value - pp_values.push(params.pp_value); + // Push new pp + pp_values.push(pp); pp_values.sort((a, b) => b - a); diff --git a/tools/objects.ts b/tools/objects.ts index 04f53948..fe332392 100644 --- a/tools/objects.ts +++ b/tools/objects.ts @@ -19,19 +19,58 @@ type Hits = { meh?: any; miss?: any; - count_100?: any; - count_300?: any; - count_50?: any; count_geki?: any; + count_300?: any; count_katu?: any; + count_100?: any; + count_50?: any; count_miss?: any; }; type Response = TotalObjectsResponse & IError; - -export const calculate_total_objects = (hits: Hits, mode: GamemodeEnum | string | number): Response => { +/** + * Calculate total passed objects + * + *   + * + * ### Parameters + * - `hits.geki` or `hits.perfect` or `hits.count_geki` - Amount of geki's + * - `hits[300]` or `hits.great` or `hits.count_300` - Amount of 300's + * - `hits.katu` or `hits.good` or `hits.count_katu` - Amount of katu's + * - `hits[100]` or `hits.ok` or `hits.count_100` - Amount of 100's + * - `hits[50]` or `hits.meh` or `hits.count_50` - Amount of 50's + * - `hits[0]` or `hits.miss` or `hits.count_miss` - Amount of misses + * + * - `mode` - Number/Name of the gamemode + * + *   + * + * ### Usage Example + * ```js + * const { tools } = require('osu-api-extended'); + * + * function main() { + * try { + * const hits = { 300: 123, 100: 12, 50: 1, 0: 1 }; + * const result = tools.calculate_total_passed_objects(hits, 'osu'); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); + * ``` + */ +export const calculate_total_passed_objects = (hits: Hits, mode: GamemodeEnum | string | number): Response => { if (Object.keys(hits).length == 0) { return handleErrors('Provide hits (300, 100, 50, etc)') as Response; }; @@ -92,7 +131,47 @@ export const calculate_total_objects = (hits: Hits, mode: GamemodeEnum | string type ResponseConvert = ConvertHitsResponse & IError; -export const convert_hits = (hits: Hits, mode: GamemodeEnum | string | number): ResponseConvert => { +/** + * Calculate hits if play was an FC + * + *   + * + * ### Parameters + * - `hits.geki` or `hits.perfect` or `hits.count_geki` - Amount of geki's + * - `hits[300]` or `hits.great` or `hits.count_300` - Amount of 300's + * - `hits.katu` or `hits.good` or `hits.count_katu` - Amount of katu's + * - `hits[100]` or `hits.ok` or `hits.count_100` - Amount of 100's + * - `hits[50]` or `hits.meh` or `hits.count_50` - Amount of 50's + * - `hits[0]` or `hits.miss` or `hits.count_miss` - Amount of misses + * + * - `mode` - Number/Name of the gamemode + * + *   + * + * ### Usage Example + * ```js + * const { tools } = require('osu-api-extended'); + * + * function main() { + * try { + * const hits = { 300: 123, 100: 12, 50: 1, 0: 1 }; + * const result = tools.calculate_hits(hits, 'osu'); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); + * ``` + */ +export const calculate_hits = (hits: Hits, mode: GamemodeEnum | string | number): ResponseConvert => { if (Object.keys(hits).length == 0) { return handleErrors('Provide hits (300, 100, 50, etc)') as ResponseConvert; }; diff --git a/tools/rank.ts b/tools/rank.ts index 225c5133..289cb065 100644 --- a/tools/rank.ts +++ b/tools/rank.ts @@ -1,5 +1,6 @@ import { IError } from "../types"; import { GamemodeEnum } from "../types/enums"; +import { Mod } from "../types/mods"; import { RankResponse } from "../types/tools"; import { handleErrors } from "../utility/handleErrors"; import { calculate_accuracy } from "./accuracy"; @@ -25,8 +26,48 @@ type Hits = { type Response = RankResponse & IError; - -export const calculate_rank = (hits: Hits, mods: string | number = 0, mode: GamemodeEnum | string | number): Response => { +/** + * Calculate total passed objects + * + *   + * + * ### Parameters + * - `hits.geki` or `hits.perfect` or `hits.count_geki` - Amount of geki's + * - `hits[300]` or `hits.great` or `hits.count_300` - Amount of 300's + * - `hits.katu` or `hits.good` or `hits.count_katu` - Amount of katu's + * - `hits[100]` or `hits.ok` or `hits.count_100` - Amount of 100's + * - `hits[50]` or `hits.meh` or `hits.count_50` - Amount of 50's + * - `hits[0]` or `hits.miss` or `hits.count_miss` - Amount of misses + * + * - `mods` - Number / Name / Array of { acronym: "EZ" } + * - `mode` - Number/Name of the gamemode + * + *   + * + * ### Usage Example + * ```js + * const { tools } = require('osu-api-extended'); + * + * function main() { + * try { + * const hits = { 300: 123, 100: 12, 50: 1, 0: 1 }; + * const result = tools.calculate_rank(hits, 72, 'osu'); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); + * ``` + */ +export const calculate_rank = (hits: Hits, mods: Mod[] | string | number = 0, mode: GamemodeEnum | string | number): Response => { if (Object.keys(hits).length == 0) { return handleErrors('Provide hits (300, 100, 50, etc)') as Response; }; @@ -122,5 +163,6 @@ export const calculate_rank = (hits: Hits, mods: string | number = 0, mode: Game return { rank, + accuracy, } as Response; }; \ No newline at end of file diff --git a/types/tools.ts b/types/tools.ts index 78a7548b..1cb3b65b 100644 --- a/types/tools.ts +++ b/types/tools.ts @@ -14,6 +14,7 @@ export interface AccuracyResponse { }; export interface RankResponse { + accuracy: number; rank: string; }; From 06e70f5e65ec18b390dabbe019e0d35a402fa77a Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 5 Oct 2024 01:11:45 +0300 Subject: [PATCH 228/259] cache cli auth --- utility/auth.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/utility/auth.ts b/utility/auth.ts index cf1478f1..6630fd78 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -226,6 +226,12 @@ const lazer_login = async (login: string, password: string): Promise => { + if (cache.v2 == '' && credentials.cachedTokenPath != '') { + const is = token_exists(); + if (is) return; + }; + + const cl = readln.createInterface(process.stdin, process.stdout); const question = (q: string) => new Promise((res, rej) => cl.question(q + ': ', (answer: string) => res(answer))); @@ -255,6 +261,9 @@ const authorize_cli = async (client_id: number | string, client_secret: string, cache.v2 = response.access_token; + save_token(response); + + return response; }; From 7183e13dc987907312d14548fa3112666674c5e1 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 5 Oct 2024 01:12:24 +0300 Subject: [PATCH 229/259] rename tokenPath to cachedTokenPath --- api/v2/beatmaps_download.ts | 2 +- routes/v2.ts | 30 +++++++++++++++--------------- types/index.ts | 8 ++++---- utility/auth.ts | 20 ++++++++++---------- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/api/v2/beatmaps_download.ts b/api/v2/beatmaps_download.ts index ba4561ca..d03f12c2 100644 --- a/api/v2/beatmaps_download.ts +++ b/api/v2/beatmaps_download.ts @@ -77,7 +77,7 @@ type Response = { * type: 'lazer', * login: login, * password: password, - * tokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // please use for caching * }); * * diff --git a/routes/v2.ts b/routes/v2.ts index 2766796d..b142f385 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -284,7 +284,7 @@ export const beatmaps = { * type: 'lazer', * login: login, * password: password, - * tokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // please use for caching * }); * * @@ -1197,7 +1197,7 @@ export const scores = { * type: 'lazer', * login: login, * password: password, - * tokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // please use for caching * }); * * const result = await v2.scores.download({ @@ -1349,7 +1349,7 @@ export const forums = { * type: 'lazer', * login: login, * password: password, - * tokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // please use for caching * }); * * const result = await v2.forums.topics.actions({ @@ -1730,7 +1730,7 @@ export const notifications = { * type: 'lazer', * login: login, * password: password, - * tokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // please use for caching * }); * * const result = await v2.notifications.list(); @@ -2023,7 +2023,7 @@ export const me = { * type: 'lazer', * login, * password - * tokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // please use for caching * }); * * const result = await v2.me.download_quota(); @@ -2067,7 +2067,7 @@ export const me = { * type: 'lazer', * login, * password - * tokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // please use for caching * }); * * const result = await v2.me.friends(); @@ -2350,7 +2350,7 @@ export const chat = { * type: 'lazer', * login, * password - * tokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // please use for caching * }); * * const result = await v2.chat.channels.actions({ @@ -2427,7 +2427,7 @@ export const chat = { * type: 'lazer', * login, * password - * tokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // please use for caching * }); * * const result = await v2.chat.messages({ id: 24594482 }); @@ -2474,7 +2474,7 @@ export const chat = { * type: 'lazer', * login, * password - * tokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // please use for caching * }); * * const result = await v2.chat.updates({ @@ -2521,7 +2521,7 @@ export const chat = { * type: 'lazer', * login, * password - * tokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // please use for caching * }); * * const result = await v2.chat.details({ channel_id: 24594482 }); @@ -2581,7 +2581,7 @@ export const session = { * type: 'lazer', * login, * password, - * tokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // please use for caching * }); * * const result = await v2.session.actions({ @@ -2656,7 +2656,7 @@ export const rooms = { * type: 'lazer', * login, * password, - * tokenPath: './test.json' + * cachedTokenPath: './test.json' * }); * * const result = await v2.rooms.list({ @@ -2717,7 +2717,7 @@ export const rooms = { * type: 'lazer', * login, * password, - * tokenPath: './test.json' + * cachedTokenPath: './test.json' * }); * * const result = await v2.rooms.scores({ @@ -2783,7 +2783,7 @@ export const rooms = { * type: 'lazer', * login, * password, - * tokenPath: './test.json' + * cachedTokenPath: './test.json' * }); * * const result = await v2.rooms.details({ @@ -2831,7 +2831,7 @@ export const rooms = { * type: 'lazer', * login, * password, - * tokenPath: './test.json' + * cachedTokenPath: './test.json' * }); * * const result = await v2.rooms.leaderboard({ diff --git a/types/index.ts b/types/index.ts index 784112b5..99c944ae 100644 --- a/types/index.ts +++ b/types/index.ts @@ -51,7 +51,7 @@ export type auth_params = ({ client_secret: string; timeout?: number; - tokenPath?: string; + cachedTokenPath?: string; scopes: auth_scopes; } | { @@ -60,7 +60,7 @@ export type auth_params = ({ api_key: string; timeout?: number; - tokenPath?: string; + cachedTokenPath?: string; } | { type: 'lazer'; @@ -68,7 +68,7 @@ export type auth_params = ({ password: string; timeout?: number; - tokenPath?: string; + cachedTokenPath?: string; } | { type: 'cli'; @@ -79,7 +79,7 @@ export type auth_params = ({ state: string; timeout?: number; - tokenPath?: string; + cachedTokenPath?: string; scopes: auth_scopes; }); diff --git a/utility/auth.ts b/utility/auth.ts index 6630fd78..fcf2188b 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -30,7 +30,7 @@ export const credentials: { redirect_url: string; state: string; - tokenPath: string; + cachedTokenPath: string; scopes: auth_scopes; } = { @@ -47,7 +47,7 @@ export const credentials: { redirect_url: '', state: '', - tokenPath: '', + cachedTokenPath: '', scopes: ['public'], }; @@ -80,7 +80,7 @@ export const login = (params: auth_params): ResponseLogin credentials.type = params.type; - if (params.tokenPath) credentials.tokenPath = params.tokenPath; + if (params.cachedTokenPath) credentials.cachedTokenPath = params.cachedTokenPath; if (params.timeout) settings.timeout = params.timeout; @@ -134,10 +134,10 @@ export const refresh_token = async () => { const token_exists = () => { - if (!fs.existsSync(credentials.tokenPath)) return false; + if (!fs.existsSync(credentials.cachedTokenPath)) return false; try { - const authData: auth_response = JSON.parse(fs.readFileSync(credentials.tokenPath, 'utf8')); + const authData: auth_response = JSON.parse(fs.readFileSync(credentials.cachedTokenPath, 'utf8')); set_v2(authData.access_token); return true; @@ -148,18 +148,18 @@ const token_exists = () => { const save_token = (response: auth_response) => { - if (!credentials.tokenPath) return; + if (!credentials.cachedTokenPath) return; - const { dir } = path.parse(credentials.tokenPath); + const { dir } = path.parse(credentials.cachedTokenPath); if (fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); - fs.writeFileSync(credentials.tokenPath, JSON.stringify(response), 'utf8'); + fs.writeFileSync(credentials.cachedTokenPath, JSON.stringify(response), 'utf8'); }; const client_login = async (client_id: number | string, client_secret: string, scopes: auth_scopes): Promise => { - if (cache.v2 == '' && credentials.tokenPath != '') { + if (cache.v2 == '' && credentials.cachedTokenPath != '') { const is = token_exists(); if (is) return; }; @@ -192,7 +192,7 @@ const client_login = async (client_id: number | string, client_secret: string, s const lazer_login = async (login: string, password: string): Promise => { - if (cache.v2 == '' && credentials.tokenPath != '') { + if (cache.v2 == '' && credentials.cachedTokenPath != '') { const is = token_exists(); if (is) return; }; From 167b22ff8777be34e013f54a563e912a92b6f145 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 5 Oct 2024 01:12:29 +0300 Subject: [PATCH 230/259] typo --- tools/rank.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/rank.ts b/tools/rank.ts index 289cb065..7d55ed53 100644 --- a/tools/rank.ts +++ b/tools/rank.ts @@ -27,7 +27,7 @@ type Response = RankResponse & IError; /** - * Calculate total passed objects + * Calculate rank from play hits * *   * From e0e798aa530e3637dbbf660ba0e35dc12accf857 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 5 Oct 2024 01:34:22 +0300 Subject: [PATCH 231/259] check for cli auth + check scopes on some routes --- api/v2/chat_channels_actions.ts | 8 ++++++-- api/v2/chat_details.ts | 8 ++++++-- api/v2/chat_messages.ts | 8 ++++++-- api/v2/forums_topics_actions.ts | 8 ++++++-- api/v2/me_details.ts | 4 ++-- api/v2/me_friends.ts | 8 ++++++-- api/v2/rooms_details.ts | 4 ++-- api/v2/rooms_leaderboard.ts | 4 ++-- api/v2/rooms_list.ts | 4 ++-- api/v2/rooms_scores.ts | 4 ++-- api/v2/scores_download.ts | 4 ++-- types/index.ts | 2 ++ utility/auth.ts | 3 +++ 13 files changed, 47 insertions(+), 22 deletions(-) diff --git a/api/v2/chat_channels_actions.ts b/api/v2/chat_channels_actions.ts index 4d90e274..949446a3 100644 --- a/api/v2/chat_channels_actions.ts +++ b/api/v2/chat_channels_actions.ts @@ -39,8 +39,12 @@ type Response = export const chat_channels_actions = async (params: T, addons?: IDefaultParams): Promise> => { - if (credentials.type != 'lazer') { - return handleErrors(`Login via lazer to use this endpoint`) as Response; + if (credentials.type != 'lazer' && credentials.type != 'cli') { + return handleErrors(`Login via lazer or cli to use this endpoint`) as Response; + }; + + if (credentials.type == 'cli' && !credentials.scopes.includes('chat.write')) { + return handleErrors(`Requires "chat.read" scope`) as Response; }; diff --git a/api/v2/chat_details.ts b/api/v2/chat_details.ts index 084bb01d..0abad2cf 100644 --- a/api/v2/chat_details.ts +++ b/api/v2/chat_details.ts @@ -9,8 +9,12 @@ type Response = ChatDetailsResponse & IError; export const chat_details = async (params: { channel_id: number }, addons?: IDefaultParams): Promise => { - if (credentials.type != 'lazer') { - return handleErrors(`Login via lazer to use this endpoint`) as Response + if (credentials.type != 'lazer' && credentials.type != 'cli') { + return handleErrors(`Login via lazer or cli to use this endpoint`) as Response + }; + + if (credentials.type == 'cli' && !credentials.scopes.includes('chat.read')) { + return handleErrors(`Requires "chat.read" scope`) as Response }; if (params?.channel_id == null) { diff --git a/api/v2/chat_messages.ts b/api/v2/chat_messages.ts index 7d11af37..3ca912c3 100644 --- a/api/v2/chat_messages.ts +++ b/api/v2/chat_messages.ts @@ -15,8 +15,12 @@ export const chat_messages = async (params: { until?: number; return_object?: boolean; }, addons?: IDefaultParams): Promise => { - if (credentials.type != 'lazer') { - return handleErrors(`Login via lazer to use this endpoint`) as Response + if (credentials.type != 'lazer' && credentials.type != 'cli') { + return handleErrors(`Login via lazer or cli to use this endpoint`) as Response + }; + + if (credentials.type == 'cli' && !credentials.scopes.includes('chat.read')) { + return handleErrors(`Requires "chat.read" scope`) as Response }; if (params?.channel_id == null) { diff --git a/api/v2/forums_topics_actions.ts b/api/v2/forums_topics_actions.ts index 765ecd8c..1a5e5a40 100644 --- a/api/v2/forums_topics_actions.ts +++ b/api/v2/forums_topics_actions.ts @@ -60,8 +60,12 @@ type Response = export const forums_topics_actions = async (params: T, addons?: IDefaultParams): Promise> => { - if (credentials.type != 'lazer') { - return handleErrors(`Login via lazer to use this endpoint`) as Response; + if (credentials.type != 'lazer' && credentials.type != 'cli') { + return handleErrors(`Login via lazer or cli to use this endpoint`) as Response; + }; + + if (credentials.type == 'cli' && !credentials.scopes.includes('forum.write')) { + return handleErrors(`Requires "forum.write" scope`) as Response; }; diff --git a/api/v2/me_details.ts b/api/v2/me_details.ts index db79dce7..870bb7a7 100644 --- a/api/v2/me_details.ts +++ b/api/v2/me_details.ts @@ -9,8 +9,8 @@ type Response = MeDetailsResponse & IError; export const me_details = async (params: { mode: Modes_names }, addons?: IDefaultParams): Promise => { - if (credentials.type != 'lazer') { - return handleErrors(`Login via lazer to use this endpoint`) as Response + if (credentials.type != 'lazer' && credentials.type != 'cli') { + return handleErrors(`Login via lazer or cli to use this endpoint`) as Response }; diff --git a/api/v2/me_friends.ts b/api/v2/me_friends.ts index 7101a99a..7265795f 100644 --- a/api/v2/me_friends.ts +++ b/api/v2/me_friends.ts @@ -9,8 +9,12 @@ type Response = MeFriendsResponse[] & IError; export const me_friends = async (addons?: IDefaultParams): Promise => { - if (credentials.type != 'lazer') { - return handleErrors(`Login via lazer to use this endpoint`) as Response + if (credentials.type != 'lazer' && credentials.type != 'cli') { + return handleErrors(`Login via lazer or cli to use this endpoint`) as Response + }; + + if (credentials.type == 'cli' && !credentials.scopes.includes('friends.read')) { + return handleErrors(`Requires "friends.read" scope`) as Response }; diff --git a/api/v2/rooms_details.ts b/api/v2/rooms_details.ts index 910b5c82..f70143fa 100644 --- a/api/v2/rooms_details.ts +++ b/api/v2/rooms_details.ts @@ -9,8 +9,8 @@ type Response = RoomsDetailsResponse & IError; export const rooms_details = async (params: { id: number | 'latest' }, addons?: IDefaultParams): Promise => { - if (credentials.type != 'lazer') { - return handleErrors(`Login via lazer to use this endpoint`) as Response + if (credentials.type != 'lazer' && credentials.type != 'cli') { + return handleErrors(`Login via lazer or cli to use this endpoint`) as Response }; if (params.id == null) { diff --git a/api/v2/rooms_leaderboard.ts b/api/v2/rooms_leaderboard.ts index 7fff2006..9425ba8c 100644 --- a/api/v2/rooms_leaderboard.ts +++ b/api/v2/rooms_leaderboard.ts @@ -12,8 +12,8 @@ export const rooms_leaderboard = async (params: { id: number; limit?: number; }, addons?: IDefaultParams): Promise => { - if (credentials.type != 'lazer') { - return handleErrors(`Login via lazer to use this endpoint`) as Response + if (credentials.type != 'lazer' && credentials.type != 'cli') { + return handleErrors(`Login via lazer or cli to use this endpoint`) as Response }; if (params?.id == null) { diff --git a/api/v2/rooms_list.ts b/api/v2/rooms_list.ts index ac5bf0c2..2fd8afb5 100644 --- a/api/v2/rooms_list.ts +++ b/api/v2/rooms_list.ts @@ -19,8 +19,8 @@ export const rooms_list = async (params: { cursor_string?: string; }, addons?: IDefaultParams): Promise => { - if (credentials.type != 'lazer') { - return handleErrors(`Login via lazer to use this endpoint`) as Response + if (credentials.type != 'lazer' && credentials.type != 'cli') { + return handleErrors(`Login via lazer or cli to use this endpoint`) as Response }; if (addons == null) diff --git a/api/v2/rooms_scores.ts b/api/v2/rooms_scores.ts index 932f4f09..780a40db 100644 --- a/api/v2/rooms_scores.ts +++ b/api/v2/rooms_scores.ts @@ -43,8 +43,8 @@ type Response = export const rooms_scores = async (params: T, addons?: IDefaultParams): Promise> => { - if (credentials.type != 'lazer') { - return handleErrors(`Login via lazer to use this endpoint`) as Response; + if (credentials.type != 'lazer' && credentials.type != 'cli') { + return handleErrors(`Login via lazer or cli to use this endpoint`) as Response; }; diff --git a/api/v2/scores_download.ts b/api/v2/scores_download.ts index da573227..c852f08e 100644 --- a/api/v2/scores_download.ts +++ b/api/v2/scores_download.ts @@ -13,8 +13,8 @@ export const scores_download = async (params: { mode?: Modes_names; file_path?: string; }): Promise => { - if (credentials.type != 'lazer') { - return handleErrors(`Login via lazer to use this endpoint`) as Response + if (credentials.type != 'lazer' && credentials.type != 'cli') { + return handleErrors(`Login via lazer or cli to use this endpoint`) as Response }; if (params?.id == null) { diff --git a/types/index.ts b/types/index.ts index 99c944ae..ab4047a4 100644 --- a/types/index.ts +++ b/types/index.ts @@ -89,6 +89,8 @@ export type auth_response = { token_type: string; access_token: string; expires_in: number; + + scopes?: auth_scopes; }; export interface lazer_auth_response extends auth_response { diff --git a/utility/auth.ts b/utility/auth.ts index fcf2188b..05323f0b 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -140,6 +140,8 @@ const token_exists = () => { const authData: auth_response = JSON.parse(fs.readFileSync(credentials.cachedTokenPath, 'utf8')); set_v2(authData.access_token); + if (Array.isArray(authData.scopes)) credentials.scopes = authData.scopes; + return true; } catch (error) { return false; @@ -152,6 +154,7 @@ const save_token = (response: auth_response) => { const { dir } = path.parse(credentials.cachedTokenPath); if (fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); + response.scopes = credentials.scopes; fs.writeFileSync(credentials.cachedTokenPath, JSON.stringify(response), 'utf8'); }; From 5824b75228a52ce40fcd8e5415b94a83c1fb8a0f Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 5 Oct 2024 01:55:09 +0300 Subject: [PATCH 232/259] handle errors for `auth.authorize` and `auth.refresh_session` --- utility/auth.ts | 68 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 14 deletions(-) diff --git a/utility/auth.ts b/utility/auth.ts index 05323f0b..4f302028 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -292,15 +292,32 @@ export const build_url = ({ client_id, redirect_url, scopes, state }: { }; -export const authorize = async ({ code, mode, client_id, client_secret, redirect_url }: { +export const authorize = async (params: { code: string; - mode: Modes_names; + mode?: Modes_names; client_id: number | string; client_secret: string; redirect_url: string; }): Promise => { + if (params?.client_id == null) { + return handleErrors(`Specify client_id`); + }; + + if (params?.client_secret == null) { + return handleErrors(`Specify client_secret`); + }; + + if (params?.redirect_url == null) { + return handleErrors(`Specify redirect_url`); + }; + + if (params?.code == null) { + return handleErrors(`Specify code`); + }; + + const response = await request('https://osu.ppy.sh/oauth/token', { method: 'POST', headers: { @@ -309,17 +326,20 @@ export const authorize = async ({ code, mode, client_id, client_secret, redirect }, data: JSON.stringify({ grant_type: 'authorization_code', - client_id: client_id, - client_secret: client_secret, - redirect_uri: redirect_url, - code, + client_id: params.client_id, + client_secret: params.client_secret, + redirect_uri: params.redirect_url, + code: params.code, }) }); if (response.error) return handleErrors(response.error); - const user = await request(`https://osu.ppy.sh/api/v2/me/${mode}`, { + let url = 'https://osu.ppy.sh/api/v2/me'; + if (params?.mode) url += `/${params.mode}`; + + const user = await request(url, { method: 'GET', addons: { authKey: response.access_token, ignoreSessionRefresh: true } }); @@ -335,15 +355,32 @@ export const authorize = async ({ code, mode, client_id, client_secret, redirect }; -export const refresh_session = async ({ refresh_token, mode, client_id, client_secret, redirect_url }: { +export const refresh_session = async (params: { refresh_token: string; - mode: Modes_names; + mode?: Modes_names; client_id: number | string; client_secret: string; redirect_url: string; }): Promise => { + if (params?.client_id == null) { + return handleErrors(`Specify client_id`); + }; + + if (params?.client_secret == null) { + return handleErrors(`Specify client_secret`); + }; + + if (params?.redirect_url == null) { + return handleErrors(`Specify redirect_url`); + }; + + if (params?.refresh_token == null) { + return handleErrors(`Specify refresh_token`); + }; + + const response = await request('https://osu.ppy.sh/oauth/token', { method: 'POST', headers: { @@ -352,17 +389,20 @@ export const refresh_session = async ({ refresh_token, mode, client_id, client_s }, data: JSON.stringify({ grant_type: 'refresh_token', - client_id: client_id, - client_secret: client_secret, - redirect_uri: redirect_url, - refresh_token, + client_id: params.client_id, + client_secret: params.client_secret, + redirect_uri: params.redirect_url, + refresh_token: params.refresh_token, }) }); if (response.error) return handleErrors(response.error); - const user = await request(`https://osu.ppy.sh/api/v2/me/${mode}`, { + let url = 'https://osu.ppy.sh/api/v2/me'; + if (params?.mode) url += `/${params.mode}`; + + const user = await request(url, { method: 'GET', addons: { authKey: response.access_token, ignoreSessionRefresh: true } }); From b6eee57e76060b987dc62259dcaf6c6e9d3fab8d Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 5 Oct 2024 02:06:55 +0300 Subject: [PATCH 233/259] readme update --- README.md | 474 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 370 insertions(+), 104 deletions(-) diff --git a/README.md b/README.md index d5cf5e88..7636d707 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,35 @@ -# osu-api-extended - [![](https://img.shields.io/npm/v/osu-api-extended?color=AD745F&style=for-the-badge)](https://www.npmjs.org/package/osu-api-extended) [![](https://img.shields.io/bundlephobia/min/@aqilcont/osu-api-extended?color=5FAE89&label=size&style=for-the-badge)](https://www.npmjs.org/package/osu-api-extended) [![](https://img.shields.io/npm/dm/osu-api-extended?color=625FAD&style=for-the-badge)](https://npm-stat.com/charts.html?package=osu-api-extended) ![](https://img.shields.io/npm/l/osu-api-extended?color=AD5F8C&style=for-the-badge) -# Usage +# osu-api-extended + +quick links: [Features](#features) [Usage](#usage) ​ / ​ [Install](#installation) ​ / ​ [V1 Api](#api-v1) ​ / ​ [V2 Api](#api-v2) -## [Documentation](https://github.com/cyperdark/osu-api-extended/wiki) +
+
+ +## Features +- Api + - osu api v1: [official documentation](https://github.com/ppy/osu-api/wiki) + - osu api v2: [official documentation](https://osu.ppy.sh/docs/index.html) +- **Auto** session refresh +- You need to login only once on application start (preferable in main server file) +- Built-in **Tools** + - `tools.build_url` - Create link for `user`, `score`, `editor_timing` and others + - `tools.calculate_accuracy` - Calculate accuracy from play hits + - `tools.calculate_hits` - Calculate hits if play was an FC + - `tools.calculate_mods` - Calculate mods Number/Name from Number/Name + - `tools.calculate_net_pp` - Calculate how much pp would you gain from a play + - `tools.calculate_pp` - Create link for `user`, `score`, `editor_timing` and others + - `tools.calculate_rank` - Calculate rank from play hits + - `tools.calculate_total_passed_objects` - Calculate total passed objects + - `tools.country_details` - Get country name and code by providing country name/code + - `tools.download_beatmaps` - Downloads a beatmap or beatmap set by given ID. (Supports different hosts) + +
+
## Installation @@ -23,155 +45,399 @@ yarn install osu-api-extended pnpm install osu-api-extended ``` -
-

IF SOME ENDPOINTS NOT WORKING, dm me in discord: cyperdark#6890

+``` +bun install osu-api-extended +``` +

-

You need to login only once on application start (auto renew token for v2)

+## Quickstart -### API V1 +Links: [create your client here](https://osu.ppy.sh/home/account/edit#oauth 'https://osu.ppy.sh/home/account/edit#oauth') ​ / ​ [get your api key here](https://osu.ppy.sh/p/api 'https://osu.ppy.sh/p/api') -You can [get your api key here](https://osu.ppy.sh/p/api 'https://osu.ppy.sh/p/api') +quick links: [v2 - client auth](#client-auth) ​ / ​ [v2 - lazer auth](#lazer-auth) ​ / ​ [v2 - cli auth](#lazer-auth) -```javascript -const { v1, auth } = require('osu-api-extended') +
-const main = async () => { - auth.set_v1(api_key) +### Client Auth - const data = await v1.beatmap.diff(1256136) - console.log(data) -} +```js +import { auth } from 'osu-api-extended'; -main() + +async function main() { + try { + await auth.login({ + type: 'v2', + client_id: CLIENT_ID, + client_secret: CLIENT_SECRET, + cachedTokenPath: './client.json' // path to a file where will be stored auth token to prevent spam auth to osu + }); + + const result = await v2.users.details({ user: 'mrekk', mode: 'osu', key: '@' }); + if (result.error != null) { + console.log(result.error); + return; + }; + + + console.log(result); + } catch (error) { + console.log(error); + }; +}; + +main(); ``` -### API V2 +
-You can [create your client here](https://osu.ppy.sh/home/account/edit#oauth 'https://osu.ppy.sh/home/account/edit#oauth') +### Lazer Auth -```javascript -const { v2, auth } = require('osu-api-extended') +Authorization though your account -const main = async () => { - const SCOPE_LIST = ['public', ...]; +```js +import { auth } from 'osu-api-extended'; - // Auth via client - await auth.login('CLIENT_ID', 'CLIENT_SECRET', SCOPE_LIST); - // Auth via lazer credentials - await auth.login_lazer('YOUR_LOGIN', 'YOUR_PASSWORD'); +async function main() { + try { + await auth.login({ + type: 'v2', + login: LOGIN, + password: PASSWORD, + cachedTokenPath: './lazer.json' // path to a file where will be stored auth token to prevent spam auth to osu + }); - // Auth via oauth2 - await auth.authorize_cli('CLIENT_ID', 'CLIENT_SECRET', 'CALLBACK_URL', SCOPE_LIST); + const result = await v2.me.details(); + if (result.error != null) { + console.log(result.error); + return; + }; - const data = await v2.beatmap.id.details(1256136) - console.log(data) -} -main() + console.log(result); + } catch (error) { + console.log(error); + }; +}; + +main(); ``` -### V2 Auth users via page +
-```javascript -const { v2, auth } = require('osu-api-extended'); +### CLI Auth -// code example for redirect page -const redirect_page = async () => { - const SCOPE_LIST = ['public', ...]; +```js +import { auth } from 'osu-api-extended'; - const url = auth.build_url('CLIENT_ID', 'CLIENT_CALLBACK_URL', SCOPE_LIST); - return url; + +async function main() { + try { + await auth.login({ + type: 'cli', + client_id: CLIENT_ID, + client_secret: CLIENT_SECRET, + redirect_url: REDIRECT_URL, + scopes: ['public'], + cachedTokenPath: './cli.json' // path to a file where will be stored auth token to prevent spam auth to osu + }); + + const result = await v2.me.details(); + if (result.error != null) { + console.log(result.error); + return; + }; + + + console.log(result); + } catch (error) { + console.log(error); + }; }; -const callback_page = async () => { - const user_data = await auth.authorize(code, 'GAMEMODE', 'CLIENT_ID', 'CLIENT_SECRET', 'CLIENT_CALLBACK_URL'); - return user_data; +main(); +``` + +
+ +### Discord Verify + +```js +import { Client } from 'discord.js'; +import { auth } from 'osu-api-extended'; + +const discord_bot = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.MessageContent, GatewayIntentBits.GuildMessages] }); // no clue why i need those intents + + +// send this link to user +discord_bot.on('messageCreate', async message => { + if (message.author.bot) return; + if (!message.content.startsWith('!')) return; + + const [command, value1, value2] = message.content.split('!').join('').split(' '); + logger('command', { _c: 'yellowBright', v: command }, value1, value2); + + if (command == 'verify') { + const url = const url = auth.build_url({ + client_id: CLIENT_ID, + redirect_url: REDIRECT_URL, + scopes: ['identify'], + state: message.author.id + }); + + + message.reply(`Verify via this link: ${url}`); + return; + }; +}); + + + +// somewhere else verify this +function verifyUser(code, state) { + // it returns user object + const verify = await auth.authorize({ + code: code, + client_id: CLIENT_ID, + client_secret: CLIENT_SECRET, + redirect_url: REDIRECT_URL + }); + + + console.log(verify); }; +``` + +
+ +### Website login + +[Nitro](https://nitro.unjs.io) framework example +```js +import { auth } from 'osu-api-extended'; + + +// /auth page +export default defineEventHandler(event => { + const build_url = auth.build_url({ + client_id: CLIENT_ID, + redirect_uri: REDIRECT_URL, + scopes: ['identify'], + }); + + + return sendRedirect(event, build_url); +}); + + +// /callback page +export default defineEventHandler(async event => { + const { code } = getQuery(event); + const verify = await auth.authorize({ + code: code.toString(), + + client_id: CLIENT_ID, + client_secret: CLIENT_SECRET, + redirect_url: REDIRECT_URL, + }); + + + setCookie(event, 'user_id', verify.id.toString()); + setCookie(event, 'user_name', verify.username.toString()); + + setCookie(event, 'access_token', verify.access_token); + setCookie(event, 'refresh_token', verify.refresh_token); + + + return sendRedirect(event, '/'); +}); ``` -### V2 Discord auth helpers +
+
+ +## Tools ```javascript -// discord bot auth | REQUEIRE TO HAVE A SITE WHERE YOU'LL REDIRECT USERS AFTER AUTH -const discord_auth_link = async () => { - const SCOPE_LIST = ['public', ...]; +import { tools } from 'osu-api-extended'; - const url = auth.build_url('CLIENT_ID', 'CLIENT_CALLBACK_URL', SCOPE_LIST, 'DICSORD_USER_ID'); - return url; + +function build_url() { + try { + const result = tools.build_url({ type: 'beatmap', value: 4397592 }); + if (result.error != null) { + console.log(result.error); + return; + }; + + + console.log(result); + } catch (error) { + console.log(error); + }; }; -const discord_callback_page = async (code, state) => { - const user_data = await auth.authorize(code, 'GAMEMODE', 'CLIENT_ID', 'CLIENT_SECRET', 'CLIENT_CALLBACK_URL'); - return { - discord_user_id: state, - user_data +function download_beatmaps() { + try { + const set_id = 320118; + const progress_update = (...args) => { + console.log(args); + }; + + + const result = await tools.download_beatmaps({ + type: 'set', + host: 'gatari', + id: set_id, + file_path: `./cache/${set_id}.osz`, + progress_track_fn: progress_update + }); + if (result.error != null) { + console.log(result.error); + return; + }; + + + console.log(result); + } catch (error) { + console.log(error); }; }; -``` -### Tools +function calculate_accuracy() { + try { + const hits = { 300: 123, 100: 12, 50: 1, 0: 1 }; + const result = tools.calculate_accuracy(hits, 'osu'); + if (result.error != null) { + console.log(result.error); + return; + }; -```javascript -const { tools } = require('osu-api-extended') - -const main = async () => { - // Accuracy from hits - const accuracy = tools.accuracy(300, 5, 10, 0, 0, 0, 'osu') - - // Country name from country code - const country_name = tools.country('RU') - - // Download difficulty file - const diff_file = tools.download.difficulty(2379651, './', '2379651') - - // Calucalute pp for a difficulty - const pp_calc = tools.pp_calc(2379651) - - // Rank letter from hits - const rank = tools.rank( - { - geki: 236, - katu: 43, - 300: 640, - 100: 54, - 50: 5, - 0: 15 - }, - 'osu' - ) - - console.log({ accuracy, country_name, diff_file, pp_calc, rank }) -} - -main() -``` -### Mods + console.log(result); + } catch (error) { + console.log(error); + }; +}; -```javascript -const { mods } = require('osu-api-extended') -const main = async () => { - // Mods name from mods id - const name = mods.name(64) // DT +function calculate_mods() { + try { + const result = tools.calculate_mods('HDDT'); + // or + const result = tools.calculate_mods(72); + // or + const result = tools.calculate_mods([{ acronym: "EZ" }]); + if (result.error != null) { + console.log(result.error); + return; + }; - // Mods id from mods name - const id = mods.id('HDDT') // 72 - console.log({ name, id }) -} + console.log(result); + } catch (error) { + console.log(error); + }; +}; + + +function country_details() { + try { + const result = tools.country_details('US'); + // or + const result = tools.country_details('United States'); + if (result.error != null) { + console.log(result.error); + return; + }; + + + console.log(result); + } catch (error) { + console.log(error); + }; +}; + + +function calculate_rank() { + try { + const hits = { 300: 123, 100: 12, 50: 1, 0: 1 }; + const result = tools.calculate_rank(hits, 72, 'osu'); + if (result.error != null) { + console.log(result.error); + return; + }; + + + console.log(result); + } catch (error) { + console.log(error); + }; +}; -main() + +function calculate_total_passed_objects() { + try { + const hits = { 300: 123, 100: 12, 50: 1, 0: 1 }; + const result = tools.calculate_total_passed_objects(hits, 'osu'); + if (result.error != null) { + console.log(result.error); + return; + }; + + + console.log(result); + } catch (error) { + console.log(error); + }; +}; + + +function calculate_hits() { + try { + const hits = { 300: 123, 100: 12, 50: 1, 0: 1 }; + const result = tools.calculate_hits(hits, 'osu'); + if (result.error != null) { + console.log(result.error); + return; + }; + + + console.log(result); + } catch (error) { + console.log(error); + }; +}; + + +function calculate_net_pp() { + try { + const plays = [1000, 900, 800, 700]; + const scores = [{ id: 123, pp: 1000 }, { id: 123, pp: 555 }, { id: 123, pp: 234 }, { id: 123, pp: 100 }]; + const result = tools.calculate_net_pp(plays, 400); + // or + const result = tools.calculate_net_pp(scores, 400); + if (result.error != null) { + console.log(result.error); + return; + }; + + + console.log(result); + } catch (error) { + console.log(error); + }; +}; ``` # Dependencies -- [lzma-native](https://www.npmjs.com/package/lzma-native 'https://www.npmjs.com/package/lzma-native'): decompress data from replay -- [node-osr](npmjs.com/package/node-osr 'npmjs.com/package/node-osr'): Working with replay file +zero + - `request.ts` by [AqilCont](https://github.com/AqilCont 'https://github.com/AqilCont') From a48bbd409c0af031ed32165dc604970fea2a1a99 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 5 Oct 2024 02:20:44 +0300 Subject: [PATCH 234/259] oops --- api/v1/form/beatmap/scores.ts | 2 +- api/v1/form/match.ts | 4 ++-- api/v1/form/user/best.ts | 2 +- api/v1/form/user/recent.ts | 2 +- api/v1/routes/beatmap/creator.ts | 2 +- api/v1/routes/beatmap/diff.ts | 2 +- api/v1/routes/beatmap/scores.ts | 2 +- api/v1/routes/beatmap/set.ts | 2 +- tools/mods.ts | 4 ++++ 9 files changed, 13 insertions(+), 9 deletions(-) diff --git a/api/v1/form/beatmap/scores.ts b/api/v1/form/beatmap/scores.ts index 5166b4cf..d665964b 100644 --- a/api/v1/form/beatmap/scores.ts +++ b/api/v1/form/beatmap/scores.ts @@ -31,7 +31,7 @@ const name = (data: any, mode: any) => { }, mods: { id: +d.enabled_mods, - name: calculate_mods(+d.enabled_mods).name || '', + name: calculate_mods(+(d.enabled_mods || '0')).name || '', }, accuracy: 0, pp: parseFloat(d.pp), diff --git a/api/v1/form/match.ts b/api/v1/form/match.ts index fd62a869..feedfed6 100644 --- a/api/v1/form/match.ts +++ b/api/v1/form/match.ts @@ -45,7 +45,7 @@ const name = (data: any) => { }, mods: { id: +g.mods, - name: calculate_mods(+g.mods).name || '', + name: calculate_mods(+(g.mods || '0')).name || '', }, scores: [], }; @@ -77,7 +77,7 @@ const name = (data: any) => { }, mods: { id: +ss.enabled_mods, - name: calculate_mods(+ss.enabled_mods).name || '', + name: calculate_mods(+(ss.enabled_mods || '0')).name || '', }, rank: g.rank, pass: g.pass, diff --git a/api/v1/form/user/best.ts b/api/v1/form/user/best.ts index 604df5e2..78be81f4 100644 --- a/api/v1/form/user/best.ts +++ b/api/v1/form/user/best.ts @@ -32,7 +32,7 @@ const name = (data: any, mode: any) => { }, mods: { id: +d.enabled_mods, - name: calculate_mods(+d.enabled_mods).name || '', + name: calculate_mods(+(d.enabled_mods || '0')).name || '', }, accuracy: 0, pp: parseFloat(d.pp), diff --git a/api/v1/form/user/recent.ts b/api/v1/form/user/recent.ts index 60d9e5eb..24696155 100644 --- a/api/v1/form/user/recent.ts +++ b/api/v1/form/user/recent.ts @@ -31,7 +31,7 @@ const name = (data: any, mode: any) => { }, mods: { id: +d.enabled_mods, - name: calculate_mods(+d.enabled_mods).name || '', + name: calculate_mods(+(d.enabled_mods || '0')).name || '', }, accuracy: 0, }; diff --git a/api/v1/routes/beatmap/creator.ts b/api/v1/routes/beatmap/creator.ts index ff899974..047e18db 100644 --- a/api/v1/routes/beatmap/creator.ts +++ b/api/v1/routes/beatmap/creator.ts @@ -189,7 +189,7 @@ const name: types = async (user_id, obj = {}) => { a: obj.converted, h: obj.hash, since: obj.since, - mods: calculate_mods(obj.mods).number, + mods: calculate_mods(obj.mods || '').number, limit: obj.limit, }; if (params.m == -1) delete params.m; diff --git a/api/v1/routes/beatmap/diff.ts b/api/v1/routes/beatmap/diff.ts index 4a99243e..fa0ceb07 100644 --- a/api/v1/routes/beatmap/diff.ts +++ b/api/v1/routes/beatmap/diff.ts @@ -189,7 +189,7 @@ const name: types = async (id, obj = {}) => { a: obj.converted, h: obj.hash, since: obj.since, - mods: calculate_mods(obj.mods).number, + mods: calculate_mods(obj.mods || '').number, limit: obj.limit, }; if (params.m == -1) delete params.m; diff --git a/api/v1/routes/beatmap/scores.ts b/api/v1/routes/beatmap/scores.ts index 875268e3..8f562e2e 100644 --- a/api/v1/routes/beatmap/scores.ts +++ b/api/v1/routes/beatmap/scores.ts @@ -104,7 +104,7 @@ const name: types = async (id, obj = {}) => { b: id, u: obj.user, m: _mode.indexOf(obj.mode), - mods: calculate_mods(obj.mods).number, + mods: calculate_mods(obj.mods || '').number, type: obj.type, limit: obj.limit, }; diff --git a/api/v1/routes/beatmap/set.ts b/api/v1/routes/beatmap/set.ts index 0552b9d8..1ed9f801 100644 --- a/api/v1/routes/beatmap/set.ts +++ b/api/v1/routes/beatmap/set.ts @@ -188,7 +188,7 @@ const name: types = async (id, obj = {}) => { a: obj.converted, h: obj.hash, since: obj.since, - mods: calculate_mods(obj.mods).number, + mods: calculate_mods(obj.mods || '').number, limit: obj.limit, }; if (params.m == -1) delete params.m; diff --git a/tools/mods.ts b/tools/mods.ts index 941d0965..5d722617 100644 --- a/tools/mods.ts +++ b/tools/mods.ts @@ -96,6 +96,10 @@ export const calculate_mods = (mods: Mod[] | string | number, order?: boolean): return handleErrors(`Specify mods name (HDDT or 72)`) as Response; }; + if (mods == '') { + return { number: 0, name: '' } as any; + }; + if (typeof mods == 'number') { const name = ModsToName(mods, order); From 6e51782cf7ea8191eca29bd9870b89ec2d33f474 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 5 Oct 2024 02:20:49 +0300 Subject: [PATCH 235/259] fix readme --- README.md | 103 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 83 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 7636d707..2fb07b0f 100644 --- a/README.md +++ b/README.md @@ -5,28 +5,28 @@ # osu-api-extended -quick links: [Features](#features) [Usage](#usage) ​ / ​ [Install](#installation) ​ / ​ [V1 Api](#api-v1) ​ / ​ [V2 Api](#api-v2) +quick links: [Features](#features) [Usage](#usage) ​ / ​ [Install](#installation) ​ / ​ [Quickstart](#quickstart) ​ / ​ [Tools](#tools) -

## Features -- Api - - osu api v1: [official documentation](https://github.com/ppy/osu-api/wiki) - - osu api v2: [official documentation](https://osu.ppy.sh/docs/index.html) -- **Auto** session refresh -- You need to login only once on application start (preferable in main server file) -- Built-in **Tools** - - `tools.build_url` - Create link for `user`, `score`, `editor_timing` and others - - `tools.calculate_accuracy` - Calculate accuracy from play hits - - `tools.calculate_hits` - Calculate hits if play was an FC - - `tools.calculate_mods` - Calculate mods Number/Name from Number/Name - - `tools.calculate_net_pp` - Calculate how much pp would you gain from a play - - `tools.calculate_pp` - Create link for `user`, `score`, `editor_timing` and others - - `tools.calculate_rank` - Calculate rank from play hits - - `tools.calculate_total_passed_objects` - Calculate total passed objects - - `tools.country_details` - Get country name and code by providing country name/code - - `tools.download_beatmaps` - Downloads a beatmap or beatmap set by given ID. (Supports different hosts) +- [ ] Api + - [ ] osu api v1: [official documentation](https://github.com/ppy/osu-api/wiki) + - [ ] osu api v2: [official documentation](https://osu.ppy.sh/docs/index.html) +- [ ] **Auto** session refresh +- [ ] You need to login only once on application start (preferable in main server file) +- [ ] Built-in **Tools** + - [ ] `tools.build_url` - Create link for `user`, `score`, `editor_timing` and others + - [ ] `tools.calculate_accuracy` - Calculate accuracy from play hits + - [ ] `tools.calculate_hits` - Calculate hits if play was an FC + - [ ] `tools.calculate_mods` - Calculate mods Number/Name from Number/Name + - [ ] `tools.calculate_net_pp` - Calculate how much pp would you gain from a play + - [ ] `tools.calculate_pp` - Create link for `user`, `score`, `editor_timing` and others + - [ ] `tools.calculate_rank` - Calculate rank from play hits + - [ ] `tools.calculate_total_passed_objects` - Calculate total passed objects + - [ ] `tools.country_details` - Get country name and code by providing country name/code + - [ ] `tools.download_beatmaps` - Downloads a beatmap or beatmap set by given ID. (Supports different hosts) +- [ ] Setting to prevent throw, [instead send .error](#prevent-throw-errors)

@@ -56,7 +56,7 @@ bun install osu-api-extended Links: [create your client here](https://osu.ppy.sh/home/account/edit#oauth 'https://osu.ppy.sh/home/account/edit#oauth') ​ / ​ [get your api key here](https://osu.ppy.sh/p/api 'https://osu.ppy.sh/p/api') -quick links: [v2 - client auth](#client-auth) ​ / ​ [v2 - lazer auth](#lazer-auth) ​ / ​ [v2 - cli auth](#lazer-auth) +quick links: [v2 - client auth](#client-auth) ​ / ​ [v2 - lazer auth](#lazer-auth) ​ / ​ [v2 - cli auth](#cli-auth) ​ / ​ [v2 - Discord Verify](#discord-verify) ​ / ​ [v2 - Website login](#website-login) ​ / ​ [v1 usage](#v1-usage) ​ / ​ [v2 - prevent throw errors](#prevent-throw-errors)
@@ -257,9 +257,72 @@ export default defineEventHandler(async event => { }); ``` +
+ +### V1 usage + +```js +import { auth, v1 } from 'osu-api-extended'; + + +async function main() { + try { + auth.login({ + type: 'v1', + api_key: API_KEY, + }); + + + const beatmap = await v1.beatmap.diff(3798013); + console.log(beatmap); + + } catch (error) { + console.log(error); + }; +}; + +main(); +``` + + +### Prevent throw errors + +```js +import { auth } from 'osu-api-extended'; + +auth.settings.throwErrors = false; + + +async function main() { + try { + await auth.login({ + type: 'v2', + client_id: CLIENT_ID, + client_secret: CLIENT_SECRET, + }); + + const result = await v2.beatmaps.events.list({ types: ['approve'] }); + if (result.error instanceof Error) { + // or + if (result.error != null) { + console.log(result.error); + return; + }; + + console.log(result); + } catch (error) { + console.log(error); + }; +}; + + +main(); +``` +

+ ## Tools ```javascript @@ -436,7 +499,7 @@ function calculate_net_pp() { }; ``` -# Dependencies +## Dependencies zero From f426d422b8d14a0ed74d678230f4130f58b2c56f Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 5 Oct 2024 02:22:37 +0300 Subject: [PATCH 236/259] a --- README.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 2fb07b0f..acd4ba66 100644 --- a/README.md +++ b/README.md @@ -10,23 +10,23 @@ quick links: [Features](#features) [Usage](#usage) ​ / ​ [Install](#
## Features -- [ ] Api - - [ ] osu api v1: [official documentation](https://github.com/ppy/osu-api/wiki) - - [ ] osu api v2: [official documentation](https://osu.ppy.sh/docs/index.html) -- [ ] **Auto** session refresh -- [ ] You need to login only once on application start (preferable in main server file) -- [ ] Built-in **Tools** - - [ ] `tools.build_url` - Create link for `user`, `score`, `editor_timing` and others - - [ ] `tools.calculate_accuracy` - Calculate accuracy from play hits - - [ ] `tools.calculate_hits` - Calculate hits if play was an FC - - [ ] `tools.calculate_mods` - Calculate mods Number/Name from Number/Name - - [ ] `tools.calculate_net_pp` - Calculate how much pp would you gain from a play - - [ ] `tools.calculate_pp` - Create link for `user`, `score`, `editor_timing` and others - - [ ] `tools.calculate_rank` - Calculate rank from play hits - - [ ] `tools.calculate_total_passed_objects` - Calculate total passed objects - - [ ] `tools.country_details` - Get country name and code by providing country name/code - - [ ] `tools.download_beatmaps` - Downloads a beatmap or beatmap set by given ID. (Supports different hosts) -- [ ] Setting to prevent throw, [instead send .error](#prevent-throw-errors) +- [x] Api + - [x] osu api v1: [official documentation](https://github.com/ppy/osu-api/wiki) + - [x] osu api v2: [official documentation](https://osu.ppy.sh/docs/index.html) +- [x] **Auto** session refresh +- [x] You need to login only once on application start (preferable in main server file) +- [x] Built-in **Tools** + - [x] `tools.build_url` - Create link for `user`, `score`, `editor_timing` and others + - [x] `tools.calculate_accuracy` - Calculate accuracy from play hits + - [x] `tools.calculate_hits` - Calculate hits if play was an FC + - [x] `tools.calculate_mods` - Calculate mods Number/Name from Number/Name + - [x] `tools.calculate_net_pp` - Calculate how much pp would you gain from a play + - [x] `tools.calculate_pp` - Create link for `user`, `score`, `editor_timing` and others + - [x] `tools.calculate_rank` - Calculate rank from play hits + - [x] `tools.calculate_total_passed_objects` - Calculate total passed objects + - [x] `tools.country_details` - Get country name and code by providing country name/code + - [x] `tools.download_beatmaps` - Downloads a beatmap or beatmap set by given ID. (Supports different hosts) +- [x] Setting to prevent throw, [instead send .error](#prevent-throw-errors)

From 02337f02de0847543854353d859cff0ea7d66f3e Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 5 Oct 2024 02:54:44 +0300 Subject: [PATCH 237/259] move errors to function level --- api/v1/routes/beatmap/creator.ts | 2 +- api/v1/routes/beatmap/diff.ts | 6 ++--- api/v1/routes/beatmap/scores.ts | 2 +- api/v1/routes/beatmap/set.ts | 2 +- api/v1/routes/match.ts | 4 ++-- api/v1/routes/user/details.ts | 4 ++-- api/v1/routes/user/scores-category.ts | 2 +- api/v2/assets_backgrounds.ts | 4 ++-- api/v2/assets_dataFiles.ts | 2 +- api/v2/beatmaps_actions.ts | 2 +- api/v2/beatmaps_details.ts | 6 ++--- api/v2/beatmaps_discussions_list.ts | 2 +- api/v2/beatmaps_discussions_posts.ts | 2 +- api/v2/beatmaps_discussions_votes.ts | 2 +- api/v2/beatmaps_download.ts | 12 +++++----- api/v2/beatmaps_events_list.ts | 2 +- api/v2/beatmaps_lookup.ts | 12 +++++----- api/v2/beatmaps_packs_details.ts | 4 ++-- api/v2/beatmaps_packs_list.ts | 2 +- api/v2/changelogs_details.ts | 6 ++--- api/v2/changelogs_list.ts | 6 ++--- api/v2/chat_actions.ts | 6 ++--- api/v2/chat_channels_actions.ts | 16 +++++++------- api/v2/chat_channels_list.ts | 2 +- api/v2/chat_details.ts | 8 +++---- api/v2/chat_list.ts | 2 +- api/v2/chat_messages.ts | 8 +++---- api/v2/chat_updates.ts | 4 ++-- api/v2/comments_actions.ts | 20 ++++++++--------- api/v2/comments_details.ts | 4 ++-- api/v2/comments_list.ts | 2 +- api/v2/forums_topics_actions.ts | 30 ++++++++++++------------- api/v2/forums_topics_details.ts | 4 ++-- api/v2/matches_details.ts | 4 ++-- api/v2/matches_list.ts | 2 +- api/v2/me_details.ts | 4 ++-- api/v2/me_download_quota.ts | 4 ++-- api/v2/me_friends.ts | 6 ++--- api/v2/news_details.ts | 4 ++-- api/v2/news_list.ts | 2 +- api/v2/notification_actions.ts | 6 ++--- api/v2/notifications_list.ts | 4 ++-- api/v2/ranking_list.ts | 6 ++--- api/v2/rooms_details.ts | 6 ++--- api/v2/rooms_leaderboard.ts | 6 ++--- api/v2/rooms_list.ts | 4 ++-- api/v2/rooms_scores.ts | 10 ++++----- api/v2/scores_details.ts | 4 ++-- api/v2/scores_download.ts | 6 ++--- api/v2/scores_list.ts | 18 +++++++-------- api/v2/search.ts | 2 +- api/v2/session_actions.ts | 8 +++---- api/v2/spotlights_list.ts | 2 +- api/v2/users_activity.ts | 4 ++-- api/v2/users_beatmaps.ts | 6 ++--- api/v2/users_details.ts | 4 ++-- api/v2/users_events.ts | 4 ++-- api/v2/users_kudosu.ts | 4 ++-- api/v2/users_list.ts | 6 ++--- api/v2/wiki_details.ts | 6 ++--- tools/accuracy.ts | 4 ++-- tools/country.ts | 6 ++--- tools/index.ts | 2 +- tools/mods.ts | 4 ++-- tools/net-pp.ts | 4 ++-- tools/objects.ts | 8 +++---- tools/rank.ts | 2 +- utility/auth.ts | 32 +++++++++++++-------------- utility/handleErrors.ts | 3 +-- 69 files changed, 199 insertions(+), 200 deletions(-) diff --git a/api/v1/routes/beatmap/creator.ts b/api/v1/routes/beatmap/creator.ts index 047e18db..58688a61 100644 --- a/api/v1/routes/beatmap/creator.ts +++ b/api/v1/routes/beatmap/creator.ts @@ -200,7 +200,7 @@ const name: types = async (user_id, obj = {}) => { params: params, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); if (data.length == 0) return []; diff --git a/api/v1/routes/beatmap/diff.ts b/api/v1/routes/beatmap/diff.ts index fa0ceb07..3ef8c069 100644 --- a/api/v1/routes/beatmap/diff.ts +++ b/api/v1/routes/beatmap/diff.ts @@ -189,7 +189,7 @@ const name: types = async (id, obj = {}) => { a: obj.converted, h: obj.hash, since: obj.since, - mods: calculate_mods(obj.mods || '').number, + mods: calculate_mods(obj.mods).number, limit: obj.limit, }; if (params.m == -1) delete params.m; @@ -199,9 +199,9 @@ const name: types = async (id, obj = {}) => { method: 'GET', params: params, }); - if (data.error) return handleErrors(data.error) as Response; + if (data.error) return handleErrors(new Error(data.error)) as Response; + if (data.length == 0) return handleErrors(new Error('Beatmap not found')) as Response; - if (data.length == 0) return handleErrors('Beatmap not found') as Response; const format = form(data); return format; diff --git a/api/v1/routes/beatmap/scores.ts b/api/v1/routes/beatmap/scores.ts index 8f562e2e..79bd5ee8 100644 --- a/api/v1/routes/beatmap/scores.ts +++ b/api/v1/routes/beatmap/scores.ts @@ -115,7 +115,7 @@ const name: types = async (id, obj = {}) => { params: params, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); if (data.length == 0) return []; diff --git a/api/v1/routes/beatmap/set.ts b/api/v1/routes/beatmap/set.ts index 1ed9f801..5ac1e458 100644 --- a/api/v1/routes/beatmap/set.ts +++ b/api/v1/routes/beatmap/set.ts @@ -198,7 +198,7 @@ const name: types = async (id, obj = {}) => { params: params, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); if (data.length == 0) return []; diff --git a/api/v1/routes/match.ts b/api/v1/routes/match.ts index abc19cb1..ca23ddcb 100644 --- a/api/v1/routes/match.ts +++ b/api/v1/routes/match.ts @@ -95,11 +95,11 @@ const name: types = async (id) => { method: 'GET', params: params, }); - if (data.error) return handleErrors(data.error) as Response; + if (data.error) return handleErrors(new Error(data.error)) as Response; if (data.match == 0 || !data.match) { - return handleErrors('Match not found') as Response; + return handleErrors(new Error('Match not found')) as Response; }; const format: response = form(data); diff --git a/api/v1/routes/user/details.ts b/api/v1/routes/user/details.ts index e876ea56..8a08ff50 100644 --- a/api/v1/routes/user/details.ts +++ b/api/v1/routes/user/details.ts @@ -121,9 +121,9 @@ const name: types = async (user, obj = {}) => { method: 'GET', params: params, }); - if (data.error) return handleErrors(data.error) as Response; + if (data.error) return handleErrors(new Error(data.error)) as Response; + if (data.length == 0) return handleErrors(new Error('User not found')) as Response; - if (data.length == 0) return handleErrors('User not found') as Response; const format = form(data); return format; diff --git a/api/v1/routes/user/scores-category.ts b/api/v1/routes/user/scores-category.ts index 5c77d145..19c0b022 100644 --- a/api/v1/routes/user/scores-category.ts +++ b/api/v1/routes/user/scores-category.ts @@ -96,7 +96,7 @@ const name: types = async (user, type, obj = {}) => { params: params, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); if (data.length == 0) return []; diff --git a/api/v2/assets_backgrounds.ts b/api/v2/assets_backgrounds.ts index 197c8796..5a256950 100644 --- a/api/v2/assets_backgrounds.ts +++ b/api/v2/assets_backgrounds.ts @@ -30,7 +30,7 @@ export const assets_backgrounds = (params: T, addons?: IDefaul if (params?.type == 'beatmapset') { if (params.set_id == null) { - return handleErrors('Specify beatmapset id') as Response; + return handleErrors(new Error('Specify beatmapset id')) as Response; }; @@ -49,5 +49,5 @@ export const assets_backgrounds = (params: T, addons?: IDefaul }; - return handleErrors(`Unsupported type: ${(params as any)?.type}`) as Response; + return handleErrors(new Error(`Unsupported type: ${(params as any)?.type}`)) as Response; }; \ No newline at end of file diff --git a/api/v2/assets_dataFiles.ts b/api/v2/assets_dataFiles.ts index 7177fff4..798f38a0 100644 --- a/api/v2/assets_dataFiles.ts +++ b/api/v2/assets_dataFiles.ts @@ -12,7 +12,7 @@ export const assets_dataFiles = async (): Promise => { method: 'GET', }); - if (data.error) return handleErrors(data.error) as Response; + if (data.error) return handleErrors(new Error(data.error)) as Response; const array = data.split('\n') diff --git a/api/v2/beatmaps_actions.ts b/api/v2/beatmaps_actions.ts index a7e24bc6..c90b0d50 100644 --- a/api/v2/beatmaps_actions.ts +++ b/api/v2/beatmaps_actions.ts @@ -21,7 +21,7 @@ type Response = // FIX const name = async (params: T, addons?: IDefaultParams): Promise> => { - return handleErrors('TEMPORARY NOT WORKING, have no clue why') as Response; + return handleErrors(new Error('TEMPORARY NOT WORKING, have no clue why')) as Response; // if (params.type == null) // return { // error: 'Type not specified', diff --git a/api/v2/beatmaps_details.ts b/api/v2/beatmaps_details.ts index 64bbca7f..88b0e169 100644 --- a/api/v2/beatmaps_details.ts +++ b/api/v2/beatmaps_details.ts @@ -24,7 +24,7 @@ type Response = export const beatmaps_details = async (params: T, addons?: IDefaultParams): Promise> => { if (params.id == null) { - return handleErrors(`Specify ${params.type} id`) as Response; + return handleErrors(new Error(`Specify ${params.type} id`)) as Response; }; @@ -43,7 +43,7 @@ export const beatmaps_details = async (params: T, addons?: IDe break; default: - return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; + return handleErrors(new Error(`Unsupported type: ${(params as any).type}`)) as Response; }; @@ -53,7 +53,7 @@ export const beatmaps_details = async (params: T, addons?: IDe addons }); - if (data.error) return handleErrors(data.error) as Response; + if (data.error) return handleErrors(new Error(data.error)) as Response; return data as Response; diff --git a/api/v2/beatmaps_discussions_list.ts b/api/v2/beatmaps_discussions_list.ts index c7c40ed3..54708e48 100644 --- a/api/v2/beatmaps_discussions_list.ts +++ b/api/v2/beatmaps_discussions_list.ts @@ -22,7 +22,7 @@ export const beatmaps_discussions_list = async (params: { addons }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; diff --git a/api/v2/beatmaps_discussions_posts.ts b/api/v2/beatmaps_discussions_posts.ts index 3ca9ba6b..3a4e24a4 100644 --- a/api/v2/beatmaps_discussions_posts.ts +++ b/api/v2/beatmaps_discussions_posts.ts @@ -33,7 +33,7 @@ export const beatmaps_discussions_posts = async (params: { addons }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; }; \ No newline at end of file diff --git a/api/v2/beatmaps_discussions_votes.ts b/api/v2/beatmaps_discussions_votes.ts index db598867..80c6cabf 100644 --- a/api/v2/beatmaps_discussions_votes.ts +++ b/api/v2/beatmaps_discussions_votes.ts @@ -29,7 +29,7 @@ export const beatmaps_discussions_votes = async (params: { addons }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; }; \ No newline at end of file diff --git a/api/v2/beatmaps_download.ts b/api/v2/beatmaps_download.ts index d03f12c2..b8a51f6b 100644 --- a/api/v2/beatmaps_download.ts +++ b/api/v2/beatmaps_download.ts @@ -188,11 +188,11 @@ export const beatmaps_download = async (params: T, addons?: ID case 'osu': if (credentials.type != 'lazer') { - return handleErrors(`Login via lazer to use this endpoint`) as Response + return handleErrors(new Error(`Login via lazer to use this endpoint`)) as Response; }; if ((addons?.authKey || cache.v2) == null) { - return handleErrors('osu is not authorized') as Response; + return handleErrors(new Error('osu is not authorized')) as Response; }; @@ -201,7 +201,7 @@ export const beatmaps_download = async (params: T, addons?: ID break; default: - return handleErrors(`Unsupported host: ${(params as any).host}`) as Response; + return handleErrors(new Error(`Unsupported host: ${(params as any).host}`)) as Response; }; @@ -212,7 +212,7 @@ export const beatmaps_download = async (params: T, addons?: ID callback: progress_track, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; @@ -243,12 +243,12 @@ export const beatmaps_download = async (params: T, addons?: ID callback: progress_track, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; }; - return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; + return handleErrors(new Error(`Unsupported type: ${(params as any).type}`)) as Response; }; \ No newline at end of file diff --git a/api/v2/beatmaps_events_list.ts b/api/v2/beatmaps_events_list.ts index 58239b14..aaf399c8 100644 --- a/api/v2/beatmaps_events_list.ts +++ b/api/v2/beatmaps_events_list.ts @@ -20,7 +20,7 @@ export const beatmaps_events_list = async (obj: { addons }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; }; \ No newline at end of file diff --git a/api/v2/beatmaps_lookup.ts b/api/v2/beatmaps_lookup.ts index d23c7c7f..1932dbcf 100644 --- a/api/v2/beatmaps_lookup.ts +++ b/api/v2/beatmaps_lookup.ts @@ -50,7 +50,7 @@ export const beatmaps_lookup = async (params: T, addons?: IDef url += '/beatmaps/lookup'; if (params.id == null && params.checksum && params.filename) { - return handleErrors(`Specify at least one parameter`) as Response; + return handleErrors(new Error(`Specify at least one parameter`)) as Response; }; object.id = params.id; @@ -63,7 +63,7 @@ export const beatmaps_lookup = async (params: T, addons?: IDef url += '/beatmapsets/lookup'; if (params.id == null) { - return handleErrors(`Specify beatmap set id`) as Response; + return handleErrors(new Error(`Specify beatmap set id`)) as Response; }; object.beatmap_id = params.id; @@ -75,7 +75,7 @@ export const beatmaps_lookup = async (params: T, addons?: IDef method = 'POST'; if (params.id == null) { - return handleErrors(`Specify beatmap id`) as Response; + return handleErrors(new Error(`Specify beatmap id`)) as Response; }; object.mods = params.mods; @@ -90,13 +90,13 @@ export const beatmaps_lookup = async (params: T, addons?: IDef if (Array.isArray(params.ids)) object['ids[]'] = params.ids; else { - return handleErrors(`Specify at least one beatmap id`) as Response; + return handleErrors(new Error(`Specify at least one beatmap id`)) as Response; }; break; default: - return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; + return handleErrors(new Error(`Unsupported type: ${(params as any).type}`)) as Response; }; @@ -106,7 +106,7 @@ export const beatmaps_lookup = async (params: T, addons?: IDef addons, }); - if (data.error) return handleErrors(data.error) as Response; + if (data.error) return handleErrors(new Error(data.error)) as Response; if (params.type == 'attributes') return data.attributes as Response; diff --git a/api/v2/beatmaps_packs_details.ts b/api/v2/beatmaps_packs_details.ts index 36f6793e..d224f643 100644 --- a/api/v2/beatmaps_packs_details.ts +++ b/api/v2/beatmaps_packs_details.ts @@ -9,7 +9,7 @@ type Response = BeatmapsPacksDetailsResponse & IError; export const beatmap_packs_details = async (pack_tag: string, addons?: IDefaultParams): Promise => { if (pack_tag == null) { - return handleErrors('Specify beatmap pack tag') as Response; + return handleErrors(new Error('Specify beatmap pack tag')) as Response; }; @@ -18,7 +18,7 @@ export const beatmap_packs_details = async (pack_tag: string, addons?: IDefaultP addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; }; \ No newline at end of file diff --git a/api/v2/beatmaps_packs_list.ts b/api/v2/beatmaps_packs_list.ts index 326f5705..755d5ca8 100644 --- a/api/v2/beatmaps_packs_list.ts +++ b/api/v2/beatmaps_packs_list.ts @@ -17,7 +17,7 @@ export const beatmaps_packs_list = async (params: { addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; }; \ No newline at end of file diff --git a/api/v2/changelogs_details.ts b/api/v2/changelogs_details.ts index 2730cd5a..b96c4e1f 100644 --- a/api/v2/changelogs_details.ts +++ b/api/v2/changelogs_details.ts @@ -12,11 +12,11 @@ export const changelogs_details = async (params: { build_version: string; }, addons?: IDefaultParams): Promise => { if (params?.stream_name == null) { - return handleErrors(`Specify stream name`) as Response; + return handleErrors(new Error(`Specify stream name`)) as Response; }; if (params?.build_version == null) { - return handleErrors(`Specify build version`) as Response; + return handleErrors(new Error(`Specify build version`)) as Response; }; @@ -25,7 +25,7 @@ export const changelogs_details = async (params: { addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; }; \ No newline at end of file diff --git a/api/v2/changelogs_list.ts b/api/v2/changelogs_list.ts index 99f47a1e..65731c1f 100644 --- a/api/v2/changelogs_list.ts +++ b/api/v2/changelogs_list.ts @@ -53,7 +53,7 @@ export const changelogs_list = async (params: T, addons?: IDef url += `/changelog/${params.changelog}`; if (params?.changelog != null == null) { - return handleErrors(`Specify changelog stream`) as Response; + return handleErrors(new Error(`Specify changelog stream`)) as Response; }; @@ -62,7 +62,7 @@ export const changelogs_list = async (params: T, addons?: IDef break; default: - return handleErrors(`Unsupported type: ${(params as any)?.type}`) as Response; + return handleErrors(new Error(`Unsupported type: ${(params as any)?.type}`)) as Response; }; @@ -72,7 +72,7 @@ export const changelogs_list = async (params: T, addons?: IDef addons }); - if (data.error) return handleErrors(data.error) as Response; + if (data.error) return handleErrors(new Error(data.error)) as Response; return data as Response; diff --git a/api/v2/chat_actions.ts b/api/v2/chat_actions.ts index f2f47abc..01ba83cf 100644 --- a/api/v2/chat_actions.ts +++ b/api/v2/chat_actions.ts @@ -42,7 +42,7 @@ export const chat_actions = async (params: T, addons?: IDefaul method = 'POST'; if (params.is_action == null || params.user_id == null || params.message == null) { - return handleErrors('Missing required parameters') as Response; + return handleErrors(new Error('Missing required parameters')) as Response; }; @@ -61,7 +61,7 @@ export const chat_actions = async (params: T, addons?: IDefaul break; default: - return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; + return handleErrors(new Error(`Unsupported type: ${(params as any).type}`)) as Response; }; @@ -71,7 +71,7 @@ export const chat_actions = async (params: T, addons?: IDefaul addons, }); - if (data.error) return handleErrors(data.error) as Response; + if (data.error) return handleErrors(new Error(data.error)) as Response; if (params?.type == 'keepalive') return data.silences as Response; diff --git a/api/v2/chat_channels_actions.ts b/api/v2/chat_channels_actions.ts index 949446a3..73dd97d0 100644 --- a/api/v2/chat_channels_actions.ts +++ b/api/v2/chat_channels_actions.ts @@ -40,11 +40,11 @@ type Response = export const chat_channels_actions = async (params: T, addons?: IDefaultParams): Promise> => { if (credentials.type != 'lazer' && credentials.type != 'cli') { - return handleErrors(`Login via lazer or cli to use this endpoint`) as Response; + return handleErrors(new Error(`Login via lazer or cli to use this endpoint`)) as Response; }; if (credentials.type == 'cli' && !credentials.scopes.includes('chat.write')) { - return handleErrors(`Requires "chat.read" scope`) as Response; + return handleErrors(new Error(`Requires "chat.read" scope`)) as Response; }; @@ -56,7 +56,7 @@ export const chat_channels_actions = async (params: T, addons? switch (params?.type) { case 'send': if (params?.channel_id == null || params?.message == null || params?.is_action == null) { - return handleErrors(`Missing required parameters`) as Response; + return handleErrors(new Error(`Missing required parameters`)) as Response; }; @@ -68,7 +68,7 @@ export const chat_channels_actions = async (params: T, addons? case 'join': if (params?.channel_id == null || params?.user_id == null) { - return handleErrors(`Missing required parameters`) as Response; + return handleErrors(new Error(`Missing required parameters`)) as Response; }; @@ -78,7 +78,7 @@ export const chat_channels_actions = async (params: T, addons? case 'leave': if (params?.channel_id == null || params?.user_id == null) { - return handleErrors(`Missing required parameters`) as Response; + return handleErrors(new Error(`Missing required parameters`)) as Response; }; @@ -88,7 +88,7 @@ export const chat_channels_actions = async (params: T, addons? case 'read': if (params?.channel_id == null || params?.message_id == null) { - return handleErrors(`Missing required parameters`) as Response; + return handleErrors(new Error(`Missing required parameters`)) as Response; }; @@ -97,7 +97,7 @@ export const chat_channels_actions = async (params: T, addons? break; default: - return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; + return handleErrors(new Error(`Unsupported type: ${(params as any).type}`)) as Response; }; @@ -107,7 +107,7 @@ export const chat_channels_actions = async (params: T, addons? addons, }); - if (data.error) return handleErrors(data.error) as Response; + if (data.error) return handleErrors(new Error(data.error)) as Response; return data as Response; diff --git a/api/v2/chat_channels_list.ts b/api/v2/chat_channels_list.ts index 98cce435..1e2fc5c8 100644 --- a/api/v2/chat_channels_list.ts +++ b/api/v2/chat_channels_list.ts @@ -11,7 +11,7 @@ export const chat_channels_list = async (addons?: IDefaultParams): Promise => { if (credentials.type != 'lazer' && credentials.type != 'cli') { - return handleErrors(`Login via lazer or cli to use this endpoint`) as Response + return handleErrors(new Error(`Login via lazer or cli to use this endpoint`)) as Response; }; if (credentials.type == 'cli' && !credentials.scopes.includes('chat.read')) { - return handleErrors(`Requires "chat.read" scope`) as Response + return handleErrors(new Error(`Requires "chat.read" scope`)) as Response; }; if (params?.channel_id == null) { - return handleErrors(`Specify channel id`) as Response; + return handleErrors(new Error(`Specify channel id`)) as Response; }; @@ -27,7 +27,7 @@ export const chat_details = async (params: { channel_id: number }, addons?: IDef addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; }; \ No newline at end of file diff --git a/api/v2/chat_list.ts b/api/v2/chat_list.ts index 0a0b54c1..12bd2444 100644 --- a/api/v2/chat_list.ts +++ b/api/v2/chat_list.ts @@ -16,7 +16,7 @@ export const chat_list = async (params: { addons }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); if (params?.sort == 'date_asc') diff --git a/api/v2/chat_messages.ts b/api/v2/chat_messages.ts index 3ca912c3..8a097b81 100644 --- a/api/v2/chat_messages.ts +++ b/api/v2/chat_messages.ts @@ -16,15 +16,15 @@ export const chat_messages = async (params: { return_object?: boolean; }, addons?: IDefaultParams): Promise => { if (credentials.type != 'lazer' && credentials.type != 'cli') { - return handleErrors(`Login via lazer or cli to use this endpoint`) as Response + return handleErrors(new Error(`Login via lazer or cli to use this endpoint`)) as Response; }; if (credentials.type == 'cli' && !credentials.scopes.includes('chat.read')) { - return handleErrors(`Requires "chat.read" scope`) as Response + return handleErrors(new Error(`Requires "chat.read" scope`)) as Response; }; if (params?.channel_id == null) { - return handleErrors(`Specify channel id`) as Response; + return handleErrors(new Error(`Specify channel id`)) as Response; }; @@ -34,7 +34,7 @@ export const chat_messages = async (params: { addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; }; \ No newline at end of file diff --git a/api/v2/chat_updates.ts b/api/v2/chat_updates.ts index 2fd8257c..7af32d53 100644 --- a/api/v2/chat_updates.ts +++ b/api/v2/chat_updates.ts @@ -14,7 +14,7 @@ export const chat_updates = async (params: { history_since: number; }, addons?: IDefaultParams): Promise => { if (credentials.type != 'lazer') { - return handleErrors(`Login via lazer to use this endpoint`) as Response + return handleErrors(new Error(`Login via lazer to use this endpoint`)) as Response }; @@ -28,7 +28,7 @@ export const chat_updates = async (params: { addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; }; \ No newline at end of file diff --git a/api/v2/comments_actions.ts b/api/v2/comments_actions.ts index fec107cd..75cfe802 100644 --- a/api/v2/comments_actions.ts +++ b/api/v2/comments_actions.ts @@ -61,15 +61,15 @@ export const comments_actions = async (params: T, addons?: IDe url += `/comments`; if (params.id == null) { - return handleErrors(`Specify news id or beatmap set id`) as Response; + return handleErrors(new Error(`Specify news id or beatmap set id`)) as Response; }; if (params.commentable_type == null) { - return handleErrors(`Specify commentable_type`) as Response; + return handleErrors(new Error(`Specify commentable_type`)) as Response; }; if (params.message == null) { - return handleErrors(`You forgot to provide message`) as Response; + return handleErrors(new Error(`You forgot to provide message`)) as Response; }; @@ -81,11 +81,11 @@ export const comments_actions = async (params: T, addons?: IDe case 'edit': if (params.id == null) { - return handleErrors(`Specify comment id`) as Response; + return handleErrors(new Error(`Specify comment id`)) as Response; }; if (params.message == null) { - return handleErrors(`You forgot to provide message`) as Response; + return handleErrors(new Error(`You forgot to provide message`)) as Response; }; @@ -97,7 +97,7 @@ export const comments_actions = async (params: T, addons?: IDe case 'delete': if (params.id == null) { - return handleErrors(`Specify comment id`) as Response; + return handleErrors(new Error(`Specify comment id`)) as Response; }; @@ -108,7 +108,7 @@ export const comments_actions = async (params: T, addons?: IDe case 'vote': if (params.id == null) { - return handleErrors(`Specify comment id`) as Response; + return handleErrors(new Error(`Specify comment id`)) as Response; }; @@ -119,7 +119,7 @@ export const comments_actions = async (params: T, addons?: IDe case 'unvote': if (params.id == null) { - return handleErrors(`Specify comment id`) as Response; + return handleErrors(new Error(`Specify comment id`)) as Response; }; @@ -129,7 +129,7 @@ export const comments_actions = async (params: T, addons?: IDe break; default: - return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; + return handleErrors(new Error(`Unsupported type: ${(params as any).type}`)) as Response; }; @@ -139,7 +139,7 @@ export const comments_actions = async (params: T, addons?: IDe addons, }); - if (data.error) return handleErrors(data.error) as Response; + if (data.error) return handleErrors(new Error(data.error)) as Response; return data as Response; diff --git a/api/v2/comments_details.ts b/api/v2/comments_details.ts index 1e488390..51d357d3 100644 --- a/api/v2/comments_details.ts +++ b/api/v2/comments_details.ts @@ -9,7 +9,7 @@ type Response = CommentsDetailsResponse & IError; export const comments_details = async (comment_id: string, addons?: IDefaultParams): Promise => { if (comment_id == null) { - return handleErrors(`Specify comment id`) as Response; + return handleErrors(new Error(`Specify comment id`)) as Response; }; @@ -18,7 +18,7 @@ export const comments_details = async (comment_id: string, addons?: IDefaultPara addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; diff --git a/api/v2/comments_list.ts b/api/v2/comments_list.ts index 06c5a880..03b913b8 100644 --- a/api/v2/comments_list.ts +++ b/api/v2/comments_list.ts @@ -34,7 +34,7 @@ export const comments_list = async (params: { addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; }; \ No newline at end of file diff --git a/api/v2/forums_topics_actions.ts b/api/v2/forums_topics_actions.ts index 1a5e5a40..ffb40c1d 100644 --- a/api/v2/forums_topics_actions.ts +++ b/api/v2/forums_topics_actions.ts @@ -61,11 +61,11 @@ type Response = export const forums_topics_actions = async (params: T, addons?: IDefaultParams): Promise> => { if (credentials.type != 'lazer' && credentials.type != 'cli') { - return handleErrors(`Login via lazer or cli to use this endpoint`) as Response; + return handleErrors(new Error(`Login via lazer or cli to use this endpoint`)) as Response; }; if (credentials.type == 'cli' && !credentials.scopes.includes('forum.write')) { - return handleErrors(`Requires "forum.write" scope`) as Response; + return handleErrors(new Error(`Requires "forum.write" scope`)) as Response; }; @@ -80,15 +80,15 @@ export const forums_topics_actions = async (params: T, addons? switch (params.type) { case 'create': if (params?.forum_id == null) { - return handleErrors(`Specify forum id`) as Response; + return handleErrors(new Error(`Specify forum id`)) as Response; }; if (params?.title == null) { - return handleErrors(`Specify title`) as Response; + return handleErrors(new Error(`Specify title`)) as Response; }; if (params?.message == null) { - return handleErrors(`Specify message`) as Response; + return handleErrors(new Error(`Specify message`)) as Response; }; @@ -122,11 +122,11 @@ export const forums_topics_actions = async (params: T, addons? case 'reply': if (params?.post_id == null) { - return handleErrors(`Specify post id`) as Response; + return handleErrors(new Error(`Specify post id`)) as Response; }; if (params?.message == null || params?.message?.trim() == '') { - return handleErrors(`Specify message`) as Response; + return handleErrors(new Error(`Specify message`)) as Response; }; @@ -140,11 +140,11 @@ export const forums_topics_actions = async (params: T, addons? case 'edit_post': if (params?.post_id == null) { - return handleErrors(`Specify post id`) as Response; + return handleErrors(new Error(`Specify post id`)) as Response; }; if (params?.message == null) { - return handleErrors(`Specify message`) as Response; + return handleErrors(new Error(`Specify message`)) as Response; }; @@ -159,11 +159,11 @@ export const forums_topics_actions = async (params: T, addons? case 'edit_topic': if (params?.topic_id && (params?.title != null && params?.title != '')) { if (params?.topic_id == null) { - return handleErrors(`Specify topic id`) as Response; + return handleErrors(new Error(`Specify topic id`)) as Response; }; if (params?.title == null || params?.title?.trim() == '') { - return handleErrors(`Specify title`) as Response; + return handleErrors(new Error(`Specify title`)) as Response; }; @@ -185,11 +185,11 @@ export const forums_topics_actions = async (params: T, addons? if (params?.post_id && (params?.message != null && params?.message != '')) { if (params?.post_id == null) { - return handleErrors(`Specify post id`) as Response; + return handleErrors(new Error(`Specify post id`)) as Response; }; if (params?.message == null) { - return handleErrors(`Specify message`) as Response; + return handleErrors(new Error(`Specify message`)) as Response; }; @@ -206,7 +206,7 @@ export const forums_topics_actions = async (params: T, addons? break; default: - return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; + return handleErrors(new Error(`Unsupported type: ${(params as any).type}`)) as Response; }; @@ -223,7 +223,7 @@ export const forums_topics_actions = async (params: T, addons? }); if (data.error) { - results.push(handleErrors(data.error) as Response); + results.push(handleErrors(new Error(data.error)) as Response); continue; }; diff --git a/api/v2/forums_topics_details.ts b/api/v2/forums_topics_details.ts index 21dba364..8f30dc59 100644 --- a/api/v2/forums_topics_details.ts +++ b/api/v2/forums_topics_details.ts @@ -19,7 +19,7 @@ export const forums_topics_details = async (params: { cursor_string?: string, }, addons?: IDefaultParams): Promise => { if (params?.id == null) { - return handleErrors(`Specify topic id`) as Response + return handleErrors(new Error('Specify topic id')) as Response }; @@ -37,7 +37,7 @@ export const forums_topics_details = async (params: { addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; diff --git a/api/v2/matches_details.ts b/api/v2/matches_details.ts index 3ac94ef7..0dd73215 100644 --- a/api/v2/matches_details.ts +++ b/api/v2/matches_details.ts @@ -9,7 +9,7 @@ type Response = MatchesDetailsResponse & IError; export const matches_details = async (params: { match_id: number }, addons?: IDefaultParams): Promise => { if (params?.match_id == null) { - return handleErrors(`Specify match id`) as Response; + return handleErrors(new Error('Specify match id')) as Response; }; @@ -18,7 +18,7 @@ export const matches_details = async (params: { match_id: number }, addons?: IDe addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; diff --git a/api/v2/matches_list.ts b/api/v2/matches_list.ts index 37b151cc..0fd0032c 100644 --- a/api/v2/matches_list.ts +++ b/api/v2/matches_list.ts @@ -25,7 +25,7 @@ export const matches_list = async (params: { addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; diff --git a/api/v2/me_details.ts b/api/v2/me_details.ts index 870bb7a7..5e272d2b 100644 --- a/api/v2/me_details.ts +++ b/api/v2/me_details.ts @@ -10,7 +10,7 @@ type Response = MeDetailsResponse & IError; export const me_details = async (params: { mode: Modes_names }, addons?: IDefaultParams): Promise => { if (credentials.type != 'lazer' && credentials.type != 'cli') { - return handleErrors(`Login via lazer or cli to use this endpoint`) as Response + return handleErrors(new Error('Login via lazer or cli to use this endpoint')) as Response }; @@ -22,7 +22,7 @@ export const me_details = async (params: { mode: Modes_names }, addons?: IDefaul addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; diff --git a/api/v2/me_download_quota.ts b/api/v2/me_download_quota.ts index 80fc5e2e..73420261 100644 --- a/api/v2/me_download_quota.ts +++ b/api/v2/me_download_quota.ts @@ -10,7 +10,7 @@ type Response = MedownloadquotaResponse & IError; export const me_download_quota = async (addons?: IDefaultParams): Promise => { if (credentials.type != 'lazer') { - return handleErrors(`Login via lazer to use this endpoint`) as Response + return handleErrors(new Error('Login via lazer to use this endpoint')) as Response }; @@ -19,7 +19,7 @@ export const me_download_quota = async (addons?: IDefaultParams): Promise => { if (credentials.type != 'lazer' && credentials.type != 'cli') { - return handleErrors(`Login via lazer or cli to use this endpoint`) as Response + return handleErrors(new Error('Login via lazer or cli to use this endpoint')) as Response }; if (credentials.type == 'cli' && !credentials.scopes.includes('friends.read')) { - return handleErrors(`Requires "friends.read" scope`) as Response + return handleErrors(new Error(`Requires "friends.read" scope`)) as Response }; @@ -23,7 +23,7 @@ export const me_friends = async (addons?: IDefaultParams): Promise => addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; }; \ No newline at end of file diff --git a/api/v2/news_details.ts b/api/v2/news_details.ts index 0e5e9ee4..5e683199 100644 --- a/api/v2/news_details.ts +++ b/api/v2/news_details.ts @@ -12,7 +12,7 @@ export const news_details = async (params: { key: 'id' | 'slug' | null; }, addons?: IDefaultParams): Promise => { if (params.news_id == null) { - return handleErrors(`Specify a query`) as Response + return handleErrors(new Error('Specify a query')) as Response }; @@ -22,7 +22,7 @@ export const news_details = async (params: { addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; }; \ No newline at end of file diff --git a/api/v2/news_list.ts b/api/v2/news_list.ts index e4449604..498e14da 100644 --- a/api/v2/news_list.ts +++ b/api/v2/news_list.ts @@ -25,7 +25,7 @@ export const news_list = async (params: { addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; diff --git a/api/v2/notification_actions.ts b/api/v2/notification_actions.ts index 4870b1cd..ca789bc2 100644 --- a/api/v2/notification_actions.ts +++ b/api/v2/notification_actions.ts @@ -41,7 +41,7 @@ export const notification_actions = async (params: T, addons?: method = 'POST'; if (!Array.isArray(params.notifications) && !Array.isArray(params.identities)) { - return handleErrors(`Missing on of parameters`) as Response; + return handleErrors(new Error(`Missing on of parameters`)) as Response; }; // params.ids.forEach((r, index) => object[`identities[${index}][id]`] = r); @@ -56,7 +56,7 @@ export const notification_actions = async (params: T, addons?: break; default: - return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; + return handleErrors(new Error(`Unsupported type: ${(params as any).type}`)) as Response; }; @@ -66,7 +66,7 @@ export const notification_actions = async (params: T, addons?: addons, }); - if (data.error) return handleErrors(data.error) as Response; + if (data.error) return handleErrors(new Error(data.error)) as Response; return data as Response; diff --git a/api/v2/notifications_list.ts b/api/v2/notifications_list.ts index 770461e9..4a3e045a 100644 --- a/api/v2/notifications_list.ts +++ b/api/v2/notifications_list.ts @@ -13,7 +13,7 @@ export const notifications_list = async (params: { unread_only: boolean; }, addons?: IDefaultParams): Promise => { if (credentials.type != 'lazer') { - return handleErrors(`Login via lazer to use this endpoint`) as Response + return handleErrors(new Error(`Login via lazer to use this endpoint`)) as Response }; @@ -24,7 +24,7 @@ export const notifications_list = async (params: { }, addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); if (params?.unread_only == true && !('error' in data)) diff --git a/api/v2/ranking_list.ts b/api/v2/ranking_list.ts index e1596aff..26a6b432 100644 --- a/api/v2/ranking_list.ts +++ b/api/v2/ranking_list.ts @@ -56,7 +56,7 @@ type Response = export const ranking_list = async (params: T, addons?: IDefaultParams): Promise> => { if (params?.type != 'kudosu' && params?.mode == null) { - return handleErrors('Gamemode not specified') as Response; + return handleErrors(new Error('Gamemode not specified')) as Response; }; @@ -105,7 +105,7 @@ export const ranking_list = async (params: T, addons?: IDefaul break; default: - return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; + return handleErrors(new Error(`Unsupported type: ${(params as any).type}`)) as Response; }; @@ -115,7 +115,7 @@ export const ranking_list = async (params: T, addons?: IDefaul addons, }); - if (data.error) return handleErrors(data.error) as Response; + if (data.error) return handleErrors(new Error(data.error)) as Response; if (params.type == 'kudosu') return data.ranking as Response; diff --git a/api/v2/rooms_details.ts b/api/v2/rooms_details.ts index f70143fa..28e6623d 100644 --- a/api/v2/rooms_details.ts +++ b/api/v2/rooms_details.ts @@ -10,11 +10,11 @@ type Response = RoomsDetailsResponse & IError; export const rooms_details = async (params: { id: number | 'latest' }, addons?: IDefaultParams): Promise => { if (credentials.type != 'lazer' && credentials.type != 'cli') { - return handleErrors(`Login via lazer or cli to use this endpoint`) as Response + return handleErrors(new Error(`Login via lazer or cli to use this endpoint`)) as Response; }; if (params.id == null) { - return handleErrors(`Specify room id`) as Response; + return handleErrors(new Error(`Specify room id`)) as Response; }; @@ -23,7 +23,7 @@ export const rooms_details = async (params: { id: number | 'latest' }, addons?: addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; diff --git a/api/v2/rooms_leaderboard.ts b/api/v2/rooms_leaderboard.ts index 9425ba8c..a9bb4d06 100644 --- a/api/v2/rooms_leaderboard.ts +++ b/api/v2/rooms_leaderboard.ts @@ -13,11 +13,11 @@ export const rooms_leaderboard = async (params: { limit?: number; }, addons?: IDefaultParams): Promise => { if (credentials.type != 'lazer' && credentials.type != 'cli') { - return handleErrors(`Login via lazer or cli to use this endpoint`) as Response + return handleErrors(new Error(`Login via lazer or cli to use this endpoint`)) as Response; }; if (params?.id == null) { - return handleErrors(`Specify room id`) as Response; + return handleErrors(new Error(`Specify room id`)) as Response; }; @@ -27,7 +27,7 @@ export const rooms_leaderboard = async (params: { addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; diff --git a/api/v2/rooms_list.ts b/api/v2/rooms_list.ts index 2fd8afb5..cb0424b9 100644 --- a/api/v2/rooms_list.ts +++ b/api/v2/rooms_list.ts @@ -20,7 +20,7 @@ export const rooms_list = async (params: { cursor_string?: string; }, addons?: IDefaultParams): Promise => { if (credentials.type != 'lazer' && credentials.type != 'cli') { - return handleErrors(`Login via lazer or cli to use this endpoint`) as Response + return handleErrors(new Error(`Login via lazer or cli to use this endpoint`)) as Response }; if (addons == null) @@ -39,7 +39,7 @@ export const rooms_list = async (params: { addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); if (params?.query && !('error' in data)) { if (data.rooms) data.rooms = data.rooms.filter((r: any) => r.name.toLowerCase().includes(params?.query.trim().toLowerCase())) diff --git a/api/v2/rooms_scores.ts b/api/v2/rooms_scores.ts index 780a40db..319f83ec 100644 --- a/api/v2/rooms_scores.ts +++ b/api/v2/rooms_scores.ts @@ -44,7 +44,7 @@ type Response = export const rooms_scores = async (params: T, addons?: IDefaultParams): Promise> => { if (credentials.type != 'lazer' && credentials.type != 'cli') { - return handleErrors(`Login via lazer or cli to use this endpoint`) as Response; + return handleErrors(new Error(`Login via lazer or cli to use this endpoint`)) as Response; }; @@ -54,11 +54,11 @@ export const rooms_scores = async (params: T, addons?: IDefaul if (params?.id == null) { - return handleErrors(`Specify room id`) as Response; + return handleErrors(new Error(`Specify room id`)) as Response; }; if (params?.playlist_id == null) { - return handleErrors(`Specify playlist id`) as Response; + return handleErrors(new Error(`Specify playlist id`)) as Response; }; @@ -82,7 +82,7 @@ export const rooms_scores = async (params: T, addons?: IDefaul break; default: - return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; + return handleErrors(new Error(`Unsupported type: ${(params as any).type}`)) as Response; }; @@ -92,7 +92,7 @@ export const rooms_scores = async (params: T, addons?: IDefaul addons, }); - if (data.error) return handleErrors(data.error) as Response; + if (data.error) return handleErrors(new Error(data.error)) as Response; return data as Response; diff --git a/api/v2/scores_details.ts b/api/v2/scores_details.ts index 94c93494..99d5bc4a 100644 --- a/api/v2/scores_details.ts +++ b/api/v2/scores_details.ts @@ -12,7 +12,7 @@ export const scores_details = async (params: { mode?: Modes_names; }, addons?: IDefaultParams): Promise => { if (params?.id == null) { - return handleErrors(`Specify score id`) as Response; + return handleErrors(new Error('Specify score id')) as Response; }; @@ -23,7 +23,7 @@ export const scores_details = async (params: { addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; diff --git a/api/v2/scores_download.ts b/api/v2/scores_download.ts index c852f08e..3b21a9dd 100644 --- a/api/v2/scores_download.ts +++ b/api/v2/scores_download.ts @@ -14,11 +14,11 @@ export const scores_download = async (params: { file_path?: string; }): Promise => { if (credentials.type != 'lazer' && credentials.type != 'cli') { - return handleErrors(`Login via lazer or cli to use this endpoint`) as Response + return handleErrors(new Error(`Login via lazer or cli to use this endpoint`)) as Response; }; if (params?.id == null) { - return handleErrors(`Specify score id`) as Response; + return handleErrors(new Error(`Specify score id`)) as Response; }; @@ -28,7 +28,7 @@ export const scores_download = async (params: { _callback: false, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; diff --git a/api/v2/scores_list.ts b/api/v2/scores_list.ts index fb8258b2..c024813b 100644 --- a/api/v2/scores_list.ts +++ b/api/v2/scores_list.ts @@ -71,7 +71,7 @@ export const scores_list = async (params: T, addons?: IDefault switch (params?.type) { case 'leaderboard': if (params.beatmap_id == null) { - return handleErrors(`Specify beatmap id`) as Response; + return handleErrors(new Error(`Specify beatmap id`)) as Response; }; @@ -85,11 +85,11 @@ export const scores_list = async (params: T, addons?: IDefault case 'user_beatmap_best': if (params.beatmap_id == null) { - return handleErrors(`Specify beatmap id`) as Response; + return handleErrors(new Error(`Specify beatmap id`)) as Response; }; if (params.user_id == null) { - return handleErrors(`Specify user id`) as Response; + return handleErrors(new Error(`Specify user id`)) as Response; }; @@ -102,11 +102,11 @@ export const scores_list = async (params: T, addons?: IDefault case 'user_beatmap_all': if (params.beatmap_id == null) { - return handleErrors(`Specify beatmap id`) as Response; + return handleErrors(new Error(`Specify beatmap id`)) as Response; }; if (params.user_id == null) { - return handleErrors(`Specify user id`) as Response; + return handleErrors(new Error(`Specify user id`)) as Response; }; @@ -121,7 +121,7 @@ export const scores_list = async (params: T, addons?: IDefault case 'user_recent': case 'user_pinned': if (params.user_id == null) { - return handleErrors(`Specify user id`) as Response; + return handleErrors(new Error(`Specify user id`)) as Response; }; @@ -136,7 +136,7 @@ export const scores_list = async (params: T, addons?: IDefault case 'solo_scores': if (params.beatmap_id == null) { - return handleErrors(`Specify beatmap id`) as Response; + return handleErrors(new Error(`Specify beatmap id`)) as Response; }; @@ -149,7 +149,7 @@ export const scores_list = async (params: T, addons?: IDefault break; default: - return handleErrors(`Unsupported type: ${(params as any).type}`) as Response; + return handleErrors(new Error(`Unsupported type: ${(params as any).type}`)) as Response; }; @@ -159,7 +159,7 @@ export const scores_list = async (params: T, addons?: IDefault addons, }); - if (data.error) return handleErrors(data.error) as Response; + if (data.error) return handleErrors(new Error(data.error)) as Response; if (['leaderboard', 'user_beatmap_all'].includes(params.type)) { diff --git a/api/v2/search.ts b/api/v2/search.ts index d605d5a5..6aba4b5a 100644 --- a/api/v2/search.ts +++ b/api/v2/search.ts @@ -84,7 +84,7 @@ export const search_all = async (params: T, addons?: IDefaultP addons }); - if (data.error) return handleErrors(data.error) as Response; + if (data.error) return handleErrors(new Error(data.error)) as Response; return data as Response; diff --git a/api/v2/session_actions.ts b/api/v2/session_actions.ts index bb7eecc9..b98b40ef 100644 --- a/api/v2/session_actions.ts +++ b/api/v2/session_actions.ts @@ -36,11 +36,11 @@ export const session_actions = async (params: T, addons?: IDef switch (params?.type) { case 'verify': if (credentials.type != 'lazer') { - return handleErrors(`Login via lazer to use this endpoint`); + return handleErrors(new Error(`Login via lazer to use this endpoint`)) as Response; }; if (params?.code == null) { - return handleErrors(`Specify verification code`) as Response; + return handleErrors(new Error(`Specify verification code`)) as Response; }; url += `/session/verify`; @@ -58,7 +58,7 @@ export const session_actions = async (params: T, addons?: IDef case 'reissue': if (credentials.type != 'lazer') { - return handleErrors(`Login via lazer to use this endpoint`); + return handleErrors(new Error(`Login via lazer to use this endpoint`)) as Response; }; url += `/session/verify/reissue`; @@ -80,7 +80,7 @@ export const session_actions = async (params: T, addons?: IDef addons, }); - if (data.error) return handleErrors(data.error) as Response; + if (data.error) return handleErrors(new Error(data.error)) as Response; return data as Response; diff --git a/api/v2/spotlights_list.ts b/api/v2/spotlights_list.ts index 06185ec0..58cb30c6 100644 --- a/api/v2/spotlights_list.ts +++ b/api/v2/spotlights_list.ts @@ -13,7 +13,7 @@ export const spotlights_list = async (addons?: IDefaultParams): Promise => { if (params?.id == null) { - return handleErrors(`Specify user id`) as Response; + return handleErrors(new Error(`Specify user id`)) as Response; }; @@ -26,7 +26,7 @@ export const users_activity = async (params: { addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; diff --git a/api/v2/users_beatmaps.ts b/api/v2/users_beatmaps.ts index 44f34b72..ee025b03 100644 --- a/api/v2/users_beatmaps.ts +++ b/api/v2/users_beatmaps.ts @@ -15,11 +15,11 @@ export const users_beatmaps = async (params: { offset?: number; }, addons?: IDefaultParams): Promise => { if (params?.id == null) { - return handleErrors(`Specify user id`) as Response; + return handleErrors(new Error(`Specify user id`)) as Response; }; if (params?.type == null) { - return handleErrors(`Specify beatmaps type`) as Response; + return handleErrors(new Error(`Specify beatmaps type`)) as Response; }; @@ -32,7 +32,7 @@ export const users_beatmaps = async (params: { addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; diff --git a/api/v2/users_details.ts b/api/v2/users_details.ts index 333b150e..7cb17ce7 100644 --- a/api/v2/users_details.ts +++ b/api/v2/users_details.ts @@ -13,7 +13,7 @@ export const users_details = async (params: { key?: 'id' | 'username' | '@'; }, addons?: IDefaultParams): Promise => { if (params?.user == null) { - return handleErrors(`Specify user id or name`) as Response; + return handleErrors(new Error('Specify user id or name')) as Response; }; let key = params?.key; @@ -26,7 +26,7 @@ export const users_details = async (params: { addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; }; \ No newline at end of file diff --git a/api/v2/users_events.ts b/api/v2/users_events.ts index 20852c88..2cac9679 100644 --- a/api/v2/users_events.ts +++ b/api/v2/users_events.ts @@ -18,11 +18,11 @@ export const users_events = async ({ sort, cursor_string, type }: { addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); if (type != null && !Array.isArray(type)) { - return handleErrors(`Events Type must be an Array of types. Example: ['achievement', 'rank']`) as Response; + return handleErrors(new Error(`Events Type must be an Array of types. Example: ['achievement', 'rank']`)) as Response; }; diff --git a/api/v2/users_kudosu.ts b/api/v2/users_kudosu.ts index 39e3ffb2..5eb6e2b2 100644 --- a/api/v2/users_kudosu.ts +++ b/api/v2/users_kudosu.ts @@ -13,7 +13,7 @@ export const users_kudosu = async (params: { offset?: number; }, addons?: IDefaultParams): Promise => { if (params?.id == null) { - return handleErrors(`Specify user id`) as Response; + return handleErrors(new Error('Specify user id')) as Response; }; @@ -26,7 +26,7 @@ export const users_kudosu = async (params: { addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; diff --git a/api/v2/users_list.ts b/api/v2/users_list.ts index 8c4ba5f8..076e1ad1 100644 --- a/api/v2/users_list.ts +++ b/api/v2/users_list.ts @@ -9,11 +9,11 @@ type Response = UsersLisResponse[] & IError; export const users_list = async (params: { ids: number[], include_variants?: boolean }, addons?: IDefaultParams): Promise => { if ((params?.ids || [])?.length == 0) { - return handleErrors(`Specify at least one user id`) as Response; + return handleErrors(new Error(`Specify at least one user id`)) as Response; }; if (params.ids.length > 50) { - return handleErrors("No more than 50 users can be requested at once.") as Response; + return handleErrors(new Error("No more than 50 users can be requested at once.")) as Response; } const data = await request(`https://osu.ppy.sh/api/v2/users`, { @@ -25,7 +25,7 @@ export const users_list = async (params: { ids: number[], include_variants?: boo addons }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); if (data.users) return data.users; diff --git a/api/v2/wiki_details.ts b/api/v2/wiki_details.ts index ac5a7fd7..34e301be 100644 --- a/api/v2/wiki_details.ts +++ b/api/v2/wiki_details.ts @@ -12,11 +12,11 @@ export const wiki_details = async (params: { path_name: string; }, addons?: IDefaultParams): Promise => { if (params?.locale == null) { - return handleErrors(`Specify locale code. Example: en`) as Response; + return handleErrors(new Error(`Specify locale code. Example: en`)) as Response; }; if (params?.path_name == null) { - return handleErrors(`Specify wiki page path`) as Response; + return handleErrors(new Error(`Specify wiki page path`)) as Response; }; @@ -25,7 +25,7 @@ export const wiki_details = async (params: { addons, }); - if (data.error) return handleErrors(data.error); + if (data.error) return handleErrors(new Error(data.error)); return data; diff --git a/tools/accuracy.ts b/tools/accuracy.ts index e7865b5b..47666bae 100644 --- a/tools/accuracy.ts +++ b/tools/accuracy.ts @@ -72,7 +72,7 @@ type Response = AccuracyResponse & IError; */ export const calculate_accuracy = (hits: Hits, mode: GamemodeEnum | string | number): Response => { if (Object.keys(hits).length == 0) { - return handleErrors('Provide hits (300, 100, 50, etc)') as Response; + return handleErrors(new Error('Provide hits (300, 100, 50, etc)')) as Response; }; @@ -118,7 +118,7 @@ export const calculate_accuracy = (hits: Hits, mode: GamemodeEnum | string | num break; default: - return handleErrors(`Unsupported gamemode: ${mode}}`) as Response; + return handleErrors(new Error(`Unsupported gamemode: ${mode}}`)) as Response; }; diff --git a/tools/country.ts b/tools/country.ts index 6c0944bd..c99212ef 100644 --- a/tools/country.ts +++ b/tools/country.ts @@ -42,14 +42,14 @@ type Response = CountryResponse & IError; */ export const country_details = (name: string): Response => { if (name == null || name == '') { - return handleErrors('Specify country code or country name') as Response; + return handleErrors(new Error('Specify country code or country name')) as Response; }; if (name.length == 2) { const find = (CountryNames as any)[name.toUpperCase()]; if (find == null) { - return handleErrors('Country not found') as Response; + return handleErrors(new Error('Country not found')) as Response; }; @@ -62,7 +62,7 @@ export const country_details = (name: string): Response => { const find = (CountryCodes as any)[name]; if (find == null) { - return handleErrors('Country not found') as Response; + return handleErrors(new Error('Country not found')) as Response; }; diff --git a/tools/index.ts b/tools/index.ts index 89360ed3..526ecb3f 100644 --- a/tools/index.ts +++ b/tools/index.ts @@ -11,7 +11,7 @@ export { calculate_net_pp } from "./net-pp"; export const calculate_pp = () => { - return handleErrors('Use rosu-pp-js instead'); + return handleErrors(new Error('Use rosu-pp-js instead')); }; /** diff --git a/tools/mods.ts b/tools/mods.ts index 5d722617..db13b9f2 100644 --- a/tools/mods.ts +++ b/tools/mods.ts @@ -93,7 +93,7 @@ type Response = ModsResponse & IError; */ export const calculate_mods = (mods: Mod[] | string | number, order?: boolean): Response => { if (mods == null) { - return handleErrors(`Specify mods name (HDDT or 72)`) as Response; + return handleErrors(new Error(`Specify mods name (HDDT or 72)`)) as Response; }; if (mods == '') { @@ -125,7 +125,7 @@ export const calculate_mods = (mods: Mod[] | string | number, order?: boolean): if (!Array.isArray(ModsArray)) { - return handleErrors(`Can't convert mods (${mods}) to array of mods`) as Response; + return handleErrors(new Error(`Can't convert mods (${mods}) to array of mods`)) as Response; }; diff --git a/tools/net-pp.ts b/tools/net-pp.ts index 2e706cf9..f647b028 100644 --- a/tools/net-pp.ts +++ b/tools/net-pp.ts @@ -50,11 +50,11 @@ type Response = { */ export const calculate_net_pp = (scores: ScoresListUserBestResponse[] | number[], pp: number): Response => { if (!Array.isArray(scores)) { - return handleErrors(`Provide array of scores or plays pp`) as Response; + return handleErrors(new Error(`Provide array of scores or plays pp`)) as Response; }; if (!isFinite(pp) || pp == null) { - return handleErrors(`Specify play pp`) as Response; + return handleErrors(new Error(`Specify play pp`)) as Response; }; diff --git a/tools/objects.ts b/tools/objects.ts index fe332392..76aeef04 100644 --- a/tools/objects.ts +++ b/tools/objects.ts @@ -72,7 +72,7 @@ type Response = TotalObjectsResponse & IError; */ export const calculate_total_passed_objects = (hits: Hits, mode: GamemodeEnum | string | number): Response => { if (Object.keys(hits).length == 0) { - return handleErrors('Provide hits (300, 100, 50, etc)') as Response; + return handleErrors(new Error('Provide hits (300, 100, 50, etc)')) as Response; }; @@ -108,7 +108,7 @@ export const calculate_total_passed_objects = (hits: Hits, mode: GamemodeEnum | break; default: - return handleErrors(`Unsupported gamemode: ${mode}}`) as Response; + return handleErrors(new Error(`Unsupported gamemode: ${mode}}`)) as Response; }; @@ -173,7 +173,7 @@ type ResponseConvert = ConvertHitsResponse & IError; */ export const calculate_hits = (hits: Hits, mode: GamemodeEnum | string | number): ResponseConvert => { if (Object.keys(hits).length == 0) { - return handleErrors('Provide hits (300, 100, 50, etc)') as ResponseConvert; + return handleErrors(new Error('Provide hits (300, 100, 50, etc)')) as ResponseConvert; }; @@ -218,7 +218,7 @@ export const calculate_hits = (hits: Hits, mode: GamemodeEnum | string | number) break; default: - return handleErrors(`Unsupported gamemode: ${mode}}`) as ResponseConvert; + return handleErrors(new Error(`Unsupported gamemode: ${mode}}`)) as ResponseConvert; }; diff --git a/tools/rank.ts b/tools/rank.ts index 7d55ed53..2a5a0fec 100644 --- a/tools/rank.ts +++ b/tools/rank.ts @@ -69,7 +69,7 @@ type Response = RankResponse & IError; */ export const calculate_rank = (hits: Hits, mods: Mod[] | string | number = 0, mode: GamemodeEnum | string | number): Response => { if (Object.keys(hits).length == 0) { - return handleErrors('Provide hits (300, 100, 50, etc)') as Response; + return handleErrors(new Error('Provide hits (300, 100, 50, etc)')) as Response; }; diff --git a/utility/auth.ts b/utility/auth.ts index 4f302028..3bf45bff 100644 --- a/utility/auth.ts +++ b/utility/auth.ts @@ -75,7 +75,7 @@ type ResponseLogin = export const login = (params: auth_params): ResponseLogin => { if (params?.type == null) { - return handleErrors('Specify login type'); + return handleErrors(new Error('Specify login type')); }; credentials.type = params.type; @@ -183,7 +183,7 @@ const client_login = async (client_id: number | string, client_secret: string, s }) }); - if (response.error) return handleErrors(response.error); + if (response.error) return handleErrors(new Error(response.error)); cache.v2 = response.access_token; @@ -217,7 +217,7 @@ const lazer_login = async (login: string, password: string): Promise => { if (params?.client_id == null) { - return handleErrors(`Specify client_id`); + return handleErrors(new Error(`Specify client_id`)); }; if (params?.client_secret == null) { - return handleErrors(`Specify client_secret`); + return handleErrors(new Error(`Specify client_secret`)); }; if (params?.redirect_url == null) { - return handleErrors(`Specify redirect_url`); + return handleErrors(new Error(`Specify redirect_url`)); }; if (params?.code == null) { - return handleErrors(`Specify code`); + return handleErrors(new Error(`Specify code`)); }; @@ -333,7 +333,7 @@ export const authorize = async (params: { }) }); - if (response.error) return handleErrors(response.error); + if (response.error) return handleErrors(new Error(response.error)); let url = 'https://osu.ppy.sh/api/v2/me'; @@ -344,7 +344,7 @@ export const authorize = async (params: { addons: { authKey: response.access_token, ignoreSessionRefresh: true } }); - if (user.error) return handleErrors(user.error); + if (user.error) return handleErrors(new Error(user.error)); user.access_token = response.access_token; @@ -365,19 +365,19 @@ export const refresh_session = async (params: { redirect_url: string; }): Promise => { if (params?.client_id == null) { - return handleErrors(`Specify client_id`); + return handleErrors(new Error(`Specify client_id`)); }; if (params?.client_secret == null) { - return handleErrors(`Specify client_secret`); + return handleErrors(new Error(`Specify client_secret`)); }; if (params?.redirect_url == null) { - return handleErrors(`Specify redirect_url`); + return handleErrors(new Error(`Specify redirect_url`)); }; if (params?.refresh_token == null) { - return handleErrors(`Specify refresh_token`); + return handleErrors(new Error(`Specify refresh_token`)); }; @@ -396,7 +396,7 @@ export const refresh_session = async (params: { }) }); - if (response.error) return handleErrors(response.error); + if (response.error) return handleErrors(new Error(response.error)); let url = 'https://osu.ppy.sh/api/v2/me'; @@ -407,7 +407,7 @@ export const refresh_session = async (params: { addons: { authKey: response.access_token, ignoreSessionRefresh: true } }); - if (user.error) return handleErrors(user.error); + if (user.error) return handleErrors(new Error(user.error)); user.access_token = response.access_token; diff --git a/utility/handleErrors.ts b/utility/handleErrors.ts index 009ee366..c6c61ace 100644 --- a/utility/handleErrors.ts +++ b/utility/handleErrors.ts @@ -1,8 +1,7 @@ import { settings } from '../utility/auth'; -export const handleErrors = (message: string | Error): any => { - const error = message instanceof Error ? message : new Error(message); +export const handleErrors = (error: Error): any => { if (settings.throwErrors) { throw error; }; From d7158bbb92884f919da6591fa23174a1f15eb2fc Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 5 Oct 2024 02:54:56 +0300 Subject: [PATCH 238/259] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3d475487..1b3222c9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.36", + "version": "3.0.0-beta.37", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", From 2aec144dd5fa804408bc7912eaff96eeea65cff1 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 5 Oct 2024 04:15:09 +0300 Subject: [PATCH 239/259] add `groups.details` --- api/v2/groups_details.ts | 35 ++++++++++++++ routes/v2.ts | 53 ++++++++++++++++++++- types/v2/groups_details.ts | 96 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 api/v2/groups_details.ts create mode 100644 types/v2/groups_details.ts diff --git a/api/v2/groups_details.ts b/api/v2/groups_details.ts new file mode 100644 index 00000000..c238e2e3 --- /dev/null +++ b/api/v2/groups_details.ts @@ -0,0 +1,35 @@ +import { request } from "../../utility/request"; +import { IDefaultParams, IError } from "../../types"; +import { handleErrors } from "../../utility/handleErrors"; +import { GroupsDetailsResponse } from "../../types/v2/groups_details"; + + +type Response = GroupsDetailsResponse & IError; + + +export const groups_details = async (params: { + id: '4' | '7' | '11' | '16' | '22' | '28' | '31' | '32' +}, addons?: IDefaultParams): Promise => { + if (params?.id == null) { + return handleErrors(new Error(`Specify group id`)) as Response; + }; + + const data = await request(`https://osu.ppy.sh/groups/${params.id}`, { + method: 'GET', + addons + }); + + if (data.error) return handleErrors(new Error(data.error)); + + + try { + const parse_group = JSON.parse(data.split('')[0]); + const parse_users = JSON.parse(data.split('')[0]); + + + parse_group.users = parse_users; + return parse_group; + } catch (error) { + return handleErrors(error as any); + }; +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index b142f385..7c1d2823 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -2856,4 +2856,55 @@ export const rooms = { * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2roomsroomleaderboard) | [Check return types](../types/v2/rooms_leaderboard.ts) */ leaderboard: rooms_leaderboard, -}; \ No newline at end of file +}; + + + +import { groups_details } from "../api/v2/groups_details"; + +/** + * ##### Description + * Retrieve data from the groups API. + */ +export const groups = { + /** + * ### `GET` /groups/{id} + * `async` Retrieves a list of users by given group id. + * + *   + * + * ### Parameters + * - `params.id` - Group id. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * const { v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * const result = await v2.groups.details({ + * id: '32' + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); + * ``` + * + *   + * + * [Check return types](../types/v2/groups_details.ts) + */ + details: groups_details, +} \ No newline at end of file diff --git a/types/v2/groups_details.ts b/types/v2/groups_details.ts new file mode 100644 index 00000000..36d63840 --- /dev/null +++ b/types/v2/groups_details.ts @@ -0,0 +1,96 @@ +export interface GroupsDetailsResponse { + colour: string + has_listing: boolean + has_playmodes: boolean + id: number + identifier: string + is_probationary: boolean + name: string + short_name: string + description: Description + users: User[] +} + +export interface Description { + html: string + markdown: string +} + +export interface User { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit?: string + pm_friends_only: boolean + profile_colour: string + username: string + country: Country + cover: Cover + groups: Group[] + statistics: Statistics + support_level: number +} + +export interface Country { + code: string + name: string +} + +export interface Cover { + custom_url: string + url: string + id: any +} + +export interface Group { + colour: string + has_listing: boolean + has_playmodes: boolean + id: number + identifier: string + is_probationary: boolean + name: string + short_name: string + playmodes: string[] +} + +export interface Statistics { + count_100: number + count_300: number + count_50: number + count_miss: number + level: Level + global_rank?: number + global_rank_exp: any + pp: number + pp_exp: number + ranked_score: number + hit_accuracy: number + play_count: number + play_time: number + total_score: number + total_hits: number + maximum_combo: number + replays_watched_by_others: number + is_ranked: boolean + grade_counts: GradeCounts +} + +export interface Level { + current: number + progress: number +} + +export interface GradeCounts { + ss: number + ssh: number + s: number + sh: number + a: number +} From 55f18a5e2611343a7b97d26331056d4351f44535 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 5 Oct 2024 04:15:24 +0300 Subject: [PATCH 240/259] add `groups.history` --- api/v2/groups_history.ts | 26 +++++++++++++++++++++++ routes/v2.ts | 43 ++++++++++++++++++++++++++++++++++++++ types/v2/groups_history.ts | 21 +++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 api/v2/groups_history.ts create mode 100644 types/v2/groups_history.ts diff --git a/api/v2/groups_history.ts b/api/v2/groups_history.ts new file mode 100644 index 00000000..8dfacdf0 --- /dev/null +++ b/api/v2/groups_history.ts @@ -0,0 +1,26 @@ +import { request } from "../../utility/request"; +import { IDefaultParams, IError } from "../../types"; +import { handleErrors } from "../../utility/handleErrors"; +import { GroupsHistoryResponse } from "../../types/v2/groups_history"; + + +type Response = GroupsHistoryResponse & IError; + + +export const groups_history = async (params: { + user?: string | number; + group?: 'gmt' | 'nat' | 'dev' | 'alumni' | 'support' | 'bng' | 'loved' | 'bng_limited'; + sort?: 'id_desc' | 'id_asc'; + max_date?: string; + min_date?: string; +}, addons?: IDefaultParams): Promise => { + const data = await request(`https://osu.ppy.sh/groups/history`, { + method: 'GET', + params, + addons + }); + + + if (data.error) return handleErrors(new Error(data.error)); + return data; +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 7c1d2823..fa3e9a8e 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -2861,6 +2861,7 @@ export const rooms = { import { groups_details } from "../api/v2/groups_details"; +import { groups_history } from "../api/v2/groups_history"; /** * ##### Description @@ -2907,4 +2908,46 @@ export const groups = { * [Check return types](../types/v2/groups_details.ts) */ details: groups_details, + /** + * ### `GET` /groups/history + * `async` Retrieves a groups history + * + *   + * + * ### Parameters + * - `params.user?` - User id or name + * - `params.group?` - Group indentifier + * - `params.sort?` - id_asc or id_desc + * - `params.max_date?` - Max date in ISOString format + * - `params.min_date?` - Min date in ISOString format + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * const { v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * const result = await v2.groups.history(); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); + * ``` + * + *   + * + * [Check return types](../types/v2/groups_details.ts) + */ + history: groups_history, } \ No newline at end of file diff --git a/types/v2/groups_history.ts b/types/v2/groups_history.ts new file mode 100644 index 00000000..4361c2db --- /dev/null +++ b/types/v2/groups_history.ts @@ -0,0 +1,21 @@ +export interface GroupsHistoryResponse { + events: Event[] + cursor: Cursor + cursor_string: string +} + +export interface Event { + created_at: string + group_id: number + hidden: boolean + id: number + type: string + user_id: number + user_name: string + group_name: string + playmodes?: string[] +} + +export interface Cursor { + id: number +} From 247cb7d248604abef3dcbe37229b937eca9cde15 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 5 Oct 2024 04:31:51 +0300 Subject: [PATCH 241/259] add jsdoc to `beatmaps.lookup` --- routes/v2.ts | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/routes/v2.ts b/routes/v2.ts index fa3e9a8e..b80a44a8 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -146,7 +146,48 @@ export const beatmaps = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * }); + * + * const result = await v2.beatmaps.lookup({ + * type: 'attributes', + * id: 3798013, + * }); + * // or + * const result = await v2.beatmaps.lookup({ + * type: 'difficulties', + * ids: [4233769, 3798013] + * }); + * // or + * const result = await v2.beatmaps.lookup({ + * type: 'difficulty', + * id: 4233769, + * }); + * // or + * const result = await v2.beatmaps.lookup({ + * type: 'set', + * id: 2246377, + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   From d49757c7fe18a455ca5ee19ecd51a8090d793c3c Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 5 Oct 2024 07:02:22 +0300 Subject: [PATCH 242/259] fix types --- api/v2/beatmaps_lookup.ts | 12 ++++++------ api/v2/chat_updates.ts | 6 +++--- api/v2/comments_actions.ts | 16 ++++++++-------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/api/v2/beatmaps_lookup.ts b/api/v2/beatmaps_lookup.ts index 1932dbcf..8ce843a5 100644 --- a/api/v2/beatmaps_lookup.ts +++ b/api/v2/beatmaps_lookup.ts @@ -10,17 +10,17 @@ import { handleErrors } from "../../utility/handleErrors"; type params = ({ type: 'difficulty'; - id: number; - checksum: string; - filename: string; + id?: number; + checksum?: string; + filename?: string; } | { type: 'set'; id: number; } | { type: 'attributes'; id: number; - mods: number; - mode: Modes_names + mods?: number; + mode?: Modes_names } | { type: 'difficulties'; ids: number[]; @@ -49,7 +49,7 @@ export const beatmaps_lookup = async (params: T, addons?: IDef case 'difficulty': url += '/beatmaps/lookup'; - if (params.id == null && params.checksum && params.filename) { + if (params.id == null && params.checksum == null && params.filename == null) { return handleErrors(new Error(`Specify at least one parameter`)) as Response; }; diff --git a/api/v2/chat_updates.ts b/api/v2/chat_updates.ts index 7af32d53..7d033720 100644 --- a/api/v2/chat_updates.ts +++ b/api/v2/chat_updates.ts @@ -9,9 +9,9 @@ type Response = ChatUpdatesResponse & IError; export const chat_updates = async (params: { - after_id: number; - includes: ('presence' | 'silences' | 'messages')[]; - history_since: number; + after_id?: number; + includes?: ('presence' | 'silences' | 'messages')[]; + history_since?: number; }, addons?: IDefaultParams): Promise => { if (credentials.type != 'lazer') { return handleErrors(new Error(`Login via lazer to use this endpoint`)) as Response diff --git a/api/v2/comments_actions.ts b/api/v2/comments_actions.ts index 75cfe802..e8c7b30c 100644 --- a/api/v2/comments_actions.ts +++ b/api/v2/comments_actions.ts @@ -11,28 +11,28 @@ import { handleErrors } from "../../utility/handleErrors"; type params = ({ type: 'new'; - commentable_type?: 'news_post' | 'beatmapset'; - id?: number; + commentable_type: 'news_post' | 'beatmapset'; + id: number; parent_id?: string; - message?: string; + message: string; } | { type: 'edit'; - id?: number; - message?: string; + id: number; + message: string; } | { type: 'delete'; - id?: number; + id: number; } | { type: 'vote'; - id?: number; + id: number; } | { type: 'unvote'; - id?: number; + id: number; }); From 839f61dd1cf60035492d9f272506929d749eb010 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 5 Oct 2024 07:02:28 +0300 Subject: [PATCH 243/259] migration list --- migration.md | 329 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 329 insertions(+) create mode 100644 migration.md diff --git a/migration.md b/migration.md new file mode 100644 index 00000000..19425737 --- /dev/null +++ b/migration.md @@ -0,0 +1,329 @@ +Migration from `v2` to `v3` + +```diff +-v2.user.activity(user, { limit, offset }); ++v2.users.activity({ id; limit?; offset?; }); +``` + +```diff +-v2.user.details(user, mode?, key?); ++v2.users.details({ user?; mode?; key? }); +``` + +```diff +-v2.user.beatmaps.kudosu(user, { limit?; offset?; }); ++v2.users.kudosu({ id; limit?; offset?; }); +``` + +```diff +-v2.user.beatmaps.category(user, type, { limit?; offset?; }); ++v2.users.beatmaps({ type; id; limit?; offset?; }); +``` + +```diff +-v2.user.beatmaps.most_played(user, { limit?; offset?; }); ++v2.users.beatmaps({ type: 'most_played'; id; limit?; offset?; }); +``` + +```diff +-v2.user.me.details(mode?); ++v2.me.details({ mode? }); +``` + +```diff +-v2.user.me.friends(); ++v2.me.friends(); +``` + +```diff +-v2.user.me.download.quota(); ++v2.me.download_quota(); +``` + +```diff +-v2.users.details(ids); ++v2.users.list({ ids; include_variants?; }); +``` + +```diff +-v2.users.events({ sort?; cursor_string?; type?; }); ++v2.users.events({ sort?; cursor_string?; type?; }); +``` + +```diff +-v2.users.groups.list(id) ++v2.groups.details({ id }); +``` + +```diff +-v2.scores.details(score_id, mode); ++v2.scores.details({ id; mode?; }); +``` + +```diff +-v2.scores.download(score_id, mode, file_path); ++v2.scores.download({ id; mode?; file_path?; }); +``` + +```diff +-v2.scores.beatmap(beatmap, { mode?; mods?; type?; }); ++v2.scores.list({ type: 'leaderboard'; leaderboard_type?; beatmap_id; mods?; }); +``` + +```diff +-v2.scores.user.category(user, type, { include_fails?; mode?; mods?; limit?; offset?; }); ++v2.scores.list({ type: 'user_best' | 'user_firsts' | 'user_recent' | 'user_pinned'; user_id; include_fails?; offset?; limit?; }); +``` + +```diff +-v2.scores.user.beatmap(beatmap, user?, { mode?; mods?; best_only?; }); ++v2.scores.list({ type: 'user_beatmap_best' | 'user_beatmap_all' beatmap_id; user_id; mods?; }); +``` + +```diff +-v2.beatmap.id.attributes(beatmap_id, { mods?; ruleset?; ruleset_id?; }); ++v2.beatmaps.lookup({ type: 'attributes', id; mods?; mode?; }); +``` + +```diff +-v2.beatmap.id.lookup({ id?; checksum?; filename?; }); ++v2.beatmaps.lookup({ type: 'difficulty', id?; checksum?; filename?; }); +``` + +```diff +-v2.beatmap.id.details(beatmap); ++v2.beatmaps.details({ type: 'difficulty', id }); +``` + +```diff +-v2.beatmap.set.lookup(beatmap_id); ++v2.beatmaps.lookup({ type: 'set', id }); +``` + +```diff +-v2.beatmap.set.details(beatmapset); ++v2.beatmaps.details({ type: 'set', id }); +``` + +```diff +-v2.beatmap.set.download(beatmapset, file_path, host_name, no_video, callback?); ++v2.beatmaps.download({ type: 'set'; id; host; file_path; no_video?; overwrite?; progress_track_fn?; }); +``` + +```diff +-v2.beatmap.set.addToFavourites(beatmapset_id, action); +// not working for some reason ++v2.beatmaps.actions; +``` + +```diff +-v2.beatmap.discussions.votes({ beatmapset_discussion_id?; limit?; page?; receiver?; score?; sort?; user?; }); ++v2.beatmaps.discussions.votes({ discussion_id?; sort?; score?; user?; receiver?; limit?; cursor_string?; }); +``` + +```diff +-v2.beatmap.discussions.posts({ beatmapset_discussion_id?; limit?; page?; sort?; types?; user?; }); ++v2.beatmaps.discussions.posts({ discussion_id?; sort?; types?; user?; limit?; cursor_string?; }); +``` + +```diff +-v2.beatmap.discussions.details({ beatmap_id?; beatmapset_id?; beatmapset_status?; limit?; message_types?; only_unresolved?; page?; sort?; user?; }); ++v2.beatmaps.discussions.list({ only_unresolved?; user?; beatmap_id?; beatmapset_id?; beatmapset_status?; message_types?; limit?; sort?; cursor_string?; }); +``` + +```diff +-v2.beatmaps.details(ids); ++v2.beatmaps.lookup({ type: 'difficulties'; ids; }) +``` + +```diff +-v2.beatmaps.search({ query?; sort?; general?; mode?; section?; genre?; language?; include?; rank?; nfsw?; played?; cursor_string?; }); ++v2.search({ type: 'beatmaps'; _played?; _nsfw?; query?; mode?; status?; category?; genre?; language?; achieved_rank?; extra?; sort?; cursor_string?; }); +``` + +```diff +-v2.beatmaps.events({ user?; types?; min_date?; max_date?; }); ++v2.beatmaps.events.list({ user?; types?; min_date?; max_date?; }); +``` + +```diff +-v2.forums.topic.new(forum_id, { title; body; }, { title; options; hide_results?; length_days?; max_options?; vote_change?; }); ++v2.forums.topics.actions({ type: 'create'; forum_id; title; message; enable_poll; poll?: { allow_vote_change?; hide_results?; title; options; max_votes_per_user?; duration_days?; }); +``` + +```diff +-v2.forums.topic.edit(topic_id, { title? body? }); ++v2.forums.topics.actions({ type: 'edit_topic', topic_id?; post_id?; title?; message?; }); +``` + +```diff +-v2.forums.topic.reply(topic_id, body); ++v2.forums.topics.actions({ type: 'reply', post_id; message; }); +``` + +```diff +-v2.forums.topic.details(topic, { cursor_string?; sort?; limit?; start?; end?; }); ++v2.forums.topics.details({ id; start_id?; end_id?; limit?; sort?; cursor_string?; }); +``` + +```diff +-v2.forums.post.edit(post_id, body); ++v2.forums.topics.actions({ type: 'edit_post'; post_id; message }); +``` + +```diff +-v2.assets.seasonalBackgrounds(); ++v2.assets.backgrounds({ type: 'seasonal' }); +``` + +```diff +-v2.changelogs.list({ from?; to?; max_id?; stream?; message_formats?; }); ++v2.changelogs.list({ type: 'all'; from_build?; to_build?; stream_name?; max_id?; message_formats?; }); +``` + +```diff +-v2.changelogs.lookup(changelog, { key; message_formats;}); ++v2.changelogs.list({ type: 'lookup'; message_formats; changelog; key; }); +``` + +```diff +-v2.changelogs.details(stream, build); ++v2.changelogs.details({ stream_name; build_version; }); +``` + +```diff +-v2.comments.new({ commentable_id?; commentable_type?; message?; parent_id?; }); ++v2.comments.actions({ type: 'new', commentable_type; id; parent_id?; message; }); +``` + +```diff +-v2.comments.edit(comment_id, message); ++v2.comments.actions({ type: 'edit', id; message; }); +``` + +```diff +-v2.comments.list({ commentable_type?; commentable_id?; cursor: { id?; created_at?; }; parent_id?; sort?; }); ++v2.comments.list({ type?; id?; parent_id?; after_id?; cursor?: { id; created_at; }; sort?; }); +``` + +```diff +-v2.comments.vote(comment_id: number, type: boolean); ++v2.comments.actions({ type: 'vote'; id; }); ++v2.comments.actions({ type: 'unvote'; id; }); +``` + +```diff +-v2.comments.remove(comment_id); ++v2.comments.actions({ type: 'delete'; id; }); +``` + +```diff +-v2.comments.details(comment); ++v2.comments.details(comment_id); +``` + +```diff +-v2.site.search({ mode?; query?; page?; }); ++v2.search({ type: 'site'; location?; query?; page?; }); +``` + +```diff +-v2.site.wiki(language, path); ++v2.wiki.details({ locale; path_name; }); +``` + +```diff +-v2.site.spotlights.list(); ++v2.spotlights.list(); +``` + +```diff +-v2.site.ranking.details(mode, type, { country?; "cursor[page]"?; filter?; spotlight?; variant?; }); ++v2.ranking.list({ type; spotlight_id?; filter?; mode?; county_code?; page?; variant?; }); +``` + +```diff +-v2.site.news.list({ limit?; year?; cursorPublished?; cursorId?; }); ++v2.news.list({ from_year?; limit?; cursor_string?; }); +``` + +```diff +-v2.site.news.details(news, key); ++v2.news.detals({ news_id; key; }); +``` + +```diff +-v2.matches.list(); ++v2.matches.list({ limit?; sort?; after_id?; }); +``` + +```diff +-v2.matches.details(match); ++v2.matches.details({ match_id }); +``` + +```diff +-v2.rooms.list(mode, { category?; limit?; season_id?; type_group?; }); ++v2.rooms.list({ type?; status?; query?; limit?; sort?; cursor_string?; }); +``` + +```diff +-v2.room.details(room_id); ++v2.rooms.details({ id }); +``` + +```diff +-v2.room.leaderboard(room_id); ++v2.rooms.leaderboard({ id; limit?; }); +``` + +```diff +-v2.notifications.list(max_id); ++v2.notifications.list({ max_id; unread_only; }); +``` + +```diff +-v2.chat.new(target_id, message, is_action?, uuid?); ++v2.chat.actions({ type: 'new'; is_action; user_id; message; uuid?; }); +``` + +```diff +-v2.chat.updates({ history_since?; includes?; since; }); ++v2.chat.updates({ after_id?; includes?; history_since?; }); +``` + +```diff +-v2.chat.channels.list(); ++v2.chat.channels.list(); +// they are the same +``` + +```diff +-v2.chat.channels.join(channel_id, user_id) ++v2.chat.channels.actions({ type: 'join'; channel_id; user_id; }); +``` + +```diff +-v2.chat.channels.leave(channel_id, user_id); ++v2.chat.channels.actions({ type: 'leave'; channel_id; user_id; }); +``` + +```diff +-v2.chat.channels.details(channel?); ++v2.chat.details({ channel_id }); +``` + +```diff +-v2.chat.channels.messages.list(channel_id, { limit?; since?; until?; }); ++v2.chat.messages({ channel_id:; limit?; since?; until?; return_object?; }); +``` + +```diff +-v2.chat.channels.messages.send(channel_id, message, is_action); ++v2.chat.channels.actions({ type: 'send'; is_action; channel_id; message; }); +``` + +```diff +-v2.chat.channels.messages.markAsReaded(channel_id?, message_id?); ++v2.chat.channels.actions({ type: 'read'; channel_id; message; }); +``` From 51965366328250dab6d7154c720a17d3082e6101 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 5 Oct 2024 07:16:54 +0300 Subject: [PATCH 244/259] edit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index acd4ba66..01e009ba 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ quick links: [Features](#features) [Usage](#usage) ​ / ​ [Install](# ## Features - [x] Api - [x] osu api v1: [official documentation](https://github.com/ppy/osu-api/wiki) - - [x] osu api v2: [official documentation](https://osu.ppy.sh/docs/index.html) + - [x] osu api v2 (81+ api routes): [official documentation](https://osu.ppy.sh/docs/index.html) - [x] **Auto** session refresh - [x] You need to login only once on application start (preferable in main server file) - [x] Built-in **Tools** From a3865751a189290bcf2be47cc7755a19e9ab0441 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 5 Oct 2024 21:37:15 +0300 Subject: [PATCH 245/259] fixes --- README.md | 22 ++++++++++----------- api/v2/beatmaps_download.ts | 19 ++++++++++--------- migration.md | 2 +- routes/v2.ts | 7 ++++--- tools/accuracy.ts | 12 ++++++------ tools/country.ts | 2 +- tools/index.ts | 2 +- tools/mods.ts | 2 +- tools/net-pp.ts | 2 +- tools/objects.ts | 38 ++++++++++++++++++------------------- tools/rank.ts | 19 +++++++++++++------ 11 files changed, 68 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index 01e009ba..13984afb 100644 --- a/README.md +++ b/README.md @@ -16,16 +16,16 @@ quick links: [Features](#features) [Usage](#usage) ​ / ​ [Install](# - [x] **Auto** session refresh - [x] You need to login only once on application start (preferable in main server file) - [x] Built-in **Tools** - - [x] `tools.build_url` - Create link for `user`, `score`, `editor_timing` and others - - [x] `tools.calculate_accuracy` - Calculate accuracy from play hits - - [x] `tools.calculate_hits` - Calculate hits if play was an FC - - [x] `tools.calculate_mods` - Calculate mods Number/Name from Number/Name - - [x] `tools.calculate_net_pp` - Calculate how much pp would you gain from a play - - [x] `tools.calculate_pp` - Create link for `user`, `score`, `editor_timing` and others - - [x] `tools.calculate_rank` - Calculate rank from play hits - - [x] `tools.calculate_total_passed_objects` - Calculate total passed objects - - [x] `tools.country_details` - Get country name and code by providing country name/code - - [x] `tools.download_beatmaps` - Downloads a beatmap or beatmap set by given ID. (Supports different hosts) + - `tools.build_url` - Create link for `user`, `score`, `editor_timing` and others + - `tools.calculate_accuracy` - Calculate accuracy from play hits + - `tools.calculate_hits` - Calculate hits if play was an FC + - `tools.calculate_mods` - Calculate mods Number/Name from Number/Name + - `tools.calculate_net_pp` - Calculate how much pp would you gain from a play + - `tools.calculate_pp` - Create link for `user`, `score`, `editor_timing` and others + - `tools.calculate_rank` - Calculate rank from play hits + - `tools.calculate_total_passed_objects` - Calculate total passed objects + - `tools.country_details` - Get country name and code by providing country name/code + - `tools.download_beatmaps` - Downloads a beatmap or beatmap set by given ID. (Supports different hosts) - [x] Setting to prevent throw, [instead send .error](#prevent-throw-errors)
@@ -358,7 +358,7 @@ function download_beatmaps() { host: 'gatari', id: set_id, file_path: `./cache/${set_id}.osz`, - progress_track_fn: progress_update + progress_log_fn: progress_update }); if (result.error != null) { console.log(result.error); diff --git a/api/v2/beatmaps_download.ts b/api/v2/beatmaps_download.ts index b8a51f6b..7e64e8c3 100644 --- a/api/v2/beatmaps_download.ts +++ b/api/v2/beatmaps_download.ts @@ -16,7 +16,7 @@ type params = ({ file_path: string; overwrite?: boolean; - progress_track_fn?: (host: string, progress: number) => void; + progress_log_fn?: (host: string, progress: number) => void; } | { type: 'set'; @@ -27,7 +27,7 @@ type params = ({ no_video?: boolean; overwrite?: boolean; - progress_track_fn?: (host: string, progress: number) => void; + progress_log_fn?: (host: string, progress: number) => void; }); @@ -47,8 +47,8 @@ type Response = { *   * * ### Available hosts - * - `type:'difficulty'`: osu, osu_direct_mirror, catboy - * - `type:'set'`: osu, beatconnect, nerinyan, osu_direct_mirror, sayobot, gatari, ripple, catboy + * - For `type:'difficulty'`: osu, osu_direct_mirror, catboy + * - For `type:'set'`: osu, beatconnect, nerinyan, osu_direct_mirror, sayobot, gatari, ripple, catboy * *   * @@ -63,6 +63,7 @@ type Response = { * * ### Parameters for `params.type:'set'` * - `params.no_video?` - Whether to include video in the download. + * - `params.progress_log_fn?` - Callback function to send progress. * *   * @@ -92,7 +93,7 @@ type Response = { * host: 'gatari', * id: set_id, * file_path: `./cache/${set_id}.osz`, - * progress_track_fn: progress_update + * progress_log_fn: progress_update * }); * // or * const result = await tools.download_beatmaps({ @@ -100,7 +101,7 @@ type Response = { * host: 'gatari', * id: set_id, * file_path: `./cache/${set_id}.osz`, - * progress_track_fn: progress_update + * progress_log_fn: progress_update * }); * * console.log(result); @@ -127,7 +128,7 @@ export const beatmaps_download = async (params: T, addons?: ID const progress_track = (progress: number) => { - params.progress_track_fn(params.host, progress); + params.progress_log_fn(params.host, progress); }; @@ -206,7 +207,7 @@ export const beatmaps_download = async (params: T, addons?: ID const data = await download(url, params.file_path, { - _callback: params.progress_track_fn != null, + _callback: params.progress_log_fn != null, headers, addons: addons, callback: progress_track, @@ -237,7 +238,7 @@ export const beatmaps_download = async (params: T, addons?: ID const data = await download(url, params.file_path, { - _callback: params.progress_track_fn != null, + _callback: params.progress_log_fn != null, headers, addons: addons, callback: progress_track, diff --git a/migration.md b/migration.md index 19425737..f77853e7 100644 --- a/migration.md +++ b/migration.md @@ -107,7 +107,7 @@ Migration from `v2` to `v3` ```diff -v2.beatmap.set.download(beatmapset, file_path, host_name, no_video, callback?); -+v2.beatmaps.download({ type: 'set'; id; host; file_path; no_video?; overwrite?; progress_track_fn?; }); ++v2.beatmaps.download({ type: 'set'; id; host; file_path; no_video?; overwrite?; progress_log_fn?; }); ``` ```diff diff --git a/routes/v2.ts b/routes/v2.ts index b80a44a8..c0ddcd1e 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -295,8 +295,8 @@ export const beatmaps = { *   * * ### Available hosts - * - `type:'difficulty'`: osu, osu_direct_mirror, catboy - * - `type:'set'`: osu, beatconnect, nerinyan, osu_direct_mirror, sayobot, gatari, ripple, catboy + * - For `type:'difficulty'`: osu, osu_direct_mirror, catboy + * - For `type:'set'`: osu, beatconnect, nerinyan, osu_direct_mirror, sayobot, gatari, ripple, catboy * *   * @@ -311,6 +311,7 @@ export const beatmaps = { * * ### Parameters for `params.type:'set'` * - `params.no_video?` - Whether to include video in the download. + * - `params.progress_log_fn?` - Callback function to send progress. * *   * @@ -340,7 +341,7 @@ export const beatmaps = { * host: 'gatari', * id: set_id, * file_path: `./cache/${set_id}.osz`, - * progress_track_fn: progress_update + * progress_log_fn: progress_update * }); * * console.log(result); diff --git a/tools/accuracy.ts b/tools/accuracy.ts index 47666bae..27bc86ca 100644 --- a/tools/accuracy.ts +++ b/tools/accuracy.ts @@ -76,12 +76,12 @@ export const calculate_accuracy = (hits: Hits, mode: GamemodeEnum | string | num }; - const geki = parseInt(hits?.geki || hits.count_geki || hits.perfect || '0'); - const h300 = parseInt(hits?.[300] || hits.count_300 || hits.great || '0'); - const katu = parseInt(hits?.katu || hits.count_katu || hits.good || '0'); - const h100 = parseInt(hits?.[100] || hits.count_100 || hits.ok || '0'); - const h50 = parseInt(hits?.[50] || hits.count_50 || hits.meh || '0'); - const h0 = parseInt(hits?.[0] || hits.count_miss || hits.miss || '0'); + const geki = parseInt(hits.perfect || hits.count_geki || hits?.geki || '0'); + const h300 = parseInt(hits.great || hits.count_300 || hits?.[300] || '0'); + const katu = parseInt(hits.good || hits.count_katu || hits?.katu || '0'); + const h100 = parseInt(hits.ok || hits.count_100 || hits?.[100] || '0'); + const h50 = parseInt(hits.meh || hits.count_50 || hits?.[50] || '0'); + const h0 = parseInt(hits.miss || hits.count_miss || hits?.[0] || '0'); let accuracy = 0.0; let fc_accuracy = 0.0; diff --git a/tools/country.ts b/tools/country.ts index c99212ef..d2134367 100644 --- a/tools/country.ts +++ b/tools/country.ts @@ -7,7 +7,7 @@ import { handleErrors } from "../utility/handleErrors"; type Response = CountryResponse & IError; /** - * Get country name and code by providing country name/code + * Get more information about the country by providing an name/code. * *   * diff --git a/tools/index.ts b/tools/index.ts index 526ecb3f..96f86701 100644 --- a/tools/index.ts +++ b/tools/index.ts @@ -15,7 +15,7 @@ export const calculate_pp = () => { }; /** - * Create link for `user`, `score`, `editor_timing` and others + * Builder that returns a link an 'user', a score, a beatmap, etc. * *   * diff --git a/tools/mods.ts b/tools/mods.ts index db13b9f2..eb25b8cc 100644 --- a/tools/mods.ts +++ b/tools/mods.ts @@ -55,7 +55,7 @@ type Response = ModsResponse & IError; /** - * Calculate mods number/name from number/name + * Get mods short name or mods number by giving one of them * *   * diff --git a/tools/net-pp.ts b/tools/net-pp.ts index f647b028..5cb4f3ea 100644 --- a/tools/net-pp.ts +++ b/tools/net-pp.ts @@ -12,7 +12,7 @@ type Response = { /** - * Calculate how much pp would you gain from a play + * Calculate how much raw pp you would gain from a play * *   * diff --git a/tools/objects.ts b/tools/objects.ts index 76aeef04..307702ac 100644 --- a/tools/objects.ts +++ b/tools/objects.ts @@ -76,12 +76,12 @@ export const calculate_total_passed_objects = (hits: Hits, mode: GamemodeEnum | }; - const geki = parseInt(hits?.geki || hits.count_geki || hits.perfect || '0'); - const h300 = parseInt(hits?.[300] || hits.count_300 || hits.great || '0'); - const katu = parseInt(hits?.katu || hits.count_katu || hits.good || '0'); - const h100 = parseInt(hits?.[100] || hits.count_100 || hits.ok || '0'); - const h50 = parseInt(hits?.[50] || hits.count_50 || hits.meh || '0'); - const h0 = parseInt(hits?.[0] || hits.count_miss || hits.miss || '0'); + const geki = parseInt(hits.perfect || hits.count_geki || hits?.geki || '0'); + const h300 = parseInt(hits.great || hits.count_300 || hits?.[300] || '0'); + const katu = parseInt(hits.good || hits.count_katu || hits?.katu || '0'); + const h100 = parseInt(hits.ok || hits.count_100 || hits?.[100] || '0'); + const h50 = parseInt(hits.meh || hits.count_50 || hits?.[50] || '0'); + const h0 = parseInt(hits.miss || hits.count_miss || hits?.[0] || '0'); let total_objects = 0; @@ -132,7 +132,7 @@ type ResponseConvert = ConvertHitsResponse & IError; /** - * Calculate hits if play was an FC + * Calculate a play as an FC with the given hits. * *   * @@ -177,19 +177,19 @@ export const calculate_hits = (hits: Hits, mode: GamemodeEnum | string | number) }; - const geki = parseInt(hits?.geki || hits.count_geki || hits.perfect || '0'); - const h300 = parseInt(hits?.[300] || hits.count_300 || hits.great || '0'); - const katu = parseInt(hits?.katu || hits.count_katu || hits.good || '0'); - const h100 = parseInt(hits?.[100] || hits.count_100 || hits.ok || '0'); - const h50 = parseInt(hits?.[50] || hits.count_50 || hits.meh || '0'); - const h0 = parseInt(hits?.[0] || hits.count_miss || hits.miss || '0'); + const geki = parseInt(hits.perfect || hits.count_geki || hits?.geki || '0'); + const h300 = parseInt(hits.great || hits.count_300 || hits?.[300] || '0'); + const katu = parseInt(hits.good || hits.count_katu || hits?.katu || '0'); + const h100 = parseInt(hits.ok || hits.count_100 || hits?.[100] || '0'); + const h50 = parseInt(hits.meh || hits.count_50 || hits?.[50] || '0'); + const h0 = parseInt(hits.miss || hits.count_miss || hits?.[0] || '0'); - let geki_fc = parseInt(hits?.geki || hits.count_geki || hits.perfect || '0'); - let h300_fc = parseInt(hits?.[300] || hits.count_300 || hits.great || '0'); - let katu_fc = parseInt(hits?.katu || hits.count_katu || hits.good || '0'); - let h100_fc = parseInt(hits?.[100] || hits.count_100 || hits.ok || '0'); - let h50_fc = parseInt(hits?.[50] || hits.count_50 || hits.meh || '0'); - let h0_fc = parseInt(hits?.[0] || hits.count_miss || hits.miss || '0'); + let geki_fc = parseInt(hits.perfect || hits.count_geki || hits?.geki || '0'); + let h300_fc = parseInt(hits.great || hits.count_300 || hits?.[300] || '0'); + let katu_fc = parseInt(hits.good || hits.count_katu || hits?.katu || '0'); + let h100_fc = parseInt(hits.ok || hits.count_100 || hits?.[100] || '0'); + let h50_fc = parseInt(hits.meh || hits.count_50 || hits?.[50] || '0'); + let h0_fc = parseInt(hits.miss || hits.count_miss || hits?.[0] || '0'); switch (mode) { diff --git a/tools/rank.ts b/tools/rank.ts index 2a5a0fec..ec29643a 100644 --- a/tools/rank.ts +++ b/tools/rank.ts @@ -21,6 +21,13 @@ type Hits = { ok?: any; meh?: any; miss?: any; + + count_geki?: any; + count_300?: any; + count_katu?: any; + count_100?: any; + count_50?: any; + count_miss?: any; }; type Response = RankResponse & IError; @@ -76,12 +83,12 @@ export const calculate_rank = (hits: Hits, mods: Mod[] | string | number = 0, mo const { name: modsName } = calculate_mods(mods);; const { accuracy } = calculate_accuracy(hits, mode); - const geki = parseInt(hits?.geki || hits.perfect || '0'); - const h300 = parseInt(hits?.[300] || hits.great || '0'); - const katu = parseInt(hits?.katu || hits.good || '0'); - const h100 = parseInt(hits?.[100] || hits.ok || '0'); - const h50 = parseInt(hits?.[50] || hits.meh || '0'); - const h0 = parseInt(hits?.[0] || hits.miss || '0'); + const geki = parseInt(hits.perfect || hits.count_geki || hits?.geki || '0'); + const h300 = parseInt(hits.great || hits.count_300 || hits?.[300] || '0'); + const katu = parseInt(hits.good || hits.count_katu || hits?.katu || '0'); + const h100 = parseInt(hits.ok || hits.count_100 || hits?.[100] || '0'); + const h50 = parseInt(hits.meh || hits.count_50 || hits?.[50] || '0'); + const h0 = parseInt(hits.miss || hits.count_miss || hits?.[0] || '0'); const is_silver = /hd|fl/i.test(modsName); From 716aee0ec53fb473efd3990fb2fb54a09760d4dc Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sat, 5 Oct 2024 21:56:08 +0300 Subject: [PATCH 246/259] more fixes --- README.md | 21 +++++++++++++-------- api/v2/beatmaps_download.ts | 2 +- migration.md | 30 ++++++++++++++++++++++++++++++ routes/v2.ts | 30 +++++++++++++++--------------- 4 files changed, 59 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 13984afb..076e80d4 100644 --- a/README.md +++ b/README.md @@ -5,16 +5,16 @@ # osu-api-extended -quick links: [Features](#features) [Usage](#usage) ​ / ​ [Install](#installation) ​ / ​ [Quickstart](#quickstart) ​ / ​ [Tools](#tools) +Quick Links: [Features](#features) ​ / ​ [Usage](#usage) ​ / ​ [Install](#installation) ​ / ​ [Quickstart](#quickstart) ​ / ​ [Tools](#tools)
## Features - [x] Api - - [x] osu api v1: [official documentation](https://github.com/ppy/osu-api/wiki) - - [x] osu api v2 (81+ api routes): [official documentation](https://osu.ppy.sh/docs/index.html) + - [x] osu api v1: [See official documentation](https://github.com/ppy/osu-api/wiki) + - [x] osu api v2 (81+ api routes): [See official documentation](https://osu.ppy.sh/docs/index.html) - [x] **Auto** session refresh -- [x] You need to login only once on application start (preferable in main server file) +- [x] Does not require you to login for each action - [x] Built-in **Tools** - `tools.build_url` - Create link for `user`, `score`, `editor_timing` and others - `tools.calculate_accuracy` - Calculate accuracy from play hits @@ -56,7 +56,7 @@ bun install osu-api-extended Links: [create your client here](https://osu.ppy.sh/home/account/edit#oauth 'https://osu.ppy.sh/home/account/edit#oauth') ​ / ​ [get your api key here](https://osu.ppy.sh/p/api 'https://osu.ppy.sh/p/api') -quick links: [v2 - client auth](#client-auth) ​ / ​ [v2 - lazer auth](#lazer-auth) ​ / ​ [v2 - cli auth](#cli-auth) ​ / ​ [v2 - Discord Verify](#discord-verify) ​ / ​ [v2 - Website login](#website-login) ​ / ​ [v1 usage](#v1-usage) ​ / ​ [v2 - prevent throw errors](#prevent-throw-errors) +Quick Links: [v2 - client auth](#client-auth) ​ / ​ [v2 - lazer auth](#lazer-auth) ​ / ​ [v2 - cli auth](#cli-auth) ​ / ​ [v2 - Discord Verify](#discord-verify) ​ / ​ [v2 - Website login](#website-login) ​ / ​ [v1 usage](#v1-usage) ​ / ​ [v2 - prevent throw errors](#prevent-throw-errors)
@@ -72,7 +72,7 @@ async function main() { type: 'v2', client_id: CLIENT_ID, client_secret: CLIENT_SECRET, - cachedTokenPath: './client.json' // path to a file where will be stored auth token to prevent spam auth to osu + cachedTokenPath: './client.json' // path to the file your auth token will be saved (to prevent osu!api spam) }); const result = await v2.users.details({ user: 'mrekk', mode: 'osu', key: '@' }); @@ -107,7 +107,7 @@ async function main() { type: 'v2', login: LOGIN, password: PASSWORD, - cachedTokenPath: './lazer.json' // path to a file where will be stored auth token to prevent spam auth to osu + cachedTokenPath: './lazer.json' // path to the file your auth token will be saved (to prevent osu!api spam) }); const result = await v2.me.details(); @@ -142,7 +142,7 @@ async function main() { client_secret: CLIENT_SECRET, redirect_url: REDIRECT_URL, scopes: ['public'], - cachedTokenPath: './cli.json' // path to a file where will be stored auth token to prevent spam auth to osu + cachedTokenPath: './cli.json' // path to the file your auth token will be saved (to prevent osu!api spam) }); const result = await v2.me.details(); @@ -503,4 +503,9 @@ function calculate_net_pp() { zero +
+
+ +## Credits + - `request.ts` by [AqilCont](https://github.com/AqilCont 'https://github.com/AqilCont') diff --git a/api/v2/beatmaps_download.ts b/api/v2/beatmaps_download.ts index 7e64e8c3..8c5583f0 100644 --- a/api/v2/beatmaps_download.ts +++ b/api/v2/beatmaps_download.ts @@ -78,7 +78,7 @@ type Response = { * type: 'lazer', * login: login, * password: password, - * cachedTokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * diff --git a/migration.md b/migration.md index f77853e7..8bb0f57d 100644 --- a/migration.md +++ b/migration.md @@ -327,3 +327,33 @@ Migration from `v2` to `v3` -v2.chat.channels.messages.markAsReaded(channel_id?, message_id?); +v2.chat.channels.actions({ type: 'read'; channel_id; message; }); ``` + +```diff +-tools.accuracy({ 300; 100; 50; 0; geki; katu; }, mode); ++tools.calculate_accuracy({ 300?; 100?; 50?; 0?; geki?; katu?; }, mode); +``` + +```diff +-tools.country(flag); ++tools.country_details(CodeOrName); +``` + +```diff +-tools.download.difficulty(diff_id, path, name, overwrite?); ++tools.download_beatmaps({ type: 'difficulty'; id; host; file_path; overwrite?; progress_log_fn?; }); +``` + +```diff +-tools.pp.calculate(id, mods?, combo?, miss?, acc?); +``` +deadge, use [rosu-pp](https://www.npmjs.com/package/rosu-pp-js) + +```diff +-tools.rank({ 300; 100; 50; 0; geki; katu; }, mods, mode); ++calculate_rank({ 300?; 100?; 50?; 0?; geki?; katu?; }, mods, mode); +``` + +```diff +-tools.total_objects({ 300; 100; 50; 0; geki; katu; }, mode); ++calculate_total_passed_objects({ 300?; 100?; 50?; 0?; geki?; katu?; }, mode); +``` diff --git a/routes/v2.ts b/routes/v2.ts index c0ddcd1e..25f09721 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -326,7 +326,7 @@ export const beatmaps = { * type: 'lazer', * login: login, * password: password, - * cachedTokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * @@ -1239,7 +1239,7 @@ export const scores = { * type: 'lazer', * login: login, * password: password, - * cachedTokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.scores.download({ @@ -1391,7 +1391,7 @@ export const forums = { * type: 'lazer', * login: login, * password: password, - * cachedTokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.forums.topics.actions({ @@ -1772,7 +1772,7 @@ export const notifications = { * type: 'lazer', * login: login, * password: password, - * cachedTokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.notifications.list(); @@ -2065,7 +2065,7 @@ export const me = { * type: 'lazer', * login, * password - * cachedTokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.me.download_quota(); @@ -2109,7 +2109,7 @@ export const me = { * type: 'lazer', * login, * password - * cachedTokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.me.friends(); @@ -2392,7 +2392,7 @@ export const chat = { * type: 'lazer', * login, * password - * cachedTokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.chat.channels.actions({ @@ -2469,7 +2469,7 @@ export const chat = { * type: 'lazer', * login, * password - * cachedTokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.chat.messages({ id: 24594482 }); @@ -2516,7 +2516,7 @@ export const chat = { * type: 'lazer', * login, * password - * cachedTokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.chat.updates({ @@ -2563,7 +2563,7 @@ export const chat = { * type: 'lazer', * login, * password - * cachedTokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.chat.details({ channel_id: 24594482 }); @@ -2623,7 +2623,7 @@ export const session = { * type: 'lazer', * login, * password, - * cachedTokenPath: './test.json' // please use for caching + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.session.actions({ @@ -2698,7 +2698,7 @@ export const rooms = { * type: 'lazer', * login, * password, - * cachedTokenPath: './test.json' + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.rooms.list({ @@ -2759,7 +2759,7 @@ export const rooms = { * type: 'lazer', * login, * password, - * cachedTokenPath: './test.json' + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.rooms.scores({ @@ -2825,7 +2825,7 @@ export const rooms = { * type: 'lazer', * login, * password, - * cachedTokenPath: './test.json' + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.rooms.details({ @@ -2873,7 +2873,7 @@ export const rooms = { * type: 'lazer', * login, * password, - * cachedTokenPath: './test.json' + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.rooms.leaderboard({ From 466a6fd4058c6bab28611527e3a16751ad73948a Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 6 Oct 2024 00:44:47 +0300 Subject: [PATCH 247/259] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1b3222c9..399c8fe8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.37", + "version": "3.0.0-beta.38", "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", "main": "dist/index.js", "types": "dist/index.d.ts", From b125fd4ce6a01b1fa9aa8df175941dc39648242a Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 6 Oct 2024 06:23:24 +0300 Subject: [PATCH 248/259] fixes again --- api/v2/beatmaps_download.ts | 24 +++++++------------ api/v2/beatmaps_events_list.ts | 2 +- routes/v2.ts | 4 ++-- types/v2/beatmaps_download.ts | 10 ++++++++ ...maps_events.ts => beatmaps_events_list.ts} | 0 5 files changed, 21 insertions(+), 19 deletions(-) create mode 100644 types/v2/beatmaps_download.ts rename types/v2/{beatmaps_events.ts => beatmaps_events_list.ts} (100%) diff --git a/api/v2/beatmaps_download.ts b/api/v2/beatmaps_download.ts index 8c5583f0..276abfee 100644 --- a/api/v2/beatmaps_download.ts +++ b/api/v2/beatmaps_download.ts @@ -1,9 +1,10 @@ -import { IDefaultParams, IError } from "../../types"; +import { IDefaultParams } from "../../types"; import { download } from "../../utility/request"; import { cache, credentials } from "../../utility/auth"; import path from "path"; import fs from "fs"; import { handleErrors } from "../../utility/handleErrors"; +import { BeatmapsDownloadResponse } from "../../types/v2/beatmaps_download"; @@ -31,15 +32,6 @@ type params = ({ }); -type Response = { - status: string, - destination?: string, - /** - * Time in milliseconds - */ - elapsed_time?: number -} & IError; - /** * `async` Downloads a beatmap or beatmap set by given ID. (Supports different hosts) @@ -117,13 +109,13 @@ type Response = { * * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2beatmapsetsbeatmapsetdownload) */ -export const beatmaps_download = async (params: T, addons?: IDefaultParams): Promise => { +export const beatmaps_download = async (params: T, addons?: IDefaultParams): Promise => { const { dir } = path.parse(params.file_path); if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); if (fs.existsSync(params.file_path) && params.overwrite != true) { - return { status: 'File already exists' } as Response; + return { status: 'File already exists' } as BeatmapsDownloadResponse; }; @@ -189,11 +181,11 @@ export const beatmaps_download = async (params: T, addons?: ID case 'osu': if (credentials.type != 'lazer') { - return handleErrors(new Error(`Login via lazer to use this endpoint`)) as Response; + return handleErrors(new Error(`Login via lazer to use this endpoint`)) as BeatmapsDownloadResponse; }; if ((addons?.authKey || cache.v2) == null) { - return handleErrors(new Error('osu is not authorized')) as Response; + return handleErrors(new Error('osu is not authorized')) as BeatmapsDownloadResponse; }; @@ -202,7 +194,7 @@ export const beatmaps_download = async (params: T, addons?: ID break; default: - return handleErrors(new Error(`Unsupported host: ${(params as any).host}`)) as Response; + return handleErrors(new Error(`Unsupported host: ${(params as any).host}`)) as BeatmapsDownloadResponse; }; @@ -251,5 +243,5 @@ export const beatmaps_download = async (params: T, addons?: ID }; - return handleErrors(new Error(`Unsupported type: ${(params as any).type}`)) as Response; + return handleErrors(new Error(`Unsupported type: ${(params as any).type}`)) as BeatmapsDownloadResponse; }; \ No newline at end of file diff --git a/api/v2/beatmaps_events_list.ts b/api/v2/beatmaps_events_list.ts index aaf399c8..518d48ad 100644 --- a/api/v2/beatmaps_events_list.ts +++ b/api/v2/beatmaps_events_list.ts @@ -1,4 +1,4 @@ -import { BeatmapsEvents } from "../../types/v2/beatmaps_events"; +import { BeatmapsEvents } from "../../types/v2/beatmaps_events_list"; import { IDefaultParams, IError, beatmap_events_types } from "../../types"; import { request } from "../../utility/request"; import { handleErrors } from "../../utility/handleErrors"; diff --git a/routes/v2.ts b/routes/v2.ts index 25f09721..1cdfc5d2 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -285,7 +285,7 @@ export const beatmaps = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2beatmapsetsevents) | [Check return types](../types/v2/beatmaps_events.ts) + * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2beatmapsetsevents) | [Check return types](../types/v2/beatmaps_events_list.ts) */ list: beatmaps_events_list, }, @@ -364,7 +364,7 @@ export const beatmaps = { */ discussions: { /** - * ### `GET` [/v2/beatmapsets/discussions`](https://osu.ppy.sh/docs/index.html#get-beatmapset-discussions) + * ### `GET` [/v2/beatmapsets/discussions](https://osu.ppy.sh/docs/index.html#get-beatmapset-discussions) * `async` Retrieves a list of beatmap set discussions. * *   diff --git a/types/v2/beatmaps_download.ts b/types/v2/beatmaps_download.ts new file mode 100644 index 00000000..6ef4412c --- /dev/null +++ b/types/v2/beatmaps_download.ts @@ -0,0 +1,10 @@ +import { IError } from ".."; + +export type BeatmapsDownloadResponse = { + status: string, + destination?: string, + /** + * Time in milliseconds + */ + elapsed_time?: number +} & IError; \ No newline at end of file diff --git a/types/v2/beatmaps_events.ts b/types/v2/beatmaps_events_list.ts similarity index 100% rename from types/v2/beatmaps_events.ts rename to types/v2/beatmaps_events_list.ts From 8f898f52aa71baa7d69360600a40d74bd1053014 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 6 Oct 2024 07:13:59 +0300 Subject: [PATCH 249/259] prevent download until path is specified --- api/v2/scores_download.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/api/v2/scores_download.ts b/api/v2/scores_download.ts index 3b21a9dd..55a15f8c 100644 --- a/api/v2/scores_download.ts +++ b/api/v2/scores_download.ts @@ -11,7 +11,7 @@ type Response = ScoresDownloadResponse & IError; export const scores_download = async (params: { id: number; mode?: Modes_names; - file_path?: string; + file_path: string; }): Promise => { if (credentials.type != 'lazer' && credentials.type != 'cli') { return handleErrors(new Error(`Login via lazer or cli to use this endpoint`)) as Response; @@ -21,6 +21,10 @@ export const scores_download = async (params: { return handleErrors(new Error(`Specify score id`)) as Response; }; + if (params?.file_path == null) { + return handleErrors(new Error(`Specify file_path`)) as Response; + }; + const url = params.mode ? `https://osu.ppy.sh/api/v2/scores/${params.mode}/${params.id}` : `https://osu.ppy.sh/api/v2/scores/${params.id}`; From 9568fb3dc43d4f65ec01e0d888196b9bca447a58 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 6 Oct 2024 07:29:39 +0300 Subject: [PATCH 250/259] use wiki instead of official docs --- api/v2/beatmaps_download.ts | 2 +- routes/v2.ts | 102 ++++++++++++++++++------------------ 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/api/v2/beatmaps_download.ts b/api/v2/beatmaps_download.ts index 276abfee..dddbb5a1 100644 --- a/api/v2/beatmaps_download.ts +++ b/api/v2/beatmaps_download.ts @@ -107,7 +107,7 @@ type params = ({ * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2beatmapsetsbeatmapsetdownload) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.beatmaps.download_v3) */ export const beatmaps_download = async (params: T, addons?: IDefaultParams): Promise => { const { dir } = path.parse(params.file_path); diff --git a/routes/v2.ts b/routes/v2.ts index 1cdfc5d2..6dc2d2e5 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -62,7 +62,7 @@ export const beatmaps = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-beatmap-packs) | [Check return types](../types/v2/beatmaps_packs_list.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.beatmaps.packs.list_v3) | [Check return types](../types/v2/beatmaps_packs_list.ts) */ list: beatmaps_packs_list, /** @@ -102,7 +102,7 @@ export const beatmaps = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-beatmap-pack) | [Check return types](../types/v2/beatmaps_packs_details.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.beatmaps.packs.details_v3) | [Check return types](../types/v2/beatmaps_packs_details.ts) */ details: beatmap_packs_details, }, @@ -192,7 +192,7 @@ export const beatmaps = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#lookup-beatmap) | [Check return types](../types/v2/beatmaps_lookup.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.beatmaps.lookup_v3) | [Check return types](../types/v2/beatmaps_lookup.ts) */ lookup: beatmaps_lookup, /** @@ -237,7 +237,7 @@ export const beatmaps = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-beatmap) | [Check return types](../types/v2/beatmaps_details_set.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.beatmaps.details_v3) | [Check return types](../types/v2/beatmaps_details_set.ts) */ details: beatmaps_details, /** @@ -285,7 +285,7 @@ export const beatmaps = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2beatmapsetsevents) | [Check return types](../types/v2/beatmaps_events_list.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.beatmaps.events.list_v3) | [Check return types](../types/v2/beatmaps_events_list.ts) */ list: beatmaps_events_list, }, @@ -355,7 +355,7 @@ export const beatmaps = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2beatmapsetsbeatmapsetdownload) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.beatmaps.download_v3) */ download: beatmaps_download, /** @@ -408,7 +408,7 @@ export const beatmaps = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-beatmapset-discussions) | [Check return types](../types/v2/beatmaps_discussions_list.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.beatmaps.discussions.list_v3) | [Check return types](../types/v2/beatmaps_discussions_list.ts) */ list: beatmaps_discussions_list, /** @@ -452,7 +452,7 @@ export const beatmaps = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#beatmapset-discussions) | [Check return types](../types/v2/beatmaps_discussions_posts.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.beatmaps.discussions.posts_v3) | [Check return types](../types/v2/beatmaps_discussions_posts.ts) */ posts: beatmaps_discussions_posts, /** @@ -498,7 +498,7 @@ export const beatmaps = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-beatmapset-discussion-votes) | [Check return types](../types/v2/beatmaps_discussions_votes.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.beatmaps.discussions.votes_v3) | [Check return types](../types/v2/beatmaps_discussions_votes.ts) */ votes: beatmaps_discussions_votes, }, @@ -574,7 +574,7 @@ export const changelogs = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-changelog-listing) | [Check return types](../types/v2/changelogs_list_all.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.changelogs.list_v3) | [Check return types](../types/v2/changelogs_list_all.ts) */ list: changelogs_list, /** @@ -616,7 +616,7 @@ export const changelogs = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-changelog-build) | [Check return types](../types/v2/changelogs_details.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.changelogs.details_v3) | [Check return types](../types/v2/changelogs_details.ts) */ details: changelogs_details, }; @@ -678,7 +678,7 @@ export const comments = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-comments-listing) | [Check return types](../types/v2/comments_list.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.comments.list_v3) | [Check return types](../types/v2/comments_list.ts) */ list: comments_list, /** @@ -717,7 +717,7 @@ export const comments = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-a-comment) | [Check return types](../types/v2/comments_details.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.comments.details_v3) | [Check return types](../types/v2/comments_details.ts) */ details: comments_details, /** @@ -757,7 +757,7 @@ export const comments = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#post-a-new-comment) | [Check return types](../types/v2/comments_actions.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.comments.actions_v3) | [Check return types](../types/v2/comments_actions.ts) */ actions: comments_actions, }; @@ -821,7 +821,7 @@ export const users = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-users) | [Check return types](../types/v2/users_list.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.users.list_v3) | [Check return types](../types/v2/users_list.ts) */ list: users_list, /** @@ -867,7 +867,7 @@ export const users = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-user-kudosu) | [Check return types](../types/v2/users_kudosu.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.users.kudosu_v3) | [Check return types](../types/v2/users_kudosu.ts) */ kudosu: users_kudosu, /** @@ -913,7 +913,7 @@ export const users = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-events) | [Check return types](../types/v2/users_events.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.users.events_v3) | [Check return types](../types/v2/users_events.ts) */ events: users_events, /** @@ -959,7 +959,7 @@ export const users = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-user) | [Check return types](../types/v2/users_details.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.users.details_v3) | [Check return types](../types/v2/users_details.ts) */ details: users_details, /** @@ -1006,7 +1006,7 @@ export const users = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-user-beatmaps) | [Check return types](../types/v2/users_beatmaps.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.users.beatmaps_v3) | [Check return types](../types/v2/users_beatmaps.ts) */ beatmaps: users_beatmaps, /** @@ -1052,7 +1052,7 @@ export const users = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-user-recent-activity) | [Check return types](../types/v2/users_activity.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.users.activity_v3) | [Check return types](../types/v2/users_activity.ts) */ activity: users_activity, }; @@ -1164,7 +1164,7 @@ export const scores = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-beatmap-scores) | [Check return types](../types/v2/scores_list_user_recent.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.scores.list_v3) | [Check return types](../types/v2/scores_list_user_recent.ts) * */ list: scores_list, @@ -1212,7 +1212,7 @@ export const scores = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2scoresrulesetorscorescore) | [Check return types](../types/v2/scores_details.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.scores.details_v3) | [Check return types](../types/v2/scores_details.ts) * */ details: scores_details, @@ -1262,7 +1262,7 @@ export const scores = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2scoresrulesetorscorescoredownload) | [Check return types](../types/v2/scores_download.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.scores.download_v3) | [Check return types](../types/v2/scores_download.ts) */ download: scores_download, }; @@ -1331,7 +1331,7 @@ export const forums = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-beatmap-packs) | [Check return types](../types/v2/forums_topics_details.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.forums.topics.details_v3) | [Check return types](../types/v2/forums_topics_details.ts) */ details: forums_topics_details, /** @@ -1443,7 +1443,7 @@ export const forums = { *   * * - * [See documentation](https://osu.ppy.sh/docs/index.html#forum) | [Check return types](../types/v2/forums_topics_actions_reply.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.forums.topics.actions_v3) | [Check return types](../types/v2/forums_topics_actions_reply.ts) */ actions: forums_topics_actions, }, @@ -1525,7 +1525,7 @@ import { search_all } from '../api/v2/search'; * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#search) | [Check return types](../types/v2/search_all.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.search_v3) | [Check return types](../types/v2/search_all.ts) * */ export const search = search_all; @@ -1588,7 +1588,7 @@ export const assets = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2seasonal-backgrounds) | [Check return types](../types/v2/assets_backgrounds.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.assets.backgrounds_v3) | [Check return types](../types/v2/assets_backgrounds.ts) */ backgrounds: assets_backgrounds, /** @@ -1626,7 +1626,7 @@ export const assets = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2seasonal-backgrounds) | [Check return types](../types/v2/assets_datafiles.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.assets.datafiles_v3) | [Check return types](../types/v2/assets_datafiles.ts) */ dataFiles: assets_dataFiles }; @@ -1685,7 +1685,7 @@ export const news = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-news-listing) | [Check return types](../types/v2/news_list.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.news.list_v3) | [Check return types](../types/v2/news_list.ts) */ list: news_list, /** @@ -1733,7 +1733,7 @@ export const news = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-news-post) | [Check return types](../types/v2/news_details.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.news.details_v3) | [Check return types](../types/v2/news_details.ts) */ details: news_details, }; @@ -1792,7 +1792,7 @@ export const notifications = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-notifications) | [Check return types](../types/v2/notifications_list.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.notifications.list_v3) | [Check return types](../types/v2/notifications_list.ts) */ list: notifications_list, /** @@ -1918,7 +1918,7 @@ export const ranking = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-ranking) | [Check return types](../types/v2/ranking_list_performance.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.ranking.list_v3) | [Check return types](../types/v2/ranking_list_performance.ts) */ list: ranking_list, }; @@ -1973,7 +1973,7 @@ export const spotlights = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-spotlights) | [Check return types](../types/v2/spotlights_list.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.spotlights.list_v3) | [Check return types](../types/v2/spotlights_list.ts) */ list: spotlights_list, }; @@ -2027,7 +2027,7 @@ export const wiki = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-wiki-page) | [Check return types](../types/v2/wiki_details.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.wiki.details_v3) | [Check return types](../types/v2/wiki_details.ts) */ details: wiki_details, }; @@ -2085,7 +2085,7 @@ export const me = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2medownload-quota-check) | [Check return types](../types/v2/me_download_quota.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.me.download_quota_v3) | [Check return types](../types/v2/me_download_quota.ts) */ download_quota: me_download_quota, /** @@ -2129,7 +2129,7 @@ export const me = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2friends) | [Check return types](../types/v2/me_friends.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.me.friends_v3) | [Check return types](../types/v2/me_friends.ts) */ friends: me_friends, /** @@ -2173,7 +2173,7 @@ export const me = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-own-data) | [Check return types](../types/v2/me_details.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.me.details_v3) | [Check return types](../types/v2/me_details.ts) */ details: me_details, }; @@ -2235,7 +2235,7 @@ export const matches = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2matches) | [Check return types](../types/v2/matches_list.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.matches.list_v3) | [Check return types](../types/v2/matches_list.ts) */ list: matches_list, /** @@ -2279,7 +2279,7 @@ export const matches = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2matchesmatch) | [Check return types](../types/v2/matches_details.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.matches.details_v3) | [Check return types](../types/v2/matches_details.ts) */ details: matches_details, }; @@ -2345,7 +2345,7 @@ export const chat = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-channel-list) | [Check return types](../types/v2/chat_channels_list.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.chat.channels.list_v3) | [Check return types](../types/v2/chat_channels_list.ts) */ list: chat_channels_list, /** @@ -2439,7 +2439,7 @@ export const chat = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#send-message-to-channel) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.chat.channels.actions_v3) */ actions: chat_channels_actions, }, @@ -2489,7 +2489,7 @@ export const chat = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-channel-messages) | [Check return types](../types/v2/chat_messages.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.chat.messages_v3) | [Check return types](../types/v2/chat_messages.ts) */ messages: chat_messages, /** @@ -2539,7 +2539,7 @@ export const chat = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-updates) | [Check return types](../types/v2/chat_updates.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.chat.updates_v3) | [Check return types](../types/v2/chat_updates.ts) */ updates: chat_updates, /** @@ -2583,7 +2583,7 @@ export const chat = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-channel) | [Check return types](../types/v2/chat_details.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.chat.details_v3) | [Check return types](../types/v2/chat_details.ts) */ details: chat_details, actions: chat_actions, @@ -2654,7 +2654,7 @@ export const session = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#post-apiv2sessionverify) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.session.actions_v3) */ actions: session_actions, }; @@ -2726,7 +2726,7 @@ export const rooms = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-multiplayer-rooms) | [Check return types](../types/v2/rooms_list.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.rooms.list_v3) | [Check return types](../types/v2/rooms_list.ts) */ list: rooms_list, /** @@ -2800,7 +2800,7 @@ export const rooms = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-scores) | [Check return types](../types/v2/rooms_scores_all.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.rooms.scores_v3) | [Check return types](../types/v2/rooms_scores_all.ts) */ scores: rooms_scores, /** @@ -2847,7 +2847,7 @@ export const rooms = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2roomsroom) | [Check return types](../types/v2/rooms_details.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.rooms.details_v3) | [Check return types](../types/v2/rooms_details.ts) */ details: rooms_details, /** @@ -2895,7 +2895,7 @@ export const rooms = { * *   * - * [See documentation](https://osu.ppy.sh/docs/index.html#get-apiv2roomsroomleaderboard) | [Check return types](../types/v2/rooms_leaderboard.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.rooms.leaderboard_v3) | [Check return types](../types/v2/rooms_leaderboard.ts) */ leaderboard: rooms_leaderboard, }; @@ -2947,7 +2947,7 @@ export const groups = { * *   * - * [Check return types](../types/v2/groups_details.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.groups.details_v3) | [Check return types](../types/v2/groups_details.ts) */ details: groups_details, /** @@ -2989,7 +2989,7 @@ export const groups = { * *   * - * [Check return types](../types/v2/groups_details.ts) + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.groups.history_v3) | [Check return types](../types/v2/groups_history.ts) */ history: groups_history, } \ No newline at end of file From 4f3526515ac14f44cf9b7db6d8b59df933ddcabd Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 6 Oct 2024 20:04:02 +0300 Subject: [PATCH 251/259] remove channels.actions --- api/v2/chat_channels_actions.ts | 114 ------------------ routes/v2.ts | 95 --------------- ...s_actions_join.ts => chat_actions_join.ts} | 2 +- ...s_actions_send.ts => chat_actions_send.ts} | 2 +- 4 files changed, 2 insertions(+), 211 deletions(-) delete mode 100644 api/v2/chat_channels_actions.ts rename types/v2/{chat_channels_actions_join.ts => chat_actions_join.ts} (87%) rename types/v2/{chat_channels_actions_send.ts => chat_actions_send.ts} (89%) diff --git a/api/v2/chat_channels_actions.ts b/api/v2/chat_channels_actions.ts deleted file mode 100644 index 73dd97d0..00000000 --- a/api/v2/chat_channels_actions.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { request } from "../../utility/request"; -import { IDefaultParams, IError } from "../../types"; -import { chatChannelsActionsSendResponse } from "../../types/v2/chat_channels_actions_send"; -import { chatChannelsActionsJoinResponse } from "../../types/v2/chat_channels_actions_join"; -import { handleErrors } from "../../utility/handleErrors"; -import { credentials } from "../../utility/auth"; - - -type params = ({ - type: 'send'; - - is_action: boolean; - - channel_id: number; - message: string; -} | { - type: 'join' | 'leave'; - - channel_id: number; - user_id: number; -} | { - type: 'read'; - - channel_id: number; - message_id: number; -}); - - -type Response = - T extends 'send' - ? chatChannelsActionsSendResponse & IError - : T extends 'join' - ? chatChannelsActionsJoinResponse & IError - : T extends 'leave' - ? "" & IError - : T extends 'read' - ? "" & IError - : IError; - - -export const chat_channels_actions = async (params: T, addons?: IDefaultParams): Promise> => { - if (credentials.type != 'lazer' && credentials.type != 'cli') { - return handleErrors(new Error(`Login via lazer or cli to use this endpoint`)) as Response; - }; - - if (credentials.type == 'cli' && !credentials.scopes.includes('chat.write')) { - return handleErrors(new Error(`Requires "chat.read" scope`)) as Response; - }; - - - const object: any = {}; - let url = 'https://osu.ppy.sh/api/v2'; - let method = 'POST'; - - - switch (params?.type) { - case 'send': - if (params?.channel_id == null || params?.message == null || params?.is_action == null) { - return handleErrors(new Error(`Missing required parameters`)) as Response; - }; - - - url += `/chat/channels/${params.channel_id}/messages`; - - if (params?.message != null) object['message'] = params.message; - if (params?.is_action != null) object['is_action'] = params.is_action; - break; - - case 'join': - if (params?.channel_id == null || params?.user_id == null) { - return handleErrors(new Error(`Missing required parameters`)) as Response; - }; - - - url += `/chat/channels/${params.channel_id}/users/${params.user_id}`; - method = 'PUT'; - break; - - case 'leave': - if (params?.channel_id == null || params?.user_id == null) { - return handleErrors(new Error(`Missing required parameters`)) as Response; - }; - - - url += `/chat/channels/${params.channel_id}/users/${params.user_id}`; - method = 'DELETE'; - break; - - case 'read': - if (params?.channel_id == null || params?.message_id == null) { - return handleErrors(new Error(`Missing required parameters`)) as Response; - }; - - - url += `/chat/channels/${params.channel_id}/mark-as-read/${params.message_id}`; - method = 'PUT'; - break; - - default: - return handleErrors(new Error(`Unsupported type: ${(params as any).type}`)) as Response; - }; - - - const data = await request(url, { - method: method, - params: object, - addons, - }); - - if (data.error) return handleErrors(new Error(data.error)) as Response; - - - return data as Response; -}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index 6dc2d2e5..fcd7c21a 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -2287,7 +2287,6 @@ export const matches = { import { chat_channels_list } from "../api/v2/chat_channels_list"; -import { chat_channels_actions } from "../api/v2/chat_channels_actions"; import { chat_messages } from "../api/v2/chat_messages"; import { chat_updates } from "../api/v2/chat_updates"; @@ -2348,100 +2347,6 @@ export const chat = { * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.chat.channels.list_v3) | [Check return types](../types/v2/chat_channels_list.ts) */ list: chat_channels_list, - /** - * ### `POST` [/v2/chat/channels/{channel}/messages](https://osu.ppy.sh/docs/index.html#send-message-to-channel) - * ### `PUT` [/v2/chat/channels/{channel}/users/{user}](https://osu.ppy.sh/docs/index.html#join-channel) - * ### `DELETE` [/v2/chat/channels/{channel}/users/{user}](https://osu.ppy.sh/docs/index.html#leave-channel) - * ### `PUT` [/v2/chat/channels/{channel}/mark-as-read/{message}](https://osu.ppy.sh/docs/index.html#mark-channel-as-read) - * `async` Performs a set of actions on a list of channels. (Requires lazer authentication) - * - *   - * - * ### Global Parameters - * - `params.type` - Type of action to perform. - * - `addons?` - Additional parameters to include in the request. - * - *   - * - * ### Parameters for `params.type: 'send'` - * - `params.id` - The ID of the channel to send to. - * - `params.message` - The message to send. - * - `params.is_action` - Whether the message is an action. - * - *   - * - * ### Parameters for `params.type: 'join' | 'leave'` - * - `params.id` - The ID of the channel. - * - `params.user_id` - The ID of the user. - * - *   - * - * ### Parameters for `params.type: 'read'` - * - `params.channel_id` - The ID of the channel. - * - `params.message_id` - The ID of the user. - * - *   - * - * ### Usage Example - * ```js - * const { auth, v2 } = require('osu-api-extended'); - * - * async function main() { - * try { - * await auth.login({ - * type: 'lazer', - * login, - * password - * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) - * }); - * - * const result = await v2.chat.channels.actions({ - * type: 'send', - * - * id: 5, - * is_action: false, - * message: '.' - * }); - * // or - * const result = await v2.chat.channels.actions({ - * type: 'join', - * - * id: 6, - * user_id: 9893708, - * }); - * // or - * const result = await v2.chat.channels.actions({ - * type: 'leave', - * - * id: 6, - * user_id: 9893708, - * }); - * // or - * const result = await v2.chat.channels.actions({ - * type: 'readed', - * - * channel_id: 45145743, - * message_id: 3626657177, - * }); - * if (result.error != null) { - * console.log(result.error); - * return; - * }; - * - * console.log(result); - * } catch (error) { - * console.log(error); - * }; - * }; - * - * main(); - * ``` - * - *   - * - * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.chat.channels.actions_v3) - */ - actions: chat_channels_actions, }, /** * ### `GET [/v2/chat/channels/{channel}/messages](https://osu.ppy.sh/docs/index.html#get-channel-messages) diff --git a/types/v2/chat_channels_actions_join.ts b/types/v2/chat_actions_join.ts similarity index 87% rename from types/v2/chat_channels_actions_join.ts rename to types/v2/chat_actions_join.ts index 0da481eb..e3f925ed 100644 --- a/types/v2/chat_channels_actions_join.ts +++ b/types/v2/chat_actions_join.ts @@ -1,4 +1,4 @@ -export interface chatChannelsActionsJoinResponse { +export interface chatActionsJoinResponse { channel_id: number description: string icon: any diff --git a/types/v2/chat_channels_actions_send.ts b/types/v2/chat_actions_send.ts similarity index 89% rename from types/v2/chat_channels_actions_send.ts rename to types/v2/chat_actions_send.ts index ea29b963..3cf54495 100644 --- a/types/v2/chat_channels_actions_send.ts +++ b/types/v2/chat_actions_send.ts @@ -1,4 +1,4 @@ -export interface chatChannelsActionsSendResponse { +export interface chatActionsSendResponse { channel_id: number content: string is_action: boolean From 4550c7090b36a627b2fd25e4a7abd025f92c78c9 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 6 Oct 2024 20:04:36 +0300 Subject: [PATCH 252/259] move `channels.actions` to `chat.actions` --- api/v2/chat_actions.ts | 101 ++++++++++++++++++++++++++++++++ api/v2/chat_updates.ts | 20 ++++--- routes/v2.ts | 130 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 244 insertions(+), 7 deletions(-) diff --git a/api/v2/chat_actions.ts b/api/v2/chat_actions.ts index 01ba83cf..729760b9 100644 --- a/api/v2/chat_actions.ts +++ b/api/v2/chat_actions.ts @@ -3,6 +3,9 @@ import { IDefaultParams, IError } from "../../types"; import { ChatActionsNewResponse } from "../../types/v2/chat_actions_new"; import { ChatActionsKeepaliveResponse } from "../../types/v2/chat_actions_keepalive"; import { handleErrors } from "../../utility/handleErrors"; +import { chatActionsSendResponse } from "../../types/v2/chat_actions_send"; +import { chatActionsJoinResponse } from "../../types/v2/chat_actions_join"; +import { credentials } from "../../utility/auth"; type params = ({ @@ -14,6 +17,23 @@ type params = ({ message: string; uuid?: string; +} | { + type: 'send'; + + is_action: boolean; + + channel_id: number; + message: string; +} | { + type: 'join' | 'leave'; + + channel_id: number; + user_id: number; +} | { + type: 'read'; + + channel_id: number; + message_id: number; } | { type: 'keepalive'; @@ -25,12 +45,25 @@ type params = ({ type Response = T extends 'new' ? ChatActionsNewResponse & IError + : T extends 'send' + ? chatActionsSendResponse & IError + : T extends 'join' + ? chatActionsJoinResponse & IError + : T extends 'leave' + ? "" & IError + : T extends 'read' + ? "" & IError : T extends 'keepalive' ? ChatActionsKeepaliveResponse[] & IError : IError; export const chat_actions = async (params: T, addons?: IDefaultParams): Promise> => { + if (credentials.type != 'lazer' && credentials.type != 'cli') { + return handleErrors(new Error(`Login via lazer or cli to use this endpoint`)) as Response; + }; + + const object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; let method = 'POST'; @@ -38,6 +71,11 @@ export const chat_actions = async (params: T, addons?: IDefaul switch (params?.type) { case 'new': + if (credentials.type == 'cli' && !credentials.scopes.includes('chat.write')) { + return handleErrors(new Error(`Requires "chat.write" scope`)) as Response; + }; + + url += `/chat/new`; method = 'POST'; @@ -52,7 +90,70 @@ export const chat_actions = async (params: T, addons?: IDefaul if (params?.uuid) object['uuid'] = params.uuid; break; + case 'send': + if (credentials.type == 'cli' && !credentials.scopes.includes('chat.write')) { + return handleErrors(new Error(`Requires "chat.write" scope`)) as Response; + }; + + if (params?.channel_id == null || params?.message == null || params?.is_action == null) { + return handleErrors(new Error(`Missing required parameters`)) as Response; + }; + + + url += `/chat/channels/${params.channel_id}/messages`; + method = 'POST'; + + if (params?.message != null) object['message'] = params.message; + if (params?.is_action != null) object['is_action'] = params.is_action; + break; + + case 'join': + if (credentials.type == 'cli' && !credentials.scopes.includes('chat.write_manage')) { + return handleErrors(new Error(`Requires "chat.write_manage" scope`)) as Response; + }; + + if (params?.channel_id == null || params?.user_id == null) { + return handleErrors(new Error(`Missing required parameters`)) as Response; + }; + + + url += `/chat/channels/${params.channel_id}/users/${params.user_id}`; + method = 'PUT'; + break; + + case 'leave': + if (credentials.type == 'cli' && !credentials.scopes.includes('chat.write_manage')) { + return handleErrors(new Error(`Requires "chat.write_manage" scope`)) as Response; + }; + + if (params?.channel_id == null || params?.user_id == null) { + return handleErrors(new Error(`Missing required parameters`)) as Response; + }; + + + url += `/chat/channels/${params.channel_id}/users/${params.user_id}`; + method = 'DELETE'; + break; + + case 'read': + if (credentials.type == 'cli' && !credentials.scopes.includes('chat.read')) { + return handleErrors(new Error(`Requires "chat.read" scope`)) as Response; + }; + + if (params?.channel_id == null || params?.message_id == null) { + return handleErrors(new Error(`Missing required parameters`)) as Response; + }; + + + url += `/chat/channels/${params.channel_id}/mark-as-read/${params.message_id}`; + method = 'PUT'; + break; + case 'keepalive': + if (credentials.type == 'cli' && !credentials.scopes.includes('chat.write')) { + return handleErrors(new Error(`Requires "chat.read" scope`)) as Response; + }; + url += `/chat/ack`; method = 'POST'; diff --git a/api/v2/chat_updates.ts b/api/v2/chat_updates.ts index 7d033720..a20f562c 100644 --- a/api/v2/chat_updates.ts +++ b/api/v2/chat_updates.ts @@ -9,7 +9,7 @@ type Response = ChatUpdatesResponse & IError; export const chat_updates = async (params: { - after_id?: number; + after_id: number; includes?: ('presence' | 'silences' | 'messages')[]; history_since?: number; }, addons?: IDefaultParams): Promise => { @@ -17,18 +17,24 @@ export const chat_updates = async (params: { return handleErrors(new Error(`Login via lazer to use this endpoint`)) as Response }; + if (params?.after_id == null) { + return handleErrors(new Error(`Specify after_id`)) as Response + }; + + + const obj: any = {}; + if (params?.history_since) obj['history_since'] = params.history_since; + if (params?.includes) obj['includes[]'] = params.includes; + if (params?.after_id) obj['since'] = params.after_id; + const data = await request(`https://osu.ppy.sh/api/v2/chat/updates`, { method: 'GET', - params: { - 'history_since': params?.history_since, - 'includes[]': params?.includes, - 'since': params?.after_id, - }, + params: obj, addons, }); - if (data.error) return handleErrors(new Error(data.error)); + if (data.error) return handleErrors(new Error(data.error)); return data; }; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index fcd7c21a..a816c6ba 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -2491,6 +2491,136 @@ export const chat = { * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.chat.details_v3) | [Check return types](../types/v2/chat_details.ts) */ details: chat_details, + /** + * ### `POST` [/v2/chat/new](https://osu.ppy.sh/docs/index.html#create-new-pm) + * ### `POST` [/v2/chat/ack](https://osu.ppy.sh/docs/index.html#chat-keepalive) + * ### `POST` [/v2/chat/channels/{channel}/messages](https://osu.ppy.sh/docs/index.html#send-message-to-channel) + * ### `PUT` [/v2/chat/channels/{channel}/users/{user}](https://osu.ppy.sh/docs/index.html#join-channel) + * ### `DELETE` [/v2/chat/channels/{channel}/users/{user}](https://osu.ppy.sh/docs/index.html#leave-channel) + * ### `PUT` [/v2/chat/channels/{channel}/mark-as-read/{message}](https://osu.ppy.sh/docs/index.html#mark-channel-as-read) + * `async` Performs a set of actions on channels pr PM's. (Requires lazer or cli authentication) + * + *   + * + * ### Global Parameters + * - `params.type` - Type of action to perform. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Parameters for `params.type: 'new'` + * - `params.is_action` - Whether the message is an action + * - `params.user_id` - The ID of the user. + * - `params.message` - The message to send. + * - `params.uuid` - client-side message identifier which will be sent back in response and websocket json. + * + *   + * + * ### Parameters for `params.type: 'send'` + * - `params.id` - The ID of the channel to send to. + * - `params.message` - The message to send. + * - `params.is_action` - Whether the message is an action. + * + *   + * + * ### Parameters for `params.type: 'join' | 'leave'` + * - `params.id` - The ID of the channel. + * - `params.user_id` - The ID of the user. + * + *   + * + * ### Parameters for `params.type: 'read'` + * - `params.channel_id` - The ID of the channel. + * - `params.message_id` - The ID of the user. + * + *   + * + * ### Parameters for `params.type: 'keepalive'` + * - `params.history_since` - The ID of the message to return `UserSilences`. + * - `params.since` - The ID of the message to return `UserSilences`. + * + *   + * + * ### Usage Example + * ```js + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'lazer', + * login: login, + * password: password, + * cachedTokenPath: './lazer.json' // path to the file your auth token will be saved (to prevent osu!api spam) + * }); + * // or + * await auth.login({ + * type: 'cli', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * redirect_url: REDIRECT_URL, + * scopes: ['public', 'chat.read', 'chat.write', 'chat.write_manage'], + * cachedTokenPath: './cli.json' // path to a file where will be stored auth token to prevent spam auth to osu + * }); + * + * + * const result = await v2.chat.actions({ + * type: 'new', + * is_action: false, + * user_id: 2070907, + * message: 'hello', + * }); + * // or + * const result = await v2.chat.actions({ + * type: 'keepalive', + * since: 3769165698, + * }); + * // or + * const result = await v2.chat.actions({ + * type: 'send', + * + * channel_id: 24594482, + * is_action: false, + * message: '.' + * }); + * // or + * const result = await v2.chat.actions({ + * type: 'join', + * + * channel_id: 55, + * user_id: 9893708, // your id + * }); + * // or + * const result = await v2.chat.actions({ + * type: 'leave', + * + * channel_id: 55, + * user_id: 9893708, + * }); + * // or + * const result = await v2.chat.actions({ + * type: 'read', + * channel_id: 56888139, + * message_id: 3758748555, + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); + * ``` + * + *   + * + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.chat.channels.actions_v3) + */ actions: chat_actions, }; From 07196425b94a8db8471dc690a83b25c95735678a Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 6 Oct 2024 20:10:20 +0300 Subject: [PATCH 253/259] fix examples --- routes/v2.ts | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/routes/v2.ts b/routes/v2.ts index a816c6ba..b2f060f2 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -45,11 +45,17 @@ export const beatmaps = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.beatmaps.packs.list({ * type: 'loved' * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * * * console.log(result); * } catch (error) { @@ -87,9 +93,15 @@ export const beatmaps = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.beatmaps.packs.details('ST265'); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * * * console.log(result); * } catch (error) { @@ -154,6 +166,7 @@ export const beatmaps = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.beatmaps.lookup({ @@ -218,12 +231,17 @@ export const beatmaps = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.beatmaps.details({ * type: 'set', * id: 2182218 * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; * * * console.log(result); @@ -270,9 +288,15 @@ export const beatmaps = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.beatmaps.events.list({ types: ['approve'] }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * * * console.log(result); * } catch (error) { @@ -343,6 +367,11 @@ export const beatmaps = { * file_path: `./cache/${set_id}.osz`, * progress_log_fn: progress_update * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * * * console.log(result); * } catch (error) { @@ -393,9 +422,15 @@ export const beatmaps = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.beatmaps.discussions.list({ beatmapset_id: 2084849 }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * * * console.log(result); * } catch (error) { @@ -437,9 +472,15 @@ export const beatmaps = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.beatmaps.discussions.posts(); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * * * console.log(result); * } catch (error) { @@ -483,9 +524,15 @@ export const beatmaps = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.beatmaps.discussions.votes({ discussion_id: 4533908 }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * * * console.log(result); * } catch (error) { @@ -562,6 +609,11 @@ export const changelogs = { * type: 'lookup', * changelog: 'lazer' * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * * * console.log(result); * } catch (error) { @@ -699,7 +751,7 @@ export const comments = { * * async function main() { * try { - * const result = const result = await v2.comments.details(3035523); + * const result = await v2.comments.details(3035523); * if (result.error != null) { * console.log(result.error); * return; @@ -799,6 +851,7 @@ export const users = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.users.list({ @@ -848,6 +901,7 @@ export const users = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.users.kudosu({ id: 4830261 }); @@ -894,6 +948,7 @@ export const users = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.users.events() @@ -940,6 +995,7 @@ export const users = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.users.details({ user: 9893708, mode: 'osu', key: 'id' }); @@ -987,6 +1043,7 @@ export const users = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.users.beatmaps({ type: 'ranked', id: 4378277 }); @@ -1033,6 +1090,7 @@ export const users = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.users.activity({ id: 11367222 }); @@ -1123,6 +1181,7 @@ export const scores = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.scores.list({ @@ -1191,6 +1250,7 @@ export const scores = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.scores.details({ @@ -1309,6 +1369,7 @@ export const forums = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.forums.topics.details({ @@ -1497,6 +1558,7 @@ import { search_all } from '../api/v2/search'; * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.search({ @@ -1607,6 +1669,7 @@ export const assets = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.assets.dataFiles(); @@ -1666,6 +1729,7 @@ export const news = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.news.list(); @@ -1711,6 +1775,7 @@ export const news = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.news.details({ @@ -1890,6 +1955,7 @@ export const ranking = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.ranking.list({ @@ -1954,6 +2020,7 @@ export const spotlights = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.spotlights.list(); @@ -2154,6 +2221,7 @@ export const me = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.me.details(); @@ -2213,6 +2281,7 @@ export const matches = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.matches.list({ @@ -2260,6 +2329,7 @@ export const matches = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * await v2.matches.details({ match_id: 16155689 }); @@ -2325,6 +2395,7 @@ export const chat = { * type: 'v2', * client_id: CLIENT_ID, * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) * }); * * const result = await v2.chat.channels.list(); From 94f2701d7372cd86c3423b3e1055872ec86e29bf Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 6 Oct 2024 20:29:25 +0300 Subject: [PATCH 254/259] oops --- api/v2/{notification_actions.ts => notifications_actions.ts} | 2 +- routes/v2.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename api/v2/{notification_actions.ts => notifications_actions.ts} (93%) diff --git a/api/v2/notification_actions.ts b/api/v2/notifications_actions.ts similarity index 93% rename from api/v2/notification_actions.ts rename to api/v2/notifications_actions.ts index ca789bc2..34eb403d 100644 --- a/api/v2/notification_actions.ts +++ b/api/v2/notifications_actions.ts @@ -29,7 +29,7 @@ type Response = : IError; -export const notification_actions = async (params: T, addons?: IDefaultParams): Promise => { +export const notifications_actions = async (params: T, addons?: IDefaultParams): Promise => { const object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; let method = 'GET'; diff --git a/routes/v2.ts b/routes/v2.ts index b2f060f2..6ce0571d 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -1807,7 +1807,7 @@ export const news = { import { notifications_list } from '../api/v2/notifications_list'; -import { notification_actions } from '../api/v2/notification_actions'; +import { notifications_actions } from '../api/v2/notifications_actions'; /** @@ -1891,7 +1891,7 @@ export const notifications = { * * [See documentation](https://osu.ppy.sh/docs/index.html#mark-notifications-as-read) */ - actions: notification_actions, + actions: notifications_actions, }; From 5dfa689fa3466af9088ee7544710d82fce51a2e1 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 6 Oct 2024 20:38:42 +0300 Subject: [PATCH 255/259] added example to `comments.actions` --- api/v2/comments_actions.ts | 6 +++++ routes/v2.ts | 54 +++++++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/api/v2/comments_actions.ts b/api/v2/comments_actions.ts index e8c7b30c..281aabe4 100644 --- a/api/v2/comments_actions.ts +++ b/api/v2/comments_actions.ts @@ -6,6 +6,7 @@ import { CommentsActionsDeleteResponse } from "../../types/v2/comments_actions_d import { CommentsActionsVoteResponse } from "../../types/v2/comments_actions_vote"; import { CommentsActionsUnvoteResponse } from "../../types/v2/comments_actions_unvote"; import { handleErrors } from "../../utility/handleErrors"; +import { credentials } from "../../utility/auth"; type params = ({ @@ -51,6 +52,11 @@ type Response = export const comments_actions = async (params: T, addons?: IDefaultParams): Promise | { error: string }> => { + if (credentials.type != 'lazer') { + return handleErrors(new Error(`Login via lazer to use this endpoint`)) as Response; + }; + + const object: any = {}; let url = 'https://osu.ppy.sh/api/v2'; let method = 'POST'; diff --git a/routes/v2.ts b/routes/v2.ts index 6ce0571d..1a3ff5bc 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -804,7 +804,59 @@ export const comments = { * * ### Usage Example * ```js - * // TBA + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'lazer', + * login: login, + * password: password, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) + * }); + * + * const result = await v2.comments.actions({ + * type: 'new', + * + * commentable_type: 'beatmapset', + * id: 1378401, + * message: 'hello from api' + * }); + * // or + * const result = await v2.comments.actions({ + * type: 'edit', + * + * id: 3058002, + * message: 'hello from api (edited)' + * }); + * // or + * const result = await v2.comments.actions({ + * type: 'vote', + * id: 3058002, + * }); + * // or + * const result = await v2.comments.actions({ + * type: 'unvote', + * id: 3058002, + * }); + * // or + * const result = await v2.comments.actions({ + * type: 'delete', + * id: 3058002, + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); * ``` * *   From 0abee78f908cda5099642a5192e5783b1a3a2986 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 6 Oct 2024 21:38:27 +0300 Subject: [PATCH 256/259] add send to announce, but i dont have permissions to test it --- api/v2/chat_actions.ts | 48 ++++++++++++++++++++++++++++++++++++++---- routes/v2.ts | 42 ++++++++++++++++++++++++------------ 2 files changed, 73 insertions(+), 17 deletions(-) diff --git a/api/v2/chat_actions.ts b/api/v2/chat_actions.ts index 729760b9..ebdf2653 100644 --- a/api/v2/chat_actions.ts +++ b/api/v2/chat_actions.ts @@ -9,7 +9,7 @@ import { credentials } from "../../utility/auth"; type params = ({ - type: 'new'; + type: 'send_pm'; is_action: boolean; @@ -18,12 +18,20 @@ type params = ({ uuid?: string; } | { - type: 'send'; + type: 'send_channel'; is_action: boolean; channel_id: number; message: string; +} | { + type: 'send_announce'; + + users_ids: number[]; + message: string; + + channel_name: string; + channel_description: string; } | { type: 'join' | 'leave'; @@ -70,7 +78,7 @@ export const chat_actions = async (params: T, addons?: IDefaul switch (params?.type) { - case 'new': + case 'send_pm': if (credentials.type == 'cli' && !credentials.scopes.includes('chat.write')) { return handleErrors(new Error(`Requires "chat.write" scope`)) as Response; }; @@ -90,7 +98,7 @@ export const chat_actions = async (params: T, addons?: IDefaul if (params?.uuid) object['uuid'] = params.uuid; break; - case 'send': + case 'send_channel': if (credentials.type == 'cli' && !credentials.scopes.includes('chat.write')) { return handleErrors(new Error(`Requires "chat.write" scope`)) as Response; }; @@ -107,6 +115,38 @@ export const chat_actions = async (params: T, addons?: IDefaul if (params?.is_action != null) object['is_action'] = params.is_action; break; + case 'send_announce': + if (credentials.type == 'cli' && !credentials.scopes.includes('chat.write_manage')) { + return handleErrors(new Error(`Requires "chat.write_manage" scope`)) as Response; + }; + + if (!Array.isArray(params?.users_ids)) { + return handleErrors(new Error(`User ids should be array`)) as Response; + }; + + if (params?.channel_name == null) { + return handleErrors(new Error(`Specify channel_name`)) as Response; + }; + + if (params?.message == null) { + return handleErrors(new Error(`Specify message`)) as Response; + }; + + + url += `/chat/channels`; + method = 'POST'; + + object['type'] = 'ANNOUNCE'; + + object['target_ids'] = params.users_ids; + object['message'] = params.message; + + object['channel'] = {}; + + object['channel']['name'] = params.channel_name; + object['channel']['description'] = params.channel_description; + break; + case 'join': if (credentials.type == 'cli' && !credentials.scopes.includes('chat.write_manage')) { return handleErrors(new Error(`Requires "chat.write_manage" scope`)) as Response; diff --git a/routes/v2.ts b/routes/v2.ts index 1a3ff5bc..1b7d4461 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -2631,7 +2631,7 @@ export const chat = { * *   * - * ### Parameters for `params.type: 'new'` + * ### Parameters for `params.type: 'send_pm'` * - `params.is_action` - Whether the message is an action * - `params.user_id` - The ID of the user. * - `params.message` - The message to send. @@ -2639,13 +2639,21 @@ export const chat = { * *   * - * ### Parameters for `params.type: 'send'` - * - `params.id` - The ID of the channel to send to. + * ### Parameters for `params.type: 'send_channel'` + * - `params.id` - The IDs of the channel to send to. * - `params.message` - The message to send. * - `params.is_action` - Whether the message is an action. * *   * + * ### Parameters for `params.type: 'send_announce'` + * - `params.users_ids[]` - The IDs of the users. + * - `params.message` - The message to send. + * - `params.channel_name` - Channel name. + * - `params.channel_description` - Description of the channel. + * + *   + * * ### Parameters for `params.type: 'join' | 'leave'` * - `params.id` - The ID of the channel. * - `params.user_id` - The ID of the user. @@ -2688,30 +2696,34 @@ export const chat = { * * * const result = await v2.chat.actions({ - * type: 'new', + * type: 'send_pm', * is_action: false, * user_id: 2070907, - * message: 'hello', + * message: '/np', * }); * // or * const result = await v2.chat.actions({ - * type: 'keepalive', - * since: 3769165698, + * type: 'send_channel', + * + * is_action: false, + * channel_id: 24594482, + * message: '.' * }); * // or * const result = await v2.chat.actions({ - * type: 'send', + * type: 'send_announce', * - * channel_id: 24594482, - * is_action: false, - * message: '.' + * ids: [17063658], + * channel_name: 'test api', + * channel_description: 'a description for test', + * message: 'hello, testing api lib' * }); * // or * const result = await v2.chat.actions({ * type: 'join', * * channel_id: 55, - * user_id: 9893708, // your id + * user_id: 9893708, * }); * // or * const result = await v2.chat.actions({ @@ -2724,7 +2736,11 @@ export const chat = { * const result = await v2.chat.actions({ * type: 'read', * channel_id: 56888139, - * message_id: 3758748555, + * }); + * // or + * const result = await v2.chat.actions({ + * type: 'keepalive', + * since: 3769165698, * }); * if (result.error != null) { * console.log(result.error); From 4a155c0b4745696a6a8c5ef351bb8ebff818f6d2 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 6 Oct 2024 21:42:41 +0300 Subject: [PATCH 257/259] docs --- routes/v2.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/routes/v2.ts b/routes/v2.ts index 1b7d4461..a69f2261 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -2617,6 +2617,7 @@ export const chat = { /** * ### `POST` [/v2/chat/new](https://osu.ppy.sh/docs/index.html#create-new-pm) * ### `POST` [/v2/chat/ack](https://osu.ppy.sh/docs/index.html#chat-keepalive) + * ### `POST` [/v2/chat/channels](https://osu.ppy.sh/docs/index.html#create-channel) * ### `POST` [/v2/chat/channels/{channel}/messages](https://osu.ppy.sh/docs/index.html#send-message-to-channel) * ### `PUT` [/v2/chat/channels/{channel}/users/{user}](https://osu.ppy.sh/docs/index.html#join-channel) * ### `DELETE` [/v2/chat/channels/{channel}/users/{user}](https://osu.ppy.sh/docs/index.html#leave-channel) From b3697a75533e1d74af6b8535dac73f8c5ce51c78 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 6 Oct 2024 21:58:07 +0300 Subject: [PATCH 258/259] new route `users.lookup` --- api/v2/users_list.ts | 2 +- api/v2/users_lookup.ts | 33 +++++++++++++++++++++++++++ routes/v2.ts | 48 ++++++++++++++++++++++++++++++++++++++++ types/v2/users_lookup.ts | 41 ++++++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 api/v2/users_lookup.ts create mode 100644 types/v2/users_lookup.ts diff --git a/api/v2/users_list.ts b/api/v2/users_list.ts index 076e1ad1..b64696ee 100644 --- a/api/v2/users_list.ts +++ b/api/v2/users_list.ts @@ -14,7 +14,7 @@ export const users_list = async (params: { ids: number[], include_variants?: boo if (params.ids.length > 50) { return handleErrors(new Error("No more than 50 users can be requested at once.")) as Response; - } + }; const data = await request(`https://osu.ppy.sh/api/v2/users`, { method: 'GET', diff --git a/api/v2/users_lookup.ts b/api/v2/users_lookup.ts new file mode 100644 index 00000000..6e3c4f67 --- /dev/null +++ b/api/v2/users_lookup.ts @@ -0,0 +1,33 @@ +import { IDefaultParams, IError } from "../../types"; +import { UsersLookupResponse } from "../../types/v2/users_lookup"; +import { handleErrors } from "../../utility/handleErrors"; +import { request } from "../../utility/request"; + + +type Response = UsersLookupResponse[] & IError; + + +export const users_lookup = async (params: { + ids: (string | number)[]; +}, addons?: IDefaultParams): Promise => { + if ((params?.ids || [])?.length == 0) { + return handleErrors(new Error(`Specify at least one user id`)) as Response; + }; + + if (params.ids.length > 50) { + return handleErrors(new Error("No more than 50 users can be requested at once.")) as Response; + }; + + + const data = await request(`https://osu.ppy.sh/api/v2/users/lookup`, { + method: 'GET', + params: { + 'ids[]': params.ids, + }, + addons, + }); + + + if (data.error) return handleErrors(new Error(data.error)); + return data; +}; \ No newline at end of file diff --git a/routes/v2.ts b/routes/v2.ts index a69f2261..62a51b6b 100644 --- a/routes/v2.ts +++ b/routes/v2.ts @@ -870,6 +870,7 @@ export const comments = { import { users_list } from "../api/v2/users_list"; +import { users_lookup } from "../api/v2/users_lookup"; import { users_events } from "../api/v2/users_events"; import { users_details } from "../api/v2/users_details"; import { users_activity } from "../api/v2/users_activity"; @@ -929,6 +930,53 @@ export const users = { * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.users.list_v3) | [Check return types](../types/v2/users_list.ts) */ list: users_list, + /** + * ### `GET` [/v2/users/lookup](https://osu.ppy.sh/docs/index.html#get-apiv2userslookup) + * `async` Retrieves a list of users by their id or name. + * + *   + * + * ### Parameters + * - `params.ids` - List of user ids or names to retrieve. + * - `addons?` - Additional parameters to include in the request. + * + *   + * + * ### Usage Example + * ```js + * const { auth, v2 } = require('osu-api-extended'); + * + * async function main() { + * try { + * await auth.login({ + * type: 'v2', + * client_id: CLIENT_ID, + * client_secret: CLIENT_SECRET, + * cachedTokenPath: './test.json' // path to the file your auth token will be saved (to prevent osu!api spam) + * }); + * + * const result = await v2.users.lookup({ + * ids: [2, 8928855, 7562902, 'mrekk', 'whitecat'], + * }); + * if (result.error != null) { + * console.log(result.error); + * return; + * }; + * + * console.log(result); + * } catch (error) { + * console.log(error); + * }; + * }; + * + * main(); + * ``` + * + *   + * + * [See documentation](https://github.com/cyperdark/osu-api-extended/wiki/v2.users.lookup_v3) | [Check return types](../types/v2/users_list.ts) + */ + lookup: users_lookup, /** * ### `GET` [/v2/users/{user}/kudosu](https://osu.ppy.sh/docs/index.html#get-user-kudosu) * `async` Retrieves the kudosu history of a given user. diff --git a/types/v2/users_lookup.ts b/types/v2/users_lookup.ts new file mode 100644 index 00000000..036a0aaa --- /dev/null +++ b/types/v2/users_lookup.ts @@ -0,0 +1,41 @@ +export interface UsersLookupResponse { + avatar_url: string + country_code: string + default_group: string + id: number + is_active: boolean + is_bot: boolean + is_deleted: boolean + is_online: boolean + is_supporter: boolean + last_visit: string + pm_friends_only: boolean + profile_colour?: string + username: string + country: Country + cover: Cover + groups: Group[] +} + +export interface Country { + code: string + name: string +} + +export interface Cover { + custom_url: string + url: string + id?: string +} + +export interface Group { + colour: string + has_listing: boolean + has_playmodes: boolean + id: number + identifier: string + is_probationary: boolean + name: string + short_name: string + playmodes: any +} From 57729839aa6e5bd80d748a41a251a9eea008fcb5 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 6 Oct 2024 22:00:29 +0300 Subject: [PATCH 259/259] v3 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 399c8fe8..0e031fbe 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "osu-api-extended", - "version": "3.0.0-beta.38", - "description": "Advanced osu! api wrapper for v1 and v2, with extra stuff", + "version": "3.0.0", + "description": "Advanced osu! api wrapper cover all V2 and V1 endpoints, and provide useful tools", "main": "dist/index.js", "types": "dist/index.d.ts", "files": [