osu-api-extended
Version:
Advanced osu! api wrapper cover all V2 and V1 endpoints, and provide useful tools
562 lines • 24.7 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
System.register("types/index", [], function (exports_1, context_1) {
"use strict";
var __moduleName = context_1 && context_1.id;
return {
setters: [],
execute: function () {
;
}
};
});
System.register("utility/request", ["querystring", "https", "utility/auth"], function (exports_2, context_2) {
"use strict";
var querystring_1, https_1, auth, total_retries, sanitize_query, request;
var __moduleName = context_2 && context_2.id;
return {
setters: [
function (querystring_1_1) {
querystring_1 = querystring_1_1;
},
function (https_1_1) {
https_1 = https_1_1;
},
function (auth_1) {
auth = auth_1;
}
],
execute: function () {
;
// VALUES
total_retries = 0;
sanitize_query = (obj) => {
const object = 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_1.default.encode(object);
};
exports_2("request", request = (url, { method, headers, data, params = {}, addons = {} }) => new Promise((resolve, reject) => {
// check required args
if (url == null) {
return resolve({ error: 'URL not specified', });
}
;
if (method == null) {
return resolve({ 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 = addons.authKey || auth.cache.v1;
if (params.k == null) {
return resolve({ error: 'v1 api key not specified', });
}
;
}
;
// V2 add credentials
if (url.includes('https://osu.ppy.sh/api/v2')) {
if (!headers)
headers = {};
headers.Authorization = `Bearer ${addons.authKey || auth.cache.v2}`;
if (!headers.Accept)
headers.Accept = `application/json`;
if (!headers['Content-Type'])
headers['Content-Type'] = `application/json`;
if (addons.apiVersion != '')
headers['x-api-version'] = addons.apiVersion || '20240130';
if ((addons.authKey || auth.cache.v2) == null) {
return resolve({ error: 'v2 not authorized' });
}
;
}
;
if (addons.legacy_only != null)
params.legacy_only = addons.legacy_only == true ? 1 : 0;
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
const req = https_1.default.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)
.catch(reject);
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
const chunks = [];
// handle response events
response.on('data', (chunk) => chunks.push(chunk));
response.on('end', () => __awaiter(void 0, void 0, void 0, function* () {
const data = Buffer.concat(chunks).toString();
if (/^application\/json/.test(response.headers['content-type'] || '')) {
try {
const parse = JSON.parse(data);
if (parse.authentication === 'basic' && total_retries < 3 && addons.ignoreSessionRefresh != true) {
total_retries++;
const refresh = yield auth.refresh_token();
if (refresh == null) {
return resolve({ error: 'Cannot refresh session, double check your credentials (or report to package author)' });
}
;
const retry_request = yield request(url, { method, headers, data, params });
return resolve(retry_request);
}
;
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)` });
}
;
return resolve({ error: parse.error });
}
;
if (parse.authentication === 'basic') {
return resolve({ error: 'Unauthorized (double check credentials)' });
}
;
total_retries = 0;
return resolve(parse);
}
catch (error) {
return resolve({ error: error.name });
}
;
}
;
resolve(data);
}));
});
// send error
req.on('error', (error) => {
resolve({ error: error.name });
});
// timeout
req.setTimeout(addons.timeout_ms || auth.settings.timeout, () => {
req.destroy();
resolve({ error: `Request to ${build_url} time out after ${addons.timeout_ms || auth.settings.timeout}ms` });
});
// write body to request, if specified
if (data)
req.write(data);
req.end();
}));
}
};
});
System.register("types/v2/users_details", [], function (exports_3, context_3) {
"use strict";
var __moduleName = context_3 && context_3.id;
return {
setters: [],
execute: function () {
}
};
});
System.register("utility/handleErrors", ["utility/auth"], function (exports_4, context_4) {
"use strict";
var auth_2, handleErrors;
var __moduleName = context_4 && context_4.id;
return {
setters: [
function (auth_2_1) {
auth_2 = auth_2_1;
}
],
execute: function () {
exports_4("handleErrors", handleErrors = (error) => {
if (auth_2.settings.throwErrors) {
throw error;
}
;
return { error };
});
}
};
});
System.register("utility/auth", ["utility/request", "utility/handleErrors"], function (exports_5, context_5) {
"use strict";
var request_1, handleErrors_1, settings, credentials, cache, login, set_v2, refresh_token, client_login;
var __moduleName = context_5 && context_5.id;
return {
setters: [
function (request_1_1) {
request_1 = request_1_1;
},
function (handleErrors_1_1) {
handleErrors_1 = handleErrors_1_1;
}
],
execute: function () {
exports_5("settings", settings = {
timeout: 60000,
throwErrors: true,
});
exports_5("credentials", credentials = {
type: '',
api_key: '',
client_id: '',
client_secret: '',
login: '',
password: '',
redirect_url: '',
state: '',
cachedTokenPath: '',
scopes: ['public'],
});
exports_5("cache", cache = {
v1: '',
v2: '',
'ratelimit-remaining': 1200,
'ratelimit-limit': 1200,
});
exports_5("login", login = (params) => {
credentials.type = 'v2';
if (params.timeout)
settings.timeout = params.timeout;
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']);
});
exports_5("set_v2", set_v2 = (token) => cache.v2 = token);
exports_5("refresh_token", refresh_token = () => __awaiter(void 0, void 0, void 0, function* () {
const refresh = yield login(credentials);
return refresh;
}));
client_login = (client_id, client_secret, scopes) => __awaiter(void 0, void 0, void 0, function* () {
const response = yield request_1.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: client_id,
client_secret: client_secret,
scope: scopes.join(' '),
code: 'code',
})
});
if (response.error)
return handleErrors_1.handleErrors(new Error(response.error));
cache.v2 = response.access_token;
return response;
});
}
};
});
System.register("types/v2/beatmaps_lookup_difficulty", [], function (exports_6, context_6) {
"use strict";
var __moduleName = context_6 && context_6.id;
return {
setters: [],
execute: function () {
}
};
});
System.register("api/v2/beatmaps_lookup", ["utility/request", "utility/handleErrors"], function (exports_7, context_7) {
"use strict";
var request_2, handleErrors_2, beatmaps_lookup;
var __moduleName = context_7 && context_7.id;
return {
setters: [
function (request_2_1) {
request_2 = request_2_1;
},
function (handleErrors_2_1) {
handleErrors_2 = handleErrors_2_1;
}
],
execute: function () {
exports_7("beatmaps_lookup", beatmaps_lookup = (params, addons) => __awaiter(void 0, void 0, void 0, function* () {
const object = {};
let url = 'https://osu.ppy.sh/api/v2';
let method = 'GET';
switch (params.type) {
case 'difficulty':
url += '/beatmaps/lookup';
if (params.id == null && params.checksum == null && params.filename == null) {
return handleErrors_2.handleErrors(new Error(`Specify at least one parameter`));
}
;
object.id = params.id;
object.checksum = params.checksum;
object.filename = params.filename;
break;
default:
return handleErrors_2.handleErrors(new Error(`Unsupported type: ${params.type}`));
}
;
const data = yield request_2.request(url, {
method: method,
params: object,
addons,
});
if (data.error)
return handleErrors_2.handleErrors(new Error(data.error));
return data;
}));
}
};
});
System.register("api/v2/users_details", ["utility/handleErrors", "utility/request"], function (exports_8, context_8) {
"use strict";
var handleErrors_3, request_3, users_details;
var __moduleName = context_8 && context_8.id;
return {
setters: [
function (handleErrors_3_1) {
handleErrors_3 = handleErrors_3_1;
},
function (request_3_1) {
request_3 = request_3_1;
}
],
execute: function () {
exports_8("users_details", users_details = (params, addons) => __awaiter(void 0, void 0, void 0, function* () {
if ((params === null || params === void 0 ? void 0 : params.user) == null) {
return handleErrors_3.handleErrors(new Error('Specify user id or name'));
}
;
let key = params === null || params === void 0 ? void 0 : params.key;
if (key == 'username')
key = '@';
const data = yield request_3.request(`https://osu.ppy.sh/api/v2/users/${params.user}${params.mode ? `/${params.mode}` : ''}`, {
method: 'GET',
params: { key: key },
addons,
});
if (data.error)
return handleErrors_3.handleErrors(new Error(data.error));
return data;
}));
}
};
});
System.register("routes/v2", ["api/v2/beatmaps_lookup", "api/v2/users_details"], function (exports_9, context_9) {
"use strict";
var beatmaps_lookup_1, beatmaps, users_details_1, users;
var __moduleName = context_9 && context_9.id;
return {
setters: [
function (beatmaps_lookup_1_1) {
beatmaps_lookup_1 = beatmaps_lookup_1_1;
},
function (users_details_1_1) {
users_details_1 = users_details_1_1;
}
],
execute: function () {
/**
* ##### Description
* Object containing methods for retrieving beatmaps data.
*/
exports_9("beatmaps", beatmaps = {
/**
* ### `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.
*
*
*
* ### 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
* 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.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();
* ```
*
*
*
* [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_1.beatmaps_lookup,
});
/**
* ##### Description
* Covers API Endpoints regarding users.
*/
exports_9("users", users = {
/**
* ### `GET` [/v2/users/{user}/{mode?}](https://osu.ppy.sh/docs/index.html#get-user)
* `async` Retrieves a user by given parameters.
*
*
*
* ### 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
* 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.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();
* ```
*
*
*
* [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_1.users_details,
});
}
};
});
System.register("index", ["utility/auth", "routes/v2", "types/v2/beatmaps_lookup_difficulty", "types/v2/users_details"], function (exports_10, context_10) {
"use strict";
var __moduleName = context_10 && context_10.id;
return {
setters: [
function (auth_3) {
exports_10("auth", auth_3);
},
function (v2_1) {
exports_10("v2", v2_1);
},
function (v2_beatmaps_lookup_difficulty_1) {
exports_10("v2_beatmaps_lookup_difficulty", v2_beatmaps_lookup_difficulty_1);
},
function (v2_users_details_1) {
exports_10("v2_users_details", v2_users_details_1);
}
],
execute: function () {
}
};
});
System.register("types/mods", [], function (exports_11, context_11) {
"use strict";
var __moduleName = context_11 && context_11.id;
return {
setters: [],
execute: function () {
}
};
});
//# sourceMappingURL=bundle.js.map