Skip to content

Commit

Permalink
Merge pull request #79 from GreepTheSheep/develop
Browse files Browse the repository at this point in the history
3.0.5
  • Loading branch information
GreepTheSheep authored Jan 12, 2022
2 parents 86b06dd + dcece9a commit 342ee94
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 33 deletions.
5 changes: 4 additions & 1 deletion docs/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,7 @@
path: ../../examples/playerCOTD.md
- name: Current official campaign
id: currentCampaign
path: ../../examples/officialCampaign.md
path: ../../examples/officialCampaign.md
- name: Gracefully catch errors
id: errorCatches
path: ../../examples/errorCatches.md
70 changes: 70 additions & 0 deletions examples/errorCatches.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
## Gracefully catches errors

Every error is sent trough a `throw`, meaning that errors is handeled with a `.catch()` block or in a try/catch way.

Most errors can come from an API block.

Every requests is managed with a Promise, so you need to handle that with async/await or with a `.then()` block

### Example with main request

```js
const TMIO = require('trackmania.io'),
client = new TMIO.Client();

client.campaigns.currentSeason().then(async campaign=>{
console.log('The actual official campaign is', campaign.name);
console.log('The image URL of this campaign is:', campaign.image);

try {
// Here, we try to execute another request, but in a async way
// so we need to use try/catch

console.log('Top 10 of this campaign:');
const leaderboard = await campaign.leaderboard();
leaderboard.forEach(top=>{
console.log(top.position, top.playerName, "with", top.points, "points");
});
} catch (err) {
// Here, an script or API error is throwed
console.error(err);

// Mostly, if it's an API block, you'll have this message:
// "You are blocked from the API. Please get in touch with @Miss#8888 on Discord: https://openplanet.nl/link/discord - or DM me on Twitter: https://twitter.com/codecatt -- For more information on third-party API usage, see the following page: https://openplanet.nl/tmio/api"
}
}).catch(err=>{
// An error, sadge
// Meanwhile, this is the same as a try/catch

console.error(err);
})
```

### Example with side requests

Side requests is requests made to another domain than trackmania.io (trackmania.exchange for example), this does not throws a error but emit an "error" Event.

Error events is not a big deal than main errors

To catch them, you just need to add a `client.on("error", error=>...)` block

```js
const TMIO = require('trackmania.io'),
client = new TMIO.Client();

client.maps.get("89OtLgP9IRQzmC9n_h0SrIr8l_4").then(map=>{
console.log(map.name);
}).catch(err=>{
// Here, we got a tm.io error, because it's the main thing after all

console.error(err);
});

client.on("error", error=>{
// But here, errors can come from another services for the map info
// Trackmania Exchange for example

console.error(error);
});

```
4 changes: 2 additions & 2 deletions examples/officialCampaign.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
const TMIO = require('trackmania.io'),
client = new TMIO.Client();

