1 | # Riot Lol API
|
2 |
|
3 | This module lets you query the Riot API for LeagueOfLegends data.
|
4 |
|
5 | You'll need a developer key from https://developer.riotgames.com.
|
6 |
|
7 | This module was developed for people that need to poll the Riot API with a *very high* throughput (with peaks above the standard production rate limit of 300 calls / second / region).
|
8 |
|
9 | If you don't need this kind of performance, you'll probably be better with other modules -- have a look at [lol-js](https://www.npmjs.com/package/lol-js) for instance :)
|
10 |
|
11 | ## Installation
|
12 | ```
|
13 | npm install --save riot-lol-api
|
14 | ```
|
15 |
|
16 | ## Usage
|
17 | ```js
|
18 | var RiotRequest = require('riot-lol-api');
|
19 |
|
20 | var riotRequest = new RiotRequest('my_api_key');
|
21 |
|
22 | // 'summoner' is a string to identify the method being used currently
|
23 | // See note about rate-limiting in the README.
|
24 | // Also see https://developer.riotgames.com/rate-limiting.html#method-headers
|
25 | riotRequest.request('euw1', 'summoner', '/lol/summoner/v3/summoners/by-name/graphistos', function(err, data) {});
|
26 | ```
|
27 |
|
28 | The library will take care of rate limiting and automatically retry on 500 and 503.
|
29 |
|
30 | It will also maintain a very high request concurrency, dynamically updating concurrency to ensure you remain a good citizen and don't get blacklisted.
|
31 |
|
32 | Ensure that your network adapter can deal with the traffic!
|
33 | If necessary, you can distribute the library across multiple servers -- I'm currently using it with a production key distributed on 4 servers sending > 35 millions calls a day.
|
34 |
|
35 | ## Caching
|
36 | The second argument in the constructor lets you define a cache object. This object should expose two keys, `get` and `set`. The default implementation does no caching:
|
37 |
|
38 | ```js
|
39 | var cache = {
|
40 | get: function(region, endpoint, cb) {
|
41 | // Try to read from cache,
|
42 | // Return cb(null, data) if data is already available in your cache.
|
43 | // If it's a cache-miss, you still need to call cb(null, null) for the request to proceed.
|
44 | // Do not just call cb(null)!
|
45 | cb(null, null);
|
46 | },
|
47 | set: function(region, endpoint, cacheStrategy, data) {
|
48 | // Use this function to store `data`, which is the result of the API call to `endpoint` on `region`.
|
49 | }
|
50 | };
|
51 | ```
|
52 |
|
53 | `cacheStrategy` is a value over which you have total control when you call `.request()`:
|
54 |
|
55 |
|
56 | ```js
|
57 | riotRequest.request('euw1', 'summoner', '/lol/summoner/v3/summoners/by-name/graphistos', YOUR_CACHE_STRATEGY, function(err, data) {});
|
58 | ```
|
59 |
|
60 | When unspecified, `cacheStrategy` will default to `false`, and cache won't be used.
|
61 | If the value is not falsy, the cache will be used and the value will be forwarded to you (in your `.set` cache method). The most common use case would be to send how long you want to store the data in cache, but this is completely up to you.
|
62 |
|
63 | You may want to use a package like `lru-cache` to help you with caching -- note that you can plug any system you want (Redis, Riak, file system), just ensure you call `cb(null, data)`. If you send an error in the first argument, the library will forward this error directly to the callback specified in `.request()`.
|
64 |
|
65 | You'll notice that the `set()` function has no callback, this is intentional. You can start async operations from here, but the system won't wait for your operation to complete before moving on to other requests.
|
66 |
|
67 | In some situations, the `get()` function might be called more than once per endpoint. For performance, when a request is queued, it is checked instantly if it's in cache: if it isn't, it's added in a queue, and when the worker start that task he will ask the cache again in case the same request was already queued and has since then been cached.
|
68 |
|
69 | ## Rate limiting
|
70 | The Riot API rate limiting is complex -- see https://developer.riotgames.com/rate-limiting.html for all the nitty gritty.
|
71 |
|
72 | This library abstracts most of it away, automatically reading the headers values and adjusting this behavior to ensure your key doesn't get blacklisted.
|
73 |
|
74 | However, when you call `.request`, you need to specifiy a string to identify the method currently being used.
|
75 |
|
76 | A list of all the buckets is available in https://developer.riotgames.com/rate-limiting.html#method-headers, but the TL;DR is that for every type of request you send, you should have some kind of tag: for instance, all requests for recent games can be tagged with "recent-games" (the second parameter to `.request(region, tag, endpoint)`. `riot-lol-api` will then ensure that all rate limits (both for the app and for the method) are respected per region.
|
77 |
|
78 | If the above paragraph didn't make any sense, go and check out the official Riot link above and then come back to this section ;)
|
79 |
|
80 | Here is a sample code excerpt:
|
81 |
|
82 | ```js
|
83 | riotRequest.request('euw1', 'summoner', '/lol/summoner/v3/summoners/by-name/graphistos', function(err, data) {});
|
84 | riotRequest.request('euw1', 'champion-mastery', '/lol/champion-mastery/v3/champion-masteries/by-summoner/4203456', function(err, data) {});
|
85 | riotRequest.request('euw1', 'league', '/lol/league/v3/positions/by-summoner/4203456', function(err, data) {});
|
86 | ```
|
87 |
|
88 | ## Logging
|
89 | The library use `debug` for logging. To see logs, set this environment variable: `DEBUG=riot-lol-api:*`.
|
90 |
|
91 | ## Errors
|
92 | Errors when trying to read the cache are forwarded directly to the requester.
|
93 |
|
94 | HTTP errrors on the Riot API side will expose three properties:
|
95 |
|
96 | * `.statusCode` containing the return code from the API (the most common one is 503. Note that the library is retrying by default all 5XX errors, so if you see it in your code it means that the error happened twice)
|
97 | * `riotInternal` a flag set to true to help you distinguish network errors (fairly common) from more standard errors (e.g. from your cache)
|
98 | * `extra`, an object exposing details about the request: endpoint, region, status code, whether the failure is due to a timeout... You may want to send this object directly to you error monitoring system.
|
99 |
|
100 | Please remember that the library will automatically retry once when it receives a 500 and 503.
|
101 |
|
102 | ## Dealing with regions and platforms
|
103 | For convenience, the library exposes a function `getPlatformFromRegion()` that takes a region as parameter (e.g "euw") and returns the associaed platform to use with the Riot API ("EUW1"). This can be useful for building URLs.
|
104 |
|
105 | Additionally, there is also a `.REGIONS` property with an array of all valid Riot regions lowercased.
|
106 |
|
107 | ## Advanced topics
|
108 | Honestly, skip this section if you're using the library for the first time. I started using this option past 20 million calls a day...
|
109 |
|
110 | ### Throttler
|
111 | Use case: throttle some process to ensure other processes always have enough requests available. For example, let's say you have a worker downloading games in the background, and you also have a frontend that can request games from the API in realtime to answer user requests. You always want the frontend to be able to request in realtime, but by default it's very likely your worker will use all capacity every 10s.
|
112 | To prevent this, the library expose a function named `setThrottler(platform, method, throttle)` (and `setThrottler(method, throttle)` which is automatically applied to all platforms).
|
113 |
|
114 | For this particular use case, in your worker, you'd call `setThrottler('match', 100)` (replace `match` with the method name you use to qualify the request type when you call `.request()`). The library will then try to reserve 100 requests for other use (for instance, assuming you can do 250 calls per second, the worker will consume around 150 requests, leaving 100 requests for other processes). Exact count isn't guaranteed, but the closer you get to the specified limit, the smaller the concurrency will be (down to a minimum of 1).
|