client.campaigns.currentSeason().then(campaign=>{
client.campaigns.currentSeason().then(async campaign=>{
console.log('The actual official campaign is', campaign.name);
console.log('The image URL of this campaign is:', campaign.image);

console.log('Top 10 of this campaign:');
const leaderboard = await campaign.leaderboard();
leaderboard.forEach(top=>{
console.log(top.position, top.playerName, "with", top.points, "points")
console.log(top.position, top.playerName, "with", top.points, "points");
});
});

Expand Down
2 changes: 1 addition & 1 deletion examples/playerCOTD.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ client.players.get("26d9a7de-4067-4926-9d93-2fe62cd869fc").then(async player=>{
${player.name}'s COTD stats:
${cotd.count} Cup Of The Day played,
${cotd.stats.totalDivWins} wins in any division,
${cotd.stats.averageDivRank * 100}% average rank,
${(cotd.stats.averageDivRank * 100).toFixed(2)}% average rank,
The best division in overall was Div ${cotd.stats.bestOverall.division},
The best division in primary COTD was Div ${cotd.stats.bestPrimary.division},
`);
Expand Down
18 changes: 9 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "trackmania.io",
"version": "3.0.4",
"version": "3.0.5",
"description": "Node.js inplementation of Trackmania Live services (trackmania.io)",
"main": "src/index.js",
"types": "typings/index.d.ts",
Expand All @@ -26,7 +26,7 @@
"homepage": "https://tmio.greep.gq/",
"dependencies": {
"events": "3.3.0",
"luxon": "^2.2.0",
"luxon": "^2.3.0",
"node-fetch": "2.6.1"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion src/client/Client.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,5 +151,5 @@ module.exports = Client;
/**
* Emitted when there is an error when fetching external data (Trackmania.exchange for example).
* @event Client#error
* @param {Error} error The error
* @param {string} error The error
*/
23 changes: 13 additions & 10 deletions src/rest/APIRequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,20 +94,23 @@ class APIRequest {
* @param {Response} response The response received from the API
*/
this.client.emit('apiResponse', this, response);
// Save the rate limit details
if (this.url.startsWith(new ReqUtil(this.client).tmioAPIURL)){
this.client.ratelimit = {
ratelimit: Number(response.headers.raw()['x-ratelimit-limit'][0]),
remaining: Number(response.headers.raw()['x-ratelimit-remaining'][0]),
reset: new Date(Number(response.headers.raw()['x-ratelimit-reset'][0]) * 1000)
};
}

if (response.status >= 200 && response.status < 300) {
// Save the rate limit details
if (this.url.startsWith(new ReqUtil(this.client).tmioAPIURL)){
this.client.ratelimit = {
ratelimit: Number(response.headers.raw()['x-ratelimit-limit'][0]),
remaining: Number(response.headers.raw()['x-ratelimit-remaining'][0]),
reset: new Date(Number(response.headers.raw()['x-ratelimit-reset'][0]) * 1000)
};
}

return await response.json();
} else {
if (response.status == 500) {
if (response.status >= 500) {
const json = await response.json();
throw json.error;
if (json.error) throw json.error;
else throw json;
} else throw response.statusText;
}
})
Expand Down
17 changes: 17 additions & 0 deletions src/structures/Campaign.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,23 @@ class Campaign {
return this._data.leaderboarduid;
}

/**
* Get the number of maps in the campaign.
* @type {number}
*/
get mapCount() {
return this._data.playlist.length;
}

/**
* Get a specific map of the campaign.
* @param {number} index The index of the map.
* @returns {Promise<TMMap>}
*/
async map(index) {
return await this.client.maps.get(this._data.playlist[index].mapUid);
}

/**
* The list of maps in the campaign.
* @returns {Promise<Array<TMMap>>}
Expand Down
2 changes: 1 addition & 1 deletion src/structures/TMMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class TMMap {
* @type {string}
*/
get storageId() {
return this.thumbnail.replace(/^[a-z:/.]*([^]*)\.[a-z]*$/gi, '$1');
return this.thumbnail.replace(/^[a-z:/.]*\/([^]*)\.[a-z]*$$/gi, '$1');
}

/**
Expand Down
17 changes: 11 additions & 6 deletions src/util/defaultOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,17 @@ class defaultOptionsAPI {
*/
this.paths = new defaultOptionsAPIPaths();

/**
* The default User Agent to use.
* @type {?string}
*/
this.useragent = null;

if (!this.useragent && 'TMIO_UA' in process.env) {
/**
* The default User Agent to use.
* If present, this defaults to `process.env.TMIO_UA` when instantiating the client
* @type {?string}
*/
this.useragent = process.env.TMIO_UA;
} else {
this.useragent = null;
}

if (!this.key && 'TMIO_API' in process.env) {
/**
* The API Key to use. It must contains "yourname:theactualsecretkey".
Expand Down
11 changes: 11 additions & 0 deletions typings/structures/Campaign.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,17 @@ declare class Campaign {
* @type {string}
*/
get leaderboardId(): string;
/**
* Get the number of maps in the campaign.
* @type {number}
*/
get mapCount(): number;
/**
* Get a specific map of the campaign.
* @param {number} index The index of the map.
* @returns {Promise<TMMap>}
*/
map(index: number): Promise<TMMap>;
/**
* The list of maps in the campaign.
* @returns {Promise<Array<TMMap>>}
Expand Down
1 change: 1 addition & 0 deletions typings/util/defaultOptions.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ declare class defaultOptionsAPI {
paths: defaultOptionsAPIPaths;
/**
* The default User Agent to use.
* If present, this defaults to `process.env.TMIO_UA` when instantiating the client
* @type {?string}
*/
useragent: string | null;
Expand Down

0 comments on commit 342ee94

Please sign in to comment